def test_left_recursive(self) -> None: grammar_source = """ start: expr NEWLINE expr: ('-' term | expr '+' term | term) term: NUMBER foo: NAME+ bar: NAME* baz: NAME? """ grammar: Grammar = parse_string(grammar_source, GrammarParser) parser_class = generate_parser(grammar) rules = grammar.rules self.assertFalse(rules["start"].left_recursive) self.assertTrue(rules["expr"].left_recursive) self.assertFalse(rules["term"].left_recursive) self.assertFalse(rules["foo"].left_recursive) self.assertFalse(rules["bar"].left_recursive) self.assertFalse(rules["baz"].left_recursive) node = parse_string("1 + 2 + 3\n", parser_class) self.assertEqual(node, [ [ [ [[TokenInfo(NUMBER, string="1", start=(1, 0), end=(1, 1), line="1 + 2 + 3\n")]], TokenInfo(OP, string="+", start=(1, 2), end=(1, 3), line="1 + 2 + 3\n"), [TokenInfo(NUMBER, string="2", start=(1, 4), end=(1, 5), line="1 + 2 + 3\n")], ], TokenInfo(OP, string="+", start=(1, 6), end=(1, 7), line="1 + 2 + 3\n"), [TokenInfo(NUMBER, string="3", start=(1, 8), end=(1, 9), line="1 + 2 + 3\n")], ], TokenInfo(NEWLINE, string="\n", start=(1, 9), end=(1, 10), line="1 + 2 + 3\n"), ])
def main() -> None: print( f"Testing {GRAMMAR_FILE} starting at nesting depth of {INITIAL_NESTING_DEPTH}..." ) with TemporaryDirectory() as tmp_dir: nesting_depth = INITIAL_NESTING_DEPTH rules, parser, tokenizer = build_parser(GRAMMAR_FILE) python_parser = generate_parser(rules) c_parser = generate_parser_c_extension(rules, Path(tmp_dir)) c_succeeded = True python_succeeded = True while c_succeeded or python_succeeded: expr = f"{'(' * nesting_depth}0{')' * nesting_depth}" if c_succeeded: c_succeeded = check_nested_expr(nesting_depth, c_parser, "C") if python_succeeded: python_succeeded = check_nested_expr(nesting_depth, python_parser, "Python") nesting_depth += NESTED_INCR_AMT sys.exit(1)
def test_left_recursive(): grammar = """ start: expr NEWLINE expr: ('-' term | expr '+' term | term) term: NUMBER foo: NAME+ bar: NAME* baz: NAME? """ rules = parse_string(grammar, GrammarParser).rules parser_class = generate_parser(rules) assert not rules['start'].left_recursive assert rules['expr'].left_recursive assert not rules['term'].left_recursive assert not rules['foo'].left_recursive assert not rules['bar'].left_recursive assert not rules['baz'].left_recursive node = parse_string("1 + 2 + 3\n", parser_class) assert node == [[[[[ TokenInfo(NUMBER, string='1', start=(1, 0), end=(1, 1), line='1 + 2 + 3\n') ]], TokenInfo(OP, string='+', start=(1, 2), end=(1, 3), line='1 + 2 + 3\n'), [ TokenInfo(NUMBER, string='2', start=(1, 4), end=(1, 5), line='1 + 2 + 3\n') ]], TokenInfo(OP, string='+', start=(1, 6), end=(1, 7), line='1 + 2 + 3\n'), [ TokenInfo(NUMBER, string='3', start=(1, 8), end=(1, 9), line='1 + 2 + 3\n') ]], TokenInfo(NEWLINE, string='\n', start=(1, 9), end=(1, 10), line='1 + 2 + 3\n')]
def test_left_recursive(): grammar = """ start: expr NEWLINE expr: ('-' term | expr '+' term | term) term: NUMBER foo: NAME+ bar: NAME* baz: NAME? """ grammar = parse_string(grammar, GrammarParser) parser_class = generate_parser(grammar) rules = grammar.rules assert not rules["start"].left_recursive assert rules["expr"].left_recursive assert not rules["term"].left_recursive assert not rules["foo"].left_recursive assert not rules["bar"].left_recursive assert not rules["baz"].left_recursive node = parse_string("1 + 2 + 3\n", parser_class) assert node == [ [ [ [[ TokenInfo(NUMBER, string="1", start=(1, 0), end=(1, 1), line="1 + 2 + 3\n") ]], TokenInfo(OP, string="+", start=(1, 2), end=(1, 3), line="1 + 2 + 3\n"), [ TokenInfo(NUMBER, string="2", start=(1, 4), end=(1, 5), line="1 + 2 + 3\n") ], ], TokenInfo(OP, string="+", start=(1, 6), end=(1, 7), line="1 + 2 + 3\n"), [ TokenInfo(NUMBER, string="3", start=(1, 8), end=(1, 9), line="1 + 2 + 3\n") ], ], TokenInfo(NEWLINE, string="\n", start=(1, 9), end=(1, 10), line="1 + 2 + 3\n"), ]