mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	 b01fd533fe
			
		
	
	
		b01fd533fe
		
			
		
	
	
	
	
		
			
			Simplify the peg generator logic by extracting as much visitors as possible to disentangle the flow and separate concerns.
		
			
				
	
	
		
			41 lines
		
	
	
	
		
			1.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			41 lines
		
	
	
	
		
			1.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from typing import Optional
 | |
| 
 | |
| from pegen import grammar
 | |
| from pegen.grammar import Alt, GrammarVisitor, Rhs, Rule
 | |
| 
 | |
| 
 | |
| class ValidationError(Exception):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class GrammarValidator(GrammarVisitor):
 | |
|     def __init__(self, grammar: grammar.Grammar) -> None:
 | |
|         self.grammar = grammar
 | |
|         self.rulename: Optional[str] = None
 | |
| 
 | |
|     def validate_rule(self, rulename: str, node: Rule) -> None:
 | |
|         self.rulename = rulename
 | |
|         self.visit(node)
 | |
|         self.rulename = None
 | |
| 
 | |
| 
 | |
| class SubRuleValidator(GrammarValidator):
 | |
|     def visit_Rhs(self, node: Rhs) -> None:
 | |
|         for index, alt in enumerate(node.alts):
 | |
|             alts_to_consider = node.alts[index + 1 :]
 | |
|             for other_alt in alts_to_consider:
 | |
|                 self.check_intersection(alt, other_alt)
 | |
| 
 | |
|     def check_intersection(self, first_alt: Alt, second_alt: Alt) -> None:
 | |
|         if str(second_alt).startswith(str(first_alt)):
 | |
|             raise ValidationError(
 | |
|                 f"In {self.rulename} there is an alternative that will "
 | |
|                 f"never be visited:\n{second_alt}"
 | |
|             )
 | |
| 
 | |
| 
 | |
| def validate_grammar(the_grammar: grammar.Grammar) -> None:
 | |
|     for validator_cls in GrammarValidator.__subclasses__():
 | |
|         validator = validator_cls(the_grammar)
 | |
|         for rule_name, rule in the_grammar.rules.items():
 | |
|             validator.validate_rule(rule_name, rule)
 |