123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- // a simple recognizer, produces no useful value
- ometa L {
- number = digit+,
- addExpr = addExpr '+' mulExpr
- | addExpr '-' mulExpr
- | mulExpr,
- mulExpr = mulExpr '*' primExpr
- | mulExpr '/' primExpr
- | primExpr,
- primExpr = '(' expr ')'
- | number,
- expr = addExpr
- }
- L.matchAll('6*(4+3)', 'expr')
- // a recognizer that also interprets
- ometa Calc {
- digit = ^digit:d -> d.digitValue(),
- number = number:n digit:d -> (n * 10 + d)
- | digit,
- addExpr = addExpr:x '+' mulExpr:y -> (x + y)
- | addExpr:x '-' mulExpr:y -> (x - y)
- | mulExpr,
- mulExpr = mulExpr:x '*' primExpr:y -> (x * y)
- | mulExpr:x '/' primExpr:y -> (x / y)
- | primExpr,
- primExpr = '(' expr:x ')' -> x
- | number,
- expr = addExpr
- }
- Calc.matchAll('6**(4+3)', 'expr')
- // parser and simple interpreter combo
- ometa CalcParser {
- digit = ^digit:d -> d.digitValue(),
- number = number:n digit:d -> (n * 10 + d)
- | digit,
- addExpr = addExpr:x '+' mulExpr:y -> ['add', x, y]
- | addExpr:x '-' mulExpr:y -> ['sub', x, y]
- | mulExpr,
- mulExpr = mulExpr:x '*' primExpr:y -> ['mul', x, y]
- | mulExpr:x '/' primExpr:y -> ['div', x, y]
- | primExpr,
- primExpr = '(' expr:x ')' -> x
- | number:n -> ['num', n],
- expr = addExpr
- }
- tree = CalcParser.matchAll('6*(4+3)', 'expr')
- ometa CalcInterpreter {
- interp = ['num' anything:x] -> x
- | ['add' interp:x interp:y] -> (x + y)
- | ['sub' interp:x interp:y] -> (x - y)
- | ['mul' interp:x interp:y] -> (x * y)
- | ['div' interp:x interp:y] -> (x / y)
- }
- CalcInterpreter.match(tree, 'interp')
- // we can write a "compiler" instead
- ometa CalcCompiler {
- comp = ['num' anything:x] -> x.toString()
- | ['add' comp:x comp:y] -> ('(' + x + '+' + y + ')')
- | ['sub' comp:x comp:y] -> ('(' + x + '-' + y + ')')
- | ['mul' comp:x comp:y] -> ('(' + x + '*' + y + ')')
- | ['div' comp:x comp:y] -> ('(' + x + '/' + y + ')')
- }
- code = CalcCompiler.match(tree, 'comp')
- eval(code)
-
- // spice things up with ML-like syntax
- ometa CalcCompiler {
- comp ['num' anything:x] -> x.toString(),
- comp ['add' comp:x comp:y] -> ('(' + x + '+' + y + ')'),
- comp ['sub' comp:x comp:y] -> ('(' + x + '-' + y + ')'),
- comp ['mul' comp:x comp:y] -> ('(' + x + '*' + y + ')'),
- comp ['div' comp:x comp:y] -> ('(' + x + '/' + y + ')')
- }
- code = CalcCompiler.match(tree, 'comp')
- eval(code)
-
- // a neat trick: dispatch on node tags using higher-order rule "apply"
- ometa CalcCompiler {
- comp [anything:t apply(t):ans] -> ans,
- num anything:x -> x.toString(),
- add comp:x comp:y -> ('(' + x + '+' + y + ')'),
- sub comp:x comp:y -> ('(' + x + '-' + y + ')'),
- mul comp:x comp:y -> ('(' + x + '*' + y + ')'),
- div comp:x comp:y -> ('(' + x + '/' + y + ')')
- }
- code = CalcCompiler.match(tree, 'comp')
- eval(code)
|