OMeta_Tutorial.txt 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // a simple recognizer, produces no useful value
  2. ometa L {
  3. number = digit+,
  4. addExpr = addExpr '+' mulExpr
  5. | addExpr '-' mulExpr
  6. | mulExpr,
  7. mulExpr = mulExpr '*' primExpr
  8. | mulExpr '/' primExpr
  9. | primExpr,
  10. primExpr = '(' expr ')'
  11. | number,
  12. expr = addExpr
  13. }
  14. L.matchAll('6*(4+3)', 'expr')
  15. // a recognizer that also interprets
  16. ometa Calc {
  17. digit = ^digit:d -> d.digitValue(),
  18. number = number:n digit:d -> (n * 10 + d)
  19. | digit,
  20. addExpr = addExpr:x '+' mulExpr:y -> (x + y)
  21. | addExpr:x '-' mulExpr:y -> (x - y)
  22. | mulExpr,
  23. mulExpr = mulExpr:x '*' primExpr:y -> (x * y)
  24. | mulExpr:x '/' primExpr:y -> (x / y)
  25. | primExpr,
  26. primExpr = '(' expr:x ')' -> x
  27. | number,
  28. expr = addExpr
  29. }
  30. Calc.matchAll('6**(4+3)', 'expr')
  31. // parser and simple interpreter combo
  32. ometa CalcParser {
  33. digit = ^digit:d -> d.digitValue(),
  34. number = number:n digit:d -> (n * 10 + d)
  35. | digit,
  36. addExpr = addExpr:x '+' mulExpr:y -> ['add', x, y]
  37. | addExpr:x '-' mulExpr:y -> ['sub', x, y]
  38. | mulExpr,
  39. mulExpr = mulExpr:x '*' primExpr:y -> ['mul', x, y]
  40. | mulExpr:x '/' primExpr:y -> ['div', x, y]
  41. | primExpr,
  42. primExpr = '(' expr:x ')' -> x
  43. | number:n -> ['num', n],
  44. expr = addExpr
  45. }
  46. tree = CalcParser.matchAll('6*(4+3)', 'expr')
  47. ometa CalcInterpreter {
  48. interp = ['num' anything:x] -> x
  49. | ['add' interp:x interp:y] -> (x + y)
  50. | ['sub' interp:x interp:y] -> (x - y)
  51. | ['mul' interp:x interp:y] -> (x * y)
  52. | ['div' interp:x interp:y] -> (x / y)
  53. }
  54. CalcInterpreter.match(tree, 'interp')
  55. // we can write a "compiler" instead
  56. ometa CalcCompiler {
  57. comp = ['num' anything:x] -> x.toString()
  58. | ['add' comp:x comp:y] -> ('(' + x + '+' + y + ')')
  59. | ['sub' comp:x comp:y] -> ('(' + x + '-' + y + ')')
  60. | ['mul' comp:x comp:y] -> ('(' + x + '*' + y + ')')
  61. | ['div' comp:x comp:y] -> ('(' + x + '/' + y + ')')
  62. }
  63. code = CalcCompiler.match(tree, 'comp')
  64. eval(code)
  65. // spice things up with ML-like syntax
  66. ometa CalcCompiler {
  67. comp ['num' anything:x] -> x.toString(),
  68. comp ['add' comp:x comp:y] -> ('(' + x + '+' + y + ')'),
  69. comp ['sub' comp:x comp:y] -> ('(' + x + '-' + y + ')'),
  70. comp ['mul' comp:x comp:y] -> ('(' + x + '*' + y + ')'),
  71. comp ['div' comp:x comp:y] -> ('(' + x + '/' + y + ')')
  72. }
  73. code = CalcCompiler.match(tree, 'comp')
  74. eval(code)
  75. // a neat trick: dispatch on node tags using higher-order rule "apply"
  76. ometa CalcCompiler {
  77. comp [anything:t apply(t):ans] -> ans,
  78. num anything:x -> x.toString(),
  79. add comp:x comp:y -> ('(' + x + '+' + y + ')'),
  80. sub comp:x comp:y -> ('(' + x + '-' + y + ')'),
  81. mul comp:x comp:y -> ('(' + x + '*' + y + ')'),
  82. div comp:x comp:y -> ('(' + x + '/' + y + ')')
  83. }
  84. code = CalcCompiler.match(tree, 'comp')
  85. eval(code)