def check_nested_expr(nesting_depth: int, parser: Any, language: str) -> bool: expr = f"{'(' * nesting_depth}0{')' * nesting_depth}" try: if language == "Python": parse_string(expr, parser) else: parser.parse_string(expr) print(f"({language}) Nesting depth of {nesting_depth} is successful") return True except Exception as err: print( f"{FAIL}({language}) Failed with nesting depth of {nesting_depth}{ENDC}" ) print(f"{FAIL}\t{err}{ENDC}") return False
def test_parse_trivial_grammar() -> None: grammar = """ start: 'a' """ rules = parse_string(grammar, GrammarParser) visitor = Visitor() visitor.visit(rules) assert visitor.n_nodes == 6
def test_rule_with_no_collision(self) -> None: grammar_source = """ start: bad_rule sum: | NAME '-' NAME | NAME '+' NAME """ grammar: Grammar = parse_string(grammar_source, GrammarParser) validator = SubRuleValidator(grammar) for rule_name, rule in grammar.rules.items(): validator.validate_rule(rule_name, rule)
def test_parse_repeat1_grammar() -> None: grammar = """ start: 'a'+ """ rules = parse_string(grammar, GrammarParser) visitor = Visitor() visitor.visit(rules) # Grammar/Rule/Rhs/Alt/NamedItem/Repeat1/StringLeaf -> 6 assert visitor.n_nodes == 7
def test_rule_with_simple_collision(self) -> None: grammar_source = """ start: bad_rule sum: | NAME '+' NAME | NAME '+' NAME ';' """ grammar: Grammar = parse_string(grammar_source, GrammarParser) validator = SubRuleValidator(grammar) with self.assertRaises(ValidationError): for rule_name, rule in grammar.rules.items(): validator.validate_rule(rule_name, rule)
def test_parse_optional_grammar() -> None: grammar = """ start: 'a' ['b'] """ rules = parse_string(grammar, GrammarParser) visitor = Visitor() visitor.visit(rules) # Grammar/Rule/Rhs/Alt/NamedItem/StringLeaf -> 6 # NamedItem/Opt/Rhs/Alt/NamedItem/Stringleaf -> 6 assert visitor.n_nodes == 12
def test_parse_or_grammar() -> None: grammar = """ start: rule rule: 'a' | 'b' """ rules = parse_string(grammar, GrammarParser) visitor = Visitor() visitor.visit(rules) # Grammar/Rule/Rhs/Alt/NamedItem/NameLeaf -> 6 # Rule/Rhs/ -> 2 # Alt/NamedItem/StringLeaf -> 3 # Alt/NamedItem/StringLeaf -> 3 assert visitor.n_nodes == 14
def test_deep_nested_rule() -> None: grammar = """ start: 'a' ['b'['c'['d']]] """ rules = parse_string(grammar, GrammarParser) printer = ASTGrammarPrinter() lines: List[str] = [] printer.print_grammar_ast(rules, printer=lines.append) output = "\n".join(lines) print() print(output) expected_output = textwrap.dedent("""\ └──Rule └──Rhs └──Alt ├──NamedItem │ └──StringLeaf("'a'") └──NamedItem └──Opt └──Rhs └──Alt ├──NamedItem │ └──StringLeaf("'b'") └──NamedItem └──Opt └──Rhs └──Alt ├──NamedItem │ └──StringLeaf("'c'") └──NamedItem └──Opt └──Rhs └──Alt └──NamedItem └──StringLeaf("'d'") """) assert output == expected_output
def test_multiple_rules() -> None: grammar = """ start: a b a: 'a' b: 'b' """ rules = parse_string(grammar, GrammarParser) printer = ASTGrammarPrinter() lines: List[str] = [] printer.print_grammar_ast(rules, printer=lines.append) output = "\n".join(lines) expected_output = textwrap.dedent("""\ └──Rule └──Rhs └──Alt ├──NamedItem │ └──NameLeaf('a') └──NamedItem └──NameLeaf('b') └──Rule └──Rhs └──Alt └──NamedItem └──StringLeaf("'a'") └──Rule └──Rhs └──Alt └──NamedItem └──StringLeaf("'b'") """) assert output == expected_output
def calculate_first_sets(grammar_source: str) -> Dict[str, Set[str]]: grammar: Grammar = parse_string(grammar_source, GrammarParser) return FirstSetCalculator(grammar.rules).calculate()