def test_regex(): assert (rload(r'A <- "a"') == grm({'A': Regex(r'a')})) assert (rload(r'A <- "a" [bc]') == grm({'A': Regex(r'a[bc]')})) assert (rload(r'A <- ~("a" [bc])') == grm({'A': Capture(Regex(r'a[bc]'))})) assert (rload(r'A <- "a" B B <- [bc]') == grm({ 'A': Sequence(Regex('a'), Nonterminal('B')), 'B': Regex('[bc]') })) assert (rload(r'A <- .* "a"') == grm( {'A': Regex(r'(?=(?P<_1>(?s:.)*))(?P=_1)a')})) assert (rload(r'A <- "a"* [bc]+') == grm( {'A': Regex(r'(?=(?P<_1>a*))(?P=_1)(?=(?P<_2>[bc]+))(?P=_2)')})) assert (rload(r'A <- "a" ~([bc] / "d")*') == grm({ 'A': Sequence( Regex(r'a'), Capture( Regex(r'(?=(?P<_2>(?:(?=(?P<_1>[bc]|d))(?P=_1))*))(?P=_2)'))) })) assert (rload(r'A <- "ab" / "abc"') == grm( {'A': Regex(r'(?=(?P<_1>ab|abc))(?P=_1)')})) assert (rload(r'A <- "a"* / ~"b"') == grm( {'A': Choice(Regex(r'(?=(?P<_1>a*))(?P=_1)'), Capture(Regex(r'b')))}))
def test_loads_def(): assert loads('A <- "a"') == ('A', {'A': Literal('a')}) assert loads('A <- "a" # comment') == ('A', {'A': Literal('a')}) assert loads('A <- "a" "b"') == ('A', {'A': Sequence('a', 'b')}) assert loads('A <- "a" B <- "b"') == ('A', { 'A': Literal('a'), 'B': Literal('b') }) assert loads(''' A <- "a" Bee Bee <- "b" ''') == ('A', { 'A': Sequence('a', Nonterminal('Bee')), 'Bee': Literal('b') })
def _make_sequential(exprs): if len(exprs) == 1: return exprs[0] elif len(exprs) > 1: return Sequence(*exprs) else: raise Error(f'empty sequence: {exprs}')
def test_Sequence(): assert (Sequence(Literal('a'), Dot()) == Def(Op.SEQ, ([Literal('a'), Dot()], ))) assert Sequence('foo', 'bar') == Sequence(Literal('foo'), Literal('bar')) # simple optimizations assert Sequence(Dot()) == Dot() assert Sequence(Sequence('a', 'b'), 'c') == Sequence('a', 'b', 'c')
def _regex_sequence(defn, defs, grpid): _subdefs = [_regex(subdef, defs, grpid) for subdef in defn.args[0]] subdefs = [] for k, grp in groupby(_subdefs, key=lambda d: d.op): # only join regexes in sequence if unstructured if k == RGX: subdefs.append(Regex(''.join(d.args[0] for d in grp))) else: subdefs.extend(grp) return Sequence(*subdefs)
def test_common(): assert (cload(r'A <- "a"') == gload(r'A <- "a"')) assert (cload(r'A <- !"a"') == gload(r'A <- !"a"')) assert (cload(r'A <- !"a"') == gload(r'A <- !"a"')) # single-char classes to literals assert (cload(r'A <- [a]') == gload(r'A <- "a"')) # but not single-range assert (cload(r'A <- [a-c]') == gload(r'A <- [a-c]')) # add "b" to avoid dropping the sequence assert (cload(r'A <- !"a" . "b"') == cload(r'A <- ![a] . "b"') == grm( {'A': Sequence(Class('a', negate=True), Literal('b'))})) # now show the dropped sequence assert (cload(r'A <- !"a" .') == cload(r'A <- ![a] .') == grm( {'A': Class('a', negate=True)})) # sequence of literals to literal assert (cload(r'A <- "a" "bc" "d"') == gload(r'A <- "abcd"')) # but not sequence with classes assert (cload(r'A <- "a" [bc] "d"') == gload(r'A <- "a" [bc] "d"')) # choice of classes or single-char literals assert (cload(r'A <- [ab] / "m" / [yz]') == gload(r'A <- [abmyz]')) # not negated classes though assert (cload(r'A <- (![ab] .) / "m" / [yz]') == grm( {'A': Choice(Class('ab', negate=True), Class('myz'))}))
from pe import Match from pe.operators import Literal, Sequence, Capture, Bind, Rule from pe.actions import Pack One = Literal('1') CaptureOne = Capture(Literal('1')) OneTwo = Sequence(Literal('1'), Literal('2')) OneCaptureTwo = Sequence(Literal('1'), Capture(Literal('2'))) OneBindTwo = Sequence(Literal('1'), Bind(Literal('2'), name='x')) OneBindCaptureTwo = Sequence(Literal('1'), Bind(Capture(Literal('2')), name='x')) OneTwoRule = Rule(Sequence(Capture(Literal('1')), Capture(Literal('2'))), action=Pack(list)) def test_Match_atom(): m = Match('123', 0, 1, One, (), {}) assert m.string == '123' assert m.start() == 0 assert m.end() == 1 assert m.span() == (0, 1) assert m.pe is One assert m.group(0) == '1' assert m.groups() == () assert m.groupdict() == {} assert m.value() is None def test_Match_capture_atom(): m = Match('123', 0, 1, CaptureOne, ('1', ), {}) assert m.string == '123'
def test_loads_sequence(): assert eloads('"a" "b"') == Sequence('a', 'b') assert eloads('"a" "b" # comment') == Sequence('a', 'b')
raise Error(f'empty sequence: {exprs}') def _make_prioritized(exprs): if len(exprs) == 1: return exprs[0] elif len(exprs) > 1: return Choice(*exprs) else: raise Error(f'empty choice: {exprs}') V = SymbolTable() # Hierarchical syntax V.Start = Sequence(V.Spacing, Choice(V.Grammar, V.Expression), V.EOF) V.Grammar = Plus(V.Definition) V.Definition = Sequence(V.Identifier, V.LEFTARROW, V.Expression) V.Expression = Sequence(V.Sequence, Star(Sequence(V.SLASH, V.Sequence))) V.Sequence = Plus(V.Valued) V.Valued = Sequence(Optional(Bind(V.Prefix, name='prefix')), V.Quantified) V.Prefix = Choice(V.AND, V.NOT, V.TILDE, V.Binding) V.Binding = Sequence(V.Identifier, ':', V.Spacing) V.Quantified = Sequence(V.Primary, Optional(Bind(V.Quantifier, name='quantifier'))) V.Quantifier = Choice(V.QUESTION, V.STAR, V.PLUS) V.Primary = Choice(V.Name, V.Group, V.Literal, V.Class, V.DOT) V.Name = Sequence(V.Identifier, V.Spacing, Not(V.LEFTARROW)) V.Group = Sequence(V.OPEN, V.Expression, V.CLOSE) V.Literal = Sequence( Choice(Capture(Sequence("'", Star(Sequence(Not("'"), V.Char)), "'")),