tpegs.nim 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. discard """
  2. output: '''
  3. PEG AST traversal output
  4. ------------------------
  5. pkNonTerminal: Sum @(2, 3)
  6. pkSequence: (Product (('+' / '-') Product)*)
  7. pkNonTerminal: Product @(3, 7)
  8. pkSequence: (Value (('*' / '/') Value)*)
  9. pkNonTerminal: Value @(4, 5)
  10. pkOrderedChoice: (([0-9] [0-9]*) / ('(' Expr ')'))
  11. pkSequence: ([0-9] [0-9]*)
  12. pkCharChoice: [0-9]
  13. pkGreedyRepSet: [0-9]*
  14. pkSequence: ('(' Expr ')')
  15. pkChar: '('
  16. pkNonTerminal: Expr @(1, 4)
  17. pkNonTerminal: Sum @(2, 3)
  18. pkChar: ')'
  19. pkGreedyRep: (('*' / '/') Value)*
  20. pkSequence: (('*' / '/') Value)
  21. pkOrderedChoice: ('*' / '/')
  22. pkChar: '*'
  23. pkChar: '/'
  24. pkNonTerminal: Value @(4, 5)
  25. pkGreedyRep: (('+' / '-') Product)*
  26. pkSequence: (('+' / '-') Product)
  27. pkOrderedChoice: ('+' / '-')
  28. pkChar: '+'
  29. pkChar: '-'
  30. pkNonTerminal: Product @(3, 7)
  31. Event parser output
  32. -------------------
  33. @[5.0]
  34. +
  35. @[5.0, 3.0]
  36. @[8.0]
  37. /
  38. @[8.0, 2.0]
  39. @[4.0]
  40. -
  41. @[4.0, 7.0]
  42. -*
  43. @[4.0, 7.0, 22.0]
  44. @[4.0, 154.0]
  45. -
  46. @[-150.0]
  47. '''
  48. """
  49. import strutils, streams
  50. import pegs
  51. const
  52. indent = " "
  53. let
  54. pegAst = """
  55. Expr <- Sum
  56. Sum <- Product (('+' / '-')Product)*
  57. Product <- Value (('*' / '/')Value)*
  58. Value <- [0-9]+ / '(' Expr ')'
  59. """.peg
  60. txt = "(5+3)/2-7*22"
  61. block:
  62. var
  63. outp = newStringStream()
  64. processed: seq[string] = @[]
  65. proc prt(outp: Stream, kind: PegKind, s: string; level: int = 0) =
  66. outp.writeLine indent.repeat(level) & "$1: $2" % [$kind, s]
  67. proc recLoop(p: Peg, level: int = 0) =
  68. case p.kind
  69. of pkEmpty..pkWhitespace:
  70. discard
  71. of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle:
  72. outp.prt(p.kind, $p, level)
  73. of pkChar, pkGreedyRepChar:
  74. outp.prt(p.kind, $p, level)
  75. of pkCharChoice, pkGreedyRepSet:
  76. outp.prt(p.kind, $p, level)
  77. of pkNonTerminal:
  78. outp.prt(p.kind,
  79. "$1 @($3, $4)" % [p.nt.name, $p.nt.rule.kind, $p.nt.line, $p.nt.col], level)
  80. if not(p.nt.name in processed):
  81. processed.add p.nt.name
  82. p.nt.rule.recLoop level+1
  83. of pkBackRef..pkBackRefIgnoreStyle:
  84. outp.prt(p.kind, $p, level)
  85. else:
  86. outp.prt(p.kind, $p, level)
  87. for s in items(p):
  88. s.recLoop level+1
  89. pegAst.recLoop
  90. echo "PEG AST traversal output"
  91. echo "------------------------"
  92. echo outp.data
  93. block:
  94. var
  95. pStack: seq[string] = @[]
  96. valStack: seq[float] = @[]
  97. opStack = ""
  98. let
  99. parseArithExpr = pegAst.eventParser:
  100. pkNonTerminal:
  101. enter:
  102. pStack.add p.nt.name
  103. leave:
  104. pStack.setLen pStack.high
  105. if length > 0:
  106. let matchStr = s.substr(start, start+length-1)
  107. case p.nt.name
  108. of "Value":
  109. try:
  110. valStack.add matchStr.parseFloat
  111. echo valStack
  112. except ValueError:
  113. discard
  114. of "Sum", "Product":
  115. try:
  116. let val = matchStr.parseFloat
  117. except ValueError:
  118. if valStack.len > 1 and opStack.len > 0:
  119. valStack[^2] = case opStack[^1]
  120. of '+': valStack[^2] + valStack[^1]
  121. of '-': valStack[^2] - valStack[^1]
  122. of '*': valStack[^2] * valStack[^1]
  123. else: valStack[^2] / valStack[^1]
  124. valStack.setLen valStack.high
  125. echo valStack
  126. opStack.setLen opStack.high
  127. echo opStack
  128. pkChar:
  129. leave:
  130. if length == 1 and "Value" != pStack[^1]:
  131. let matchChar = s[start]
  132. opStack.add matchChar
  133. echo opStack
  134. echo "Event parser output"
  135. echo "-------------------"
  136. let pLen = parseArithExpr(txt)
  137. assert txt.len == pLen