* Make PEG AST nodes readable from outside the module. * Added a test module for the pegs stdlib module. * Edited changelog. * Renamed ``sons`` iterator to ``items``, added ``pairs``, inlined both. * Updated entry and moved it to the right category.
78 lines
No EOL
2.1 KiB
Nim
78 lines
No EOL
2.1 KiB
Nim
discard """
|
|
output: '''
|
|
pkNonTerminal: Sum @(2, 3)
|
|
pkSequence: (Product (('+' / '-') Product)*)
|
|
pkNonTerminal: Product @(3, 7)
|
|
pkSequence: (Value (('*' / '/') Value)*)
|
|
pkNonTerminal: Value @(4, 5)
|
|
pkOrderedChoice: (([0-9] [0-9]*) / ('(' Expr ')'))
|
|
pkSequence: ([0-9] [0-9]*)
|
|
pkCharChoice: [0-9]
|
|
pkGreedyRepSet: [0-9]*
|
|
pkSequence: ('(' Expr ')')
|
|
pkChar: '('
|
|
pkNonTerminal: Expr @(1, 4)
|
|
pkNonTerminal: Sum @(2, 3)
|
|
pkChar: ')'
|
|
pkGreedyRep: (('*' / '/') Value)*
|
|
pkSequence: (('*' / '/') Value)
|
|
pkOrderedChoice: ('*' / '/')
|
|
pkChar: '*'
|
|
pkChar: '/'
|
|
pkNonTerminal: Value @(4, 5)
|
|
pkGreedyRep: (('+' / '-') Product)*
|
|
pkSequence: (('+' / '-') Product)
|
|
pkOrderedChoice: ('+' / '-')
|
|
pkChar: '+'
|
|
pkChar: '-'
|
|
pkNonTerminal: Product @(3, 7)
|
|
'''
|
|
"""
|
|
|
|
import strutils, streams
|
|
import pegs
|
|
|
|
const
|
|
indent = " "
|
|
|
|
let
|
|
pegSrc = """
|
|
Expr <- Sum
|
|
Sum <- Product (('+' / '-') Product)*
|
|
Product <- Value (('*' / '/') Value)*
|
|
Value <- [0-9]+ / '(' Expr ')'
|
|
"""
|
|
pegAst: Peg = pegSrc.peg
|
|
|
|
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 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 outp.data |