diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/stdlib/tpegs.nim | 142 |
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 |