| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  | from typing import Optional | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  | from pegen import grammar | 
					
						
							| 
									
										
										
										
											2021-09-05 14:58:52 +01:00
										 |  |  | from pegen.grammar import Alt, GrammarVisitor, Rhs, Rule | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  | class ValidationError(Exception): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  | class GrammarValidator(GrammarVisitor): | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  |     def __init__(self, grammar: grammar.Grammar) -> None: | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  |         self.grammar = grammar | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  |         self.rulename: Optional[str] = None | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  |     def validate_rule(self, rulename: str, node: Rule) -> None: | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  |         self.rulename = rulename | 
					
						
							|  |  |  |         self.visit(node) | 
					
						
							|  |  |  |         self.rulename = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SubRuleValidator(GrammarValidator): | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  |     def visit_Rhs(self, node: Rhs) -> None: | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  |         for index, alt in enumerate(node.alts): | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  |             alts_to_consider = node.alts[index + 1 :] | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  |             for other_alt in alts_to_consider: | 
					
						
							|  |  |  |                 self.check_intersection(alt, other_alt) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  |     def check_intersection(self, first_alt: Alt, second_alt: Alt) -> None: | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  |         if str(second_alt).startswith(str(first_alt)): | 
					
						
							|  |  |  |             raise ValidationError( | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  |                 f"In {self.rulename} there is an alternative that will " | 
					
						
							|  |  |  |                 f"never be visited:\n{second_alt}" | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 17:37:30 +01:00
										 |  |  | def validate_grammar(the_grammar: grammar.Grammar) -> None: | 
					
						
							| 
									
										
										
										
											2020-12-26 19:11:29 +00:00
										 |  |  |     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) |