Pegs AST read access (#8050)
* 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.
This commit is contained in:
parent
3ca11def6d
commit
db68bbe4f7
3 changed files with 102 additions and 2 deletions
|
|
@ -107,6 +107,9 @@
|
||||||
use the Nim VM in a native Nim application.
|
use the Nim VM in a native Nim application.
|
||||||
- Added the parameter ``val`` for the ``CritBitTree[T].incl`` proc.
|
- Added the parameter ``val`` for the ``CritBitTree[T].incl`` proc.
|
||||||
- The proc ``tgamma`` was renamed to ``gamma``. ``tgamma`` is deprecated.
|
- The proc ``tgamma`` was renamed to ``gamma``. ``tgamma`` is deprecated.
|
||||||
|
- The ``pegs`` module now exports getters for the fields of its ``Peg`` and ``NonTerminal``
|
||||||
|
object types. ``Peg``s with child nodes now have the standard ``items`` and ``pairs``
|
||||||
|
iterators.
|
||||||
|
|
||||||
### Language additions
|
### Language additions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ const
|
||||||
## can be captured. More subpatterns cannot be captured!
|
## can be captured. More subpatterns cannot be captured!
|
||||||
|
|
||||||
type
|
type
|
||||||
PegKind = enum
|
PegKind* = enum
|
||||||
pkEmpty,
|
pkEmpty,
|
||||||
pkAny, ## any character (.)
|
pkAny, ## any character (.)
|
||||||
pkAnyRune, ## any Unicode character (_)
|
pkAnyRune, ## any Unicode character (_)
|
||||||
|
|
@ -67,7 +67,7 @@ type
|
||||||
pkRule, ## a <- b
|
pkRule, ## a <- b
|
||||||
pkList, ## a, b
|
pkList, ## a, b
|
||||||
pkStartAnchor ## ^ --> Internal DSL: startAnchor()
|
pkStartAnchor ## ^ --> Internal DSL: startAnchor()
|
||||||
NonTerminalFlag = enum
|
NonTerminalFlag* = enum
|
||||||
ntDeclared, ntUsed
|
ntDeclared, ntUsed
|
||||||
NonTerminalObj = object ## represents a non terminal symbol
|
NonTerminalObj = object ## represents a non terminal symbol
|
||||||
name: string ## the name of the symbol
|
name: string ## the name of the symbol
|
||||||
|
|
@ -86,6 +86,25 @@ type
|
||||||
else: sons: seq[Peg]
|
else: sons: seq[Peg]
|
||||||
NonTerminal* = ref NonTerminalObj
|
NonTerminal* = ref NonTerminalObj
|
||||||
|
|
||||||
|
proc name*(nt: NonTerminal): string = nt.name
|
||||||
|
proc line*(nt: NonTerminal): int = nt.line
|
||||||
|
proc col*(nt: NonTerminal): int = nt.col
|
||||||
|
proc flags*(nt: NonTerminal): set[NonTerminalFlag] = nt.flags
|
||||||
|
proc rule*(nt: NonTerminal): Peg = nt.rule
|
||||||
|
|
||||||
|
proc kind*(p: Peg): PegKind = p.kind
|
||||||
|
proc term*(p: Peg): string = p.term
|
||||||
|
proc ch*(p: Peg): char = p.ch
|
||||||
|
proc charChoice*(p: Peg): ref set[char] = p.charChoice
|
||||||
|
proc nt*(p: Peg): NonTerminal = p.nt
|
||||||
|
proc index*(p: Peg): range[0..MaxSubpatterns] = p.index
|
||||||
|
iterator items*(p: Peg): Peg {.inline.} =
|
||||||
|
for s in p.sons:
|
||||||
|
yield s
|
||||||
|
iterator pairs*(p: Peg): (int, Peg) {.inline.} =
|
||||||
|
for i in 0 ..< p.sons.len:
|
||||||
|
yield (i, p.sons[i])
|
||||||
|
|
||||||
proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} =
|
proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} =
|
||||||
## constructs a PEG from a terminal string
|
## constructs a PEG from a terminal string
|
||||||
if t.len != 1:
|
if t.len != 1:
|
||||||
|
|
|
||||||
78
tests/stdlib/tpegs.nim
Normal file
78
tests/stdlib/tpegs.nim
Normal file
|
|
@ -0,0 +1,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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue