17db96d56Sopenharmony_cifrom typing import Optional 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_cifrom pegen import grammar 47db96d56Sopenharmony_cifrom pegen.grammar import Alt, GrammarVisitor, Rhs, Rule 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ciclass ValidationError(Exception): 87db96d56Sopenharmony_ci pass 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ciclass GrammarValidator(GrammarVisitor): 127db96d56Sopenharmony_ci def __init__(self, grammar: grammar.Grammar) -> None: 137db96d56Sopenharmony_ci self.grammar = grammar 147db96d56Sopenharmony_ci self.rulename: Optional[str] = None 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci def validate_rule(self, rulename: str, node: Rule) -> None: 177db96d56Sopenharmony_ci self.rulename = rulename 187db96d56Sopenharmony_ci self.visit(node) 197db96d56Sopenharmony_ci self.rulename = None 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ciclass SubRuleValidator(GrammarValidator): 237db96d56Sopenharmony_ci def visit_Rhs(self, node: Rhs) -> None: 247db96d56Sopenharmony_ci for index, alt in enumerate(node.alts): 257db96d56Sopenharmony_ci alts_to_consider = node.alts[index + 1 :] 267db96d56Sopenharmony_ci for other_alt in alts_to_consider: 277db96d56Sopenharmony_ci self.check_intersection(alt, other_alt) 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci def check_intersection(self, first_alt: Alt, second_alt: Alt) -> None: 307db96d56Sopenharmony_ci if str(second_alt).startswith(str(first_alt)): 317db96d56Sopenharmony_ci raise ValidationError( 327db96d56Sopenharmony_ci f"In {self.rulename} there is an alternative that will " 337db96d56Sopenharmony_ci f"never be visited:\n{second_alt}" 347db96d56Sopenharmony_ci ) 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_cidef validate_grammar(the_grammar: grammar.Grammar) -> None: 387db96d56Sopenharmony_ci for validator_cls in GrammarValidator.__subclasses__(): 397db96d56Sopenharmony_ci validator = validator_cls(the_grammar) 407db96d56Sopenharmony_ci for rule_name, rule in the_grammar.rules.items(): 417db96d56Sopenharmony_ci validator.validate_rule(rule_name, rule) 42