Playing with Ohm
This world is meant to make it easy to experiment with Alex's Ohm. When you change the text in the workspaces, comments starting with // => are automatically re-evaluated. For the Ohm syntax you get inline annotations in case of errors.
Ohm Workspace
X

Menu
Arithmetic {
  Expr
    = AddExpr
  AddExpr
    = AddExpr '+' MulExpr  -- plus
    | AddExpr '-' MulExpr  -- minus
    | MulExpr
  MulExpr
    = MulExpr '*' PriExpr  -- times
    | MulExpr '/' PriExpr  -- divide
    | PriExpr
  PriExpr
    = '(' Expr ')'  -- paren
    | '+' PriExpr   -- pos
    | '-' PriExpr   -- neg
    | ident
    | number
  ident  -- identifier
    = letter alnum*
  number  -- number
    = digit+ ('.' digit*)?  -- integerAndFract
    | '.' digit+            -- onlyFract
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
depth: 1
reset
Ohm Tester
X

Menu
show vars
/*global Arithmetic*/
var calc = Arithmetic.synthesizedAttribute({
  AddExpr_plus:   function(x_y) { return calc(x) + calc(y) - 2; },
  AddExpr_minus:  function(x_y) { return calc(x) - calc(y); },
  MulExpr_times:  function(x_y) { return calc(x) * calc(y); },
  MulExpr_divide: function(x_y) { return calc(x) / calc(y); },
  PriExpr_paren:  function(_e_) { return calc(e); },
  PriExpr_pos:    function(_e)    { return calc(e); },
  PriExpr_neg:    function(_e)    { return calc(-e); },
  ident:          function(__)    { return constants[this.interval.contents]; },
  number:         function(_)       { return parseFloat(this.interval.contents); }
});
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
apply(calc, parse(Arithmetic, '3 + 4', 'Expr')); // => 5
var constants = {x: 4};
apply(calc, parse(Arithmetic, '(3 + x) / 2', 'Expr')); // => 2.5
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX