bs-ometa-optimizer.txt 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // TODO: turn off the "seq" inliner when G.seq !== OMeta.seq (will require some refactoring)
  2. // TODO: add a factorizing optimization (will make jumptables more useful)
  3. ometa BSNullOptimization {
  4. setHelped = !(this._didSomething = true),
  5. helped = ?this._didSomething,
  6. trans = [:t ?(this[t] != undefined) apply(t):ans] -> ans,
  7. optimize = trans:x helped -> x,
  8. App :rule anything*:args -> ['App', rule].concat(args),
  9. Act :expr -> ['Act', expr],
  10. Pred :expr -> ['Pred', expr],
  11. Or trans*:xs -> ['Or'].concat(xs),
  12. XOr trans*:xs -> ['XOr'].concat(xs),
  13. And trans*:xs -> ['And'].concat(xs),
  14. Opt trans:x -> ['Opt', x],
  15. Many trans:x -> ['Many', x],
  16. Many1 trans:x -> ['Many1', x],
  17. Set :n trans:v -> ['Set', n, v],
  18. Not trans:x -> ['Not', x],
  19. Lookahead trans:x -> ['Lookahead', x],
  20. Form trans:x -> ['Form', x],
  21. ConsBy trans:x -> ['ConsBy', x],
  22. IdxConsBy trans:x -> ['IdxConsBy', x],
  23. JumpTable ([:c trans:e] -> [c, e])*:ces -> ['JumpTable'].concat(ces),
  24. Interleave ([:m trans:p] -> [m, p])*:xs -> ['Interleave'].concat(xs),
  25. Rule :name :ls trans:body -> ['Rule', name, ls, body]
  26. }
  27. BSNullOptimization.initialize = function() { this._didSomething = false }
  28. ometa BSAssociativeOptimization <: BSNullOptimization {
  29. And trans:x end setHelped -> x,
  30. And transInside('And'):xs -> ['And'].concat(xs),
  31. Or trans:x end setHelped -> x,
  32. Or transInside('Or'):xs -> ['Or'].concat(xs),
  33. XOr trans:x end setHelped -> x,
  34. XOr transInside('XOr'):xs -> ['XOr'].concat(xs),
  35. transInside :t = [exactly(t) transInside(t):xs] transInside(t):ys setHelped -> xs.concat(ys)
  36. | trans:x transInside(t):xs -> [x].concat(xs)
  37. | -> []
  38. }
  39. ometa BSSeqInliner <: BSNullOptimization {
  40. App = 'seq' :s end seqString(s):cs setHelped -> ['And'].concat(cs).concat([['Act', s]])
  41. | :rule anything*:args -> ['App', rule].concat(args),
  42. inlineChar = BSOMetaParser.eChar:c ~end -> ['App', 'exactly', c.toProgramString()],
  43. seqString = &(:s ?(typeof s === 'string'))
  44. ( ['"' inlineChar*:cs '"' ] -> cs
  45. | ['\'' inlineChar*:cs '\''] -> cs
  46. )
  47. }
  48. JumpTable = function(choiceOp, choice) {
  49. this.choiceOp = choiceOp
  50. this.choices = {}
  51. this.add(choice)
  52. }
  53. JumpTable.prototype.add = function(choice) {
  54. var c = choice[0], t = choice[1]
  55. if (this.choices[c]) {
  56. if (this.choices[c][0] == this.choiceOp)
  57. this.choices[c].push(t)
  58. else
  59. this.choices[c] = [this.choiceOp, this.choices[c], t]
  60. }
  61. else
  62. this.choices[c] = t
  63. }
  64. JumpTable.prototype.toTree = function() {
  65. var r = ['JumpTable'], choiceKeys = ownPropertyNames(this.choices)
  66. for (var i = 0; i < choiceKeys.length; i += 1)
  67. r.push([choiceKeys[i], this.choices[choiceKeys[i]]])
  68. return r
  69. }
  70. ometa BSJumpTableOptimization <: BSNullOptimization {
  71. Or (jtChoices('Or') | trans)*:cs -> ['Or'].concat(cs),
  72. XOr (jtChoices('XOr') | trans)*:cs -> ['XOr'].concat(cs),
  73. quotedString = &string [ '"' (BSOMetaParser.eChar:c ~end -> c)*:cs '"'
  74. | '\'' (BSOMetaParser.eChar:c ~end -> c)*:cs '\''] -> cs.join(''),
  75. jtChoice = ['And' ['App' 'exactly' quotedString:x] anything*:rest] -> [x, ['And'].concat(rest)]
  76. | ['App' 'exactly' quotedString:x] -> [x, ['Act', x.toProgramString()]],
  77. jtChoices :op = jtChoice:c {new JumpTable(op, c)}:jt (jtChoice:c {jt.add(c)})* setHelped -> jt.toTree()
  78. }
  79. ometa BSOMetaOptimizer {
  80. optimizeGrammar = ['Grammar' :n :sn optimizeRule*:rs] -> ['Grammar', n, sn].concat(rs),
  81. optimizeRule = :r (BSSeqInliner.optimize(r):r | empty)
  82. ( BSAssociativeOptimization.optimize(r):r
  83. | BSJumpTableOptimization.optimize(r):r
  84. )* -> r
  85. }