title: R: create a list of admissible names from a string
body: <p>I am building a shiny app where users will enter text in a textInput box, something like this:</p>
  
  <pre><code>str &lt;- "1.1* max(a,b) * e* exp(1) * (sqrt(abs(x_1)))^(x2y) * min(maxy) * (b2^2)/sqrt(pi) /alpha + betax - gamma"
  </code></pre>
  
  <p>The text is a mathematical expression involving </p>
  
  <ul>
  <li>real numbers: 1.1, 2</li>
  <li>known mathematical constants: e, pi, gamma</li>
  <li>known mathematical functions: max(), exp(), sqrt(), abs(), min()</li>
  <li>variable names: a, b, x_1, x2y, maxy, b2, alpha, betax</li>
  <li>arithmetic operators: +, -, *, /, ^</li>
  <li>separators and similar: ( , ) .</li>
  </ul>
  
  <p>In addition to pre-defined constants such as gamma, I will also construct a list of "forbidden" names, such as 'digits' or 'base', because they may appear as arguments to some of the mathematical functions.</p>
  
  <p>My purpose is to extract from the expression all the valid variable names, and store them in a list: </p>
  
  <pre><code>(a, b, x_1, x2y, maxy, b2, alpha, betax)
  </code></pre>
  
  <p>or perhaps</p>
  
  <pre><code>("a", "b", "x_1", "x2y", "maxy", "b2", "alpha", "betax")
  </code></pre>
  
  <p>I have been able to deal with the situation where only single letters are admissible as variable names, the case where variable names contain only letters and are always separated by space, but I have not been able to deal with the situation described. </p>
  
  <p>For what it's worth, here's my best shot:</p>
  
  <pre><code># multi-gsub-to-1
  mgsub21 &lt;- function(pattern, replacement, x, ...) {
    for (i in 1:length(pattern)) {
      x &lt;- gsub(pattern[i], replacement, x, ...)
    }
    x
  }
  
  ops &lt;- list("\\+","\\-","\\*","\\/","\\^",",","\\(","\\)","\\.")
  math &lt;- list("log","logb","log10","log2","exp","sqrt"
    ,"cos","sin","tan","acos","asin","atan","atan2","cosh","sinh","tanh","acosh","asinh","atanh"
    ,"max","min","round","floor","ceiling","trunc","sign","abs","mean","median","mode","base","digits") 
  cst &lt;- list("pi","Pi","e","gamma")
  pattern &lt;- unlist(list(ops,cst,math))
  replacement &lt;- " "
  str2 &lt;- mgsub21(pattern,replacement,str)
  str2
  #  [1] "1 1    a b        xp 1         x_1     x2y       y     b2 2        alpha   b tax    "
  str2 &lt;- gsub("[0-9]+", " ", str2)
  str2 &lt;- gsub(" {2,}", " ", str2)
  str2
  #  [1] " a b xp x_ x y y b alpha b tax "
  </code></pre>
  
  <p>Problems with the above include:</p>
  
  <ul>
  <li>betax becomes b tax after I remove e</li>
  <li>exp(1) becomes xp 1 after I remove e</li>
  <li>maxy becomes y after I remove max</li>
  <li>does not deal with variables containing numbers</li>
  </ul>
  
  <p>I get:</p>
  
  <pre><code>a b xp x_ x y alpha tax
  </code></pre>
  
  <p>Expected answer is: </p>
  
  <pre><code>a b x_1 x2y maxy b2 alpha betax
  </code></pre>
  
  <p>Suggestions welcome, thanks!</p>