• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from pegen import grammar
2from pegen.grammar import (
3    Alt,
4    Cut,
5    Gather,
6    GrammarVisitor,
7    Group,
8    Lookahead,
9    NamedItem,
10    NameLeaf,
11    NegativeLookahead,
12    Opt,
13    PositiveLookahead,
14    Repeat0,
15    Repeat1,
16    Rhs,
17    Rule,
18    StringLeaf,
19)
20
21class ValidationError(Exception):
22    pass
23
24class GrammarValidator(GrammarVisitor):
25    def __init__(self, grammar: grammar.Grammar):
26        self.grammar = grammar
27        self.rulename = None
28
29    def validate_rule(self, rulename: str, node: Rule):
30        self.rulename = rulename
31        self.visit(node)
32        self.rulename = None
33
34
35class SubRuleValidator(GrammarValidator):
36    def visit_Rhs(self, node: Rule):
37        for index, alt in enumerate(node.alts):
38            alts_to_consider = node.alts[index+1:]
39            for other_alt in alts_to_consider:
40                self.check_intersection(alt, other_alt)
41
42    def check_intersection(self, first_alt: Alt, second_alt: Alt) -> bool:
43        if str(second_alt).startswith(str(first_alt)):
44            raise ValidationError(
45                    f"In {self.rulename} there is an alternative that will "
46                    f"never be visited:\n{second_alt}")
47
48def validate_grammar(the_grammar: grammar.Grammar):
49    for validator_cls in GrammarValidator.__subclasses__():
50        validator = validator_cls(the_grammar)
51        for rule_name, rule in the_grammar.rules.items():
52            validator.validate_rule(rule_name, rule)
53