tpegs.nim 3.9 KB

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