// Make a parser that eaves symbols unchanged ometa CalcParser2 <: Parser { fromTo :x :y = seq(x) (~seq(y) char)* seq(y), space = super(#space) | fromTo('//', '\n') | fromTo('/*', '*/'), nameFirst = letter | '$' | '_', nameRest = nameFirst | digit, symbol = firstAndRest(`nameFirst, `nameRest):r -> r.join(''), digit = super(#digit):d -> d.digitValue(), number = number:n digit:d -> (n * 10 + d) | digit, addExpr = addExpr:x '+' mulExpr:y -> [`Plus, x, y] | addExpr:x '-' mulExpr:y -> [`Plus, x, [`Times, -1, y]] | mulExpr, mulExpr = mulExpr:x '*' primExpr:y -> [`Times, x, y] | mulExpr:x '/' primExpr:y -> [`Times, x, [`Power, y, -1]] | primExpr, primExpr = '(' expr:x ')' -> x | symbol:s -> s | number:n -> [`Number, n], expr = addExpr } // Works as expected CalcParser2.matchAll('xy2', 'primExpr') CalcParser2.matchAll('2', 'primExpr') CalcParser2.matchAll('6*(4+3)', 'expr') CalcParser2.matchAll('6*(4-3)', 'expr') CalcParser2.matchAll('6*(x+y)', 'expr') CalcParser2.matchAll('x+0', 'expr') // Try to normalize, using rules like x+0 = 0 ometa CalcNormalizer { anumber = [`Number anything:x], normalize = [`Plus anything:x [`Number 0]] -> x | [`Plus anything:x anything:x] -> [`Times, 2, x], normalizedistributive = [`Plus [`Times anumber:a anything:x] [`Times anumber:b anything:x]] -> [`Times, [`Plus, a, b], x] | anything:x -> x } tree = CalcParser2.matchAll('x+0', 'expr') CalcNormalizer.match(tree, 'normalize') tree = CalcParser2.matchAll('x+x', 'expr') CalcNormalizer.match(tree, 'normalize') tree = CalcParser2.matchAll('2*x+3*x', 'expr') CalcNormalizer.match(tree, 'normalizedistributive') tree = CalcParser2.matchAll('2*x+a*x', 'expr') CalcNormalizer.match(tree, 'normalizedistributive') // Hmmm... tree = CalcParser2.matchAll('2*(x+y)+3*(x+y+z)', 'expr') CalcNormalizer.match(tree, 'normalizedistributive')