Rsec is a dynamic parser generator for Ruby 1.9.


gem in rsec


Here's a simple arithmetic example:

require "rsec"
include Rsec::Helpers
def arithmetic

  # evaluate binary arithmetic series
  # Apply this procedure to the lists of terms and factors generated in term and expr
  calculate = proc do |(p, *ps)|
    ps.each_slice(2).inject(p) do |left, (op, right)|
      left.send op, right

  # `num` is a primitive of type double;
  # if recognition fails, the token should be reported as "number"
  num    = prim(:double).fail 'number'

  # `paren` is a left parenthesis, followed by an expr, followed by a right parenthesis.
  # The left parenthesis is treated as a token (.r);
  # this is necessary for the token to be processed by rsec.
  # The >> and << operators ignore the value of the delimiters they adjoin:
  # the value of the expression is `expr`.
  # lazy is used to deal with the forward reference of `expr`, which has not been defined yet.
  paren  = '('.r >> lazy{expr} << ')'

  factor = num | paren

  # `term` is a sequence of factors, delimited with one of the delimites */%,
  # optionally separated by space (one_of_).
  # The value of the expression is derived by applying the method calc
  # to the list generated by join (map).
  term   = factor.join(one_of_('*/%').fail 'operator').map &calculate

  expr   = term.join(one_of_('+-').fail 'operator').map &calculate

  # The root non-terminal symbol, assigned to the arithmetic parser, is `expr`;
  # it can only be followed by End-Of-File.
  arithmetic = expr.eof

# test it!
print '1+ 2*4 = '
p arithmetic.parse! '1+ 2*4' #=> 9
print '1+ 2*/4 = '
p arithmetic.parse! '1+ 2*/4' #=> should raise syntax error


Hosted on github.