summary refs log tree commit diff stats
path: root/tests/stdlib
diff options
context:
space:
mode:
authorgemath <33119724+gemath@users.noreply.github.com>2018-08-24 20:13:37 +0200
committerAndreas Rumpf <rumpf_a@web.de>2018-08-24 20:13:37 +0200
commitf26ed1d540c154efa67e8d427c492069719c5159 (patch)
tree64db80a4fab203d0a56c6157a915691ea077dd7e /tests/stdlib
parentd5e1d102df9b0a1aba0428e5191ca081cc9dde97 (diff)
downloadNim-f26ed1d540c154efa67e8d427c492069719c5159.tar.gz
Add interpreting event parser proc to pegs module. (#8075)
* Added simple interpreting event parser to pegs module.
* Has side-effects problem.
* Macro solution works.
* First flat callback test works.
* Fixed namespace pollution.
* Added handler for pkChar.
* Replaced event parser test.
* Started extensive docs.
* 'callback' to 'handler' renaming part 1.
* Renaming 'callback' to 'handler' part2, completed comments.
* Fixed exported API pollution.
* Added more event handler hooks, fixed comments.
* Changed event parser addition entry.
* Fixed variable names and comments.
* Enhanced comment.
* Leave handlers are not called for an unsuccessful match.
* The three varieties of back-reference matches are processed in separate
of-clauses now.
* Improved hygiene and (almost) eliminated exports.
* Trying to fix CI test breakage by eliminating export.
* Trying to fix CI test breakage by eliminating exports.
* Re-activated leave handler code execution for unsuccessful matches.
* Eliminated the last export statement (with a funny smelling hack).
* Make sure leave handler code is executed for all unsuccessful matcher
cases.
* Replaced local unicode.`==` with export.
Diffstat (limited to 'tests/stdlib')
-rw-r--r--tests/stdlib/tpegs.nim142
1 files changed, 106 insertions, 36 deletions
diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim
index e5b709a66..b07442dcb 100644
--- a/tests/stdlib/tpegs.nim
+++ b/tests/stdlib/tpegs.nim
@@ -1,5 +1,7 @@
 discard """
   output: '''
+PEG AST traversal output
+------------------------
 pkNonTerminal: Sum @(2, 3)
   pkSequence: (Product (('+' / '-') Product)*)
     pkNonTerminal: Product @(3, 7)
@@ -26,6 +28,25 @@ pkNonTerminal: Sum @(2, 3)
           pkChar: '+'
           pkChar: '-'
         pkNonTerminal: Product @(3, 7)
+
+Event parser output
+-------------------
+@[5.0]
++
+@[5.0, 3.0]
+@[8.0]
+
+/
+@[8.0, 2.0]
+@[4.0]
+
+-
+@[4.0, 7.0]
+-*
+@[4.0, 7.0, 22.0]
+@[4.0, 154.0]
+-
+@[-150.0]
 '''
 """
 
@@ -36,43 +57,92 @@ const
   indent = "  "
 
 let
-  pegSrc = """
-Expr <- Sum
-Sum <- Product (('+' / '-') Product)*
-Product <- Value (('*' / '/') Value)*
-Value <- [0-9]+ / '(' Expr ')'
-  """
-  pegAst: Peg = pegSrc.peg
+  pegAst = """
+Expr    <- Sum
+Sum     <- Product (('+' / '-')Product)*
+Product <- Value (('*' / '/')Value)*
+Value   <- [0-9]+ / '(' Expr ')'
+  """.peg
+  txt = "(5+3)/2-7*22"
+
+block:
+  var
+    outp = newStringStream()
+    processed: seq[string] = @[]
 
-var
-  outp = newStringStream()
-  processed: seq[string] = @[]
+  proc prt(outp: Stream, kind: PegKind, s: string; level: int = 0) =
+    outp.writeLine indent.repeat(level) & "$1: $2" % [$kind, s]
 
-proc prt(outp: Stream, kind: PegKind, s: string; level: int = 0) =
-  outp.writeLine indent.repeat(level) & "$1: $2" % [$kind, s]
+  proc recLoop(p: Peg, level: int = 0) =
+    case p.kind
+    of pkEmpty..pkWhitespace:
+      discard
+    of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle:
+      outp.prt(p.kind, $p, level)
+    of pkChar, pkGreedyRepChar:
+      outp.prt(p.kind, $p, level)
+    of pkCharChoice, pkGreedyRepSet:
+      outp.prt(p.kind, $p, level)
+    of pkNonTerminal:
+      outp.prt(p.kind,
+        "$1 @($3, $4)" % [p.nt.name, $p.nt.rule.kind, $p.nt.line, $p.nt.col], level)
+      if not(p.nt.name in processed):
+        processed.add p.nt.name
+        p.nt.rule.recLoop level+1
+    of pkBackRef..pkBackRefIgnoreStyle:
+      outp.prt(p.kind, $p, level)
+    else:
+      outp.prt(p.kind, $p, level)
+      for s in items(p):
+        s.recLoop level+1
 
-proc recLoop(p: Peg, level: int = 0) =
-  case p.kind
-  of pkEmpty..pkWhitespace:
-    discard
-  of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle:
-    outp.prt(p.kind, $p, level)
-  of pkChar, pkGreedyRepChar:
-    outp.prt(p.kind, $p, level)
-  of pkCharChoice, pkGreedyRepSet:
-    outp.prt(p.kind, $p, level)
-  of pkNonTerminal:
-    outp.prt(p.kind,
-      "$1 @($3, $4)" % [p.nt.name, $p.nt.rule.kind, $p.nt.line, $p.nt.col], level)
-    if not(p.nt.name in processed):
-      processed.add p.nt.name
-      p.nt.rule.recLoop level+1
-  of pkBackRef..pkBackRefIgnoreStyle:
-    outp.prt(p.kind, $p, level)
-  else:
-    outp.prt(p.kind, $p, level)
-    for s in items(p):
-      s.recLoop level+1
+  pegAst.recLoop
+  echo "PEG AST traversal output"
+  echo "------------------------"
+  echo outp.data
 
-pegAst.recLoop
-echo outp.data
\ No newline at end of file
+block:
+  var
+    pStack: seq[string] = @[]
+    valStack: seq[float] = @[]
+    opStack = ""
+  let
+    parseArithExpr = pegAst.eventParser:
+      pkNonTerminal:
+        enter:
+          pStack.add p.nt.name
+        leave:
+          pStack.setLen pStack.high
+          if length > 0:
+            let matchStr = s.substr(start, start+length-1)
+            case p.nt.name
+            of "Value":
+              try:
+                valStack.add matchStr.parseFloat
+                echo valStack
+              except ValueError:
+                discard
+            of "Sum", "Product":
+              try:
+                let val = matchStr.parseFloat
+              except ValueError:
+                if valStack.len > 1 and opStack.len > 0:
+                  valStack[^2] = case opStack[^1]
+                  of '+': valStack[^2] + valStack[^1]
+                  of '-': valStack[^2] - valStack[^1]
+                  of '*': valStack[^2] * valStack[^1]
+                  else: valStack[^2] / valStack[^1]
+                  valStack.setLen valStack.high
+                  echo valStack
+                  opStack.setLen opStack.high
+                  echo opStack
+      pkChar:
+        leave:
+          if length == 1 and "Value" != pStack[^1]:
+            let matchChar = s[start]
+            opStack.add matchChar
+            echo opStack
+  echo "Event parser output"
+  echo "-------------------"
+  let pLen = parseArithExpr(txt)
+  assert txt.len == pLen