summary refs log tree commit diff stats
path: root/tests/stdlib/tpegs.nim
blob: e5b709a661f26f07201d117d1be0698278122fe8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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