vote up 1 vote down star

So why is this not working? I'm creating a regex that will match a formula (which is then part of a larger standard description). But I'm stuck here, as it doesn't appear to want to match embedded formulas within a formula.

stat        = /(Stat3|Stat2|Stat1)/

number_sym  = /[0-9]*/
formula_sym = /((target's )?#{stat}|#{number_sym}|N#{number_sym})\%?/
math_sym    = /(\+|\-|\*|\/|\%)/

formula     = /^\((#{formula}|#{formula_sym})( #{math_sym} (#{formula}|#{formula_sym}))?\)$/

p "(target's Stat2 * N1%)".match(formula).to_s #matches
p "((target's Stat2 * N1%) + 3)".match(formula).to_s #no match
p "(Stat1 + ((target's Stat2 * N1%) + 3))".match(formula).to_s #no match
flag

3 Answers

vote up 1 vote down check

When you use the #{ } syntax, Ruby converts the Regexp object to a string using to_s. Look what happens when you convert a Regexp object to a string:

irb> re = /blah/
  => /blah/
irb> re.to_s
  => "(?-mix:blah)"
irb> "my regex: #{re}"
  => "my regex: (?-mix:blah)"
irb> /my regex: #{re}/
  => /my regex: (?-mix:blah)/

To get the string you want (in my example, "blah"), use the Regexp#source method:

irb> re.source
"blah"

So to use your example:

formula_sym = /((target's )?#{stat.source}|#{number_sym.source}|N#{number_sym.source})\%?/
link|flag
thanks ... and I did discover why it wasn't working ... guess I should have phrased my question as "how can I get it working" .... looks like #{formula.source} showed that formula was still nil. – Reed Debaets Apr 15 at 18:53
vote up 1 vote down

Bear in mind: using a regex against a math formula is not recommended. Validating a formula is usually not at all possible.

Depending on your application: you should use or write a parser...

That said, there is a post on matching parens HERE

link|flag
yes ... i was just thinking it may be easier to use regex considering how I have my standard description currently defined. – Reed Debaets Apr 15 at 18:54
This doesn't work with ruby. Ruby regexen don't have recursion. – sepp2k Apr 15 at 18:55
vote up 1 vote down

You can't use recursion like that: the #{formula}s in your definition of formula are converted into empty strings. What you want is beyond regular expression's ability -- regular expressions cannot even match nested parentheses. I suspect you will need an actual parser to do what you want. Check out treetop, for example.

link|flag
excellent ... treetop will allow me to migrate my current definition spec into it easily. Thanks! – Reed Debaets Apr 15 at 19:12

Your Answer

Get an OpenID
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.