def test_maybe_2(): program = ("start: [foo]\n" "foo: NAME\n") rules = start(program).rules assert rules == [ Rule('start', [Alt([Maybe('foo')])]), Rule('foo', [Alt(['NAME'])]) ]
def test_grammar(): program = ("stmt: asmt | expr\n" "asmt: NAME '=' expr\n" "expr: NAME\n") rules = start(program).rules assert rules == [ Rule('stmt', [Alt(['asmt']), Alt(['expr'])]), Rule('asmt', [Alt(['NAME', "'='", 'expr'])]), Rule('expr', [Alt(['NAME'])]) ]
def test_maybe_3(): program = ("start: [foo foo | foo]\n" "foo: NAME\n") rules = start(program).rules assert rules == [ Rule('start', [Alt([Maybe('_synthetic_rule_0')])]), Rule('foo', [Alt(['NAME'])]), Rule('_synthetic_rule_0', [Alt(['foo', 'foo']), Alt(['foo'])]) ]
def test_group(): program = ("start: (foo foo | foo)\n" "foo: NAME\n") rules = start(program).rules assert rules == [ Rule('start', [Alt(['_synthetic_rule_0'])]), Rule('foo', [Alt(['NAME'])]), Rule('_synthetic_rule_0', [Alt(['foo', 'foo']), Alt(['foo'])]) ]
def test_named_item(): program = ("start: f=foo\n" "foo: n=NAME\n") file = StringIO(program) tokengen = generate_tokens(file.readline) tok = Tokenizer(tokengen) p = GrammarParser(tok) rules = p.start().rules assert rules == [ Rule('start', [Alt([NamedItem('f', 'foo')])]), Rule('foo', [Alt([NamedItem('n', 'NAME')])]) ]
def test_action(): program = "start: NAME { foo + bar } | NUMBER { -baz }\n" rules = start(program).rules assert rules == [ Rule("start", [Alt(["NAME"], "foo + bar"), Alt(["NUMBER"], "- baz")]) ] assert rules != [ Rule("start", [Alt(["NAME"], "foo + bar"), Alt(["NUMBER"], "baz")]) ]
def synthetic_rule(self, alts): if len(alts) == 1 and len(alts[0].items) == 1: return alts[0].items[0] name = f"_synthetic_rule_{len(self.extra_rules)}" rule = Rule(name, alts) self.extra_rules.append(rule) return rule.name
def test_indents2(): program = ("stmt:\n" " | foo | bar\n" " | baz\n" " | booh | bah\n" "foo: bar\n") rules = start(program).rules assert rules == [ Rule('stmt', [ Alt(['foo']), Alt(['bar']), Alt(['baz']), Alt(['booh']), Alt(['bah']) ]), Rule('foo', [Alt(['bar'])]) ]
def rule(self): self.show_rule('rule', [[ 'NAME', '":"', 'alts', 'NEWLINE', 'INDENT', 'more_alts', 'DEDENT' ], ['NAME', '":"', 'NEWLINE', 'INDENT', 'more_alts', 'DEDENT'], ['NAME', '":"', 'alts', 'NEWLINE']]) pos = self.mark() if (True and self.show_index(0, 0) and (name := self.expect(NAME)) is not None and self.show_index(0, 1) and self.expect(":") is not None and self.show_index(0, 2) and (alts := self.alts()) is not None and self.show_index(0, 3) and (newline := self.expect(NEWLINE)) is not None and self.show_index(0, 4) and (indent := self.expect(INDENT)) is not None and self.show_index(0, 5) and (more_alts := self.more_alts()) is not None and self.show_index(0, 6) and (dedent := self.expect(DEDENT)) is not None): self.show_index(0, 0, 7) retval = Rule(name.string, alts + more_alts) if retval is not None: return retval
def test_meta(): program = ("@start 'start'\n" "@foo bar\n" "@bar\n" "stmt: foo\n") grammar = start(program) assert grammar assert grammar.rules == [Rule('stmt', [Alt(["foo"])])] assert grammar.metas == [('start', 'start'), ('foo', 'bar'), ('bar', None)]
def test_cut(): program = "start: NAME ~ NAME\n" rules = start(program).rules assert rules == [Rule('start', [Alt(['NAME', Cut(), 'NAME'])])]
def test_lookahead_negative(): program = "start: !NUMBER NAME\n" rules = start(program).rules assert rules == [ Rule('start', [Alt([Lookahead('NUMBER', False), 'NAME'])]) ]
def test_lookahead(): program = "start: &NUMBER NAME\n" rules = start(program).rules assert rules == [Rule('start', [Alt([Lookahead('NUMBER'), 'NAME'])])]
def test_plus(): program = "start: NAME+\n" rules = start(program).rules assert rules == [Rule('start', [Alt([Loop('NAME', True)])])]
def test_star(): program = "start: NAME*\n" rules = start(program).rules assert rules == [Rule('start', [Alt([Loop('NAME')])])]
retval = Rule(name.string, alts + more_alts) if retval is not None: return retval self.reset(pos) if (True and self.show_index(1, 0) and (name := self.expect(NAME)) is not None and self.show_index(1, 1) and self.expect(":") is not None and self.show_index(1, 2) and (newline := self.expect(NEWLINE)) is not None and self.show_index(1, 3) and (indent := self.expect(INDENT)) is not None and self.show_index(1, 4) and (more_alts := self.more_alts()) is not None and self.show_index(1, 5) and (dedent := self.expect(DEDENT)) is not None): self.show_index(1, 0, 6) retval = Rule(name.string, more_alts) if retval is not None: return retval self.reset(pos) if (True and self.show_index(2, 0) and (name := self.expect(NAME)) is not None and self.show_index(2, 1) and self.expect(":") is not None and self.show_index(2, 2) and (alts := self.alts()) is not None and self.show_index(2, 3) and (newline := self.expect(NEWLINE)) is not None): self.show_index(2, 0, 4) retval = Rule(name.string, alts) if retval is not None: return retval self.reset(pos) self.show_index(0, 0, 0)