summary refs log tree commit diff stats
path: root/tests/js/tenumhole.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/js/tenumhole.nim')
0 files changed, 0 insertions, 0 deletions
id='n55' href='#n55'>55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
discard """
  output: '''
PEG AST traversal 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)

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]
'''
"""

import strutils, streams
import pegs

const
  indent = "  "

let
  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] = @[]

  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 "PEG AST traversal output"
  echo "------------------------"
  echo outp.data

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