毕设专用git仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.1 KiB

// 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)