From e203e27407fc00da3c77f52fb0326fa183f6b4be Mon Sep 17 00:00:00 2001 From: John Doty Date: Sat, 1 Jun 2024 05:42:40 -0700 Subject: [PATCH] Allow the grammar to specify a preference for a generator Overridable, like start production --- grammar.py | 3 ++- harness.py | 7 +++---- parser.py | 13 +++++++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/grammar.py b/grammar.py index 41c2064..1801bfd 100644 --- a/grammar.py +++ b/grammar.py @@ -1,7 +1,7 @@ # This is an example grammar. import re -from parser import Assoc, Grammar, Nothing, Terminal, rule, seq, Rule +from parser import Assoc, GenerateLALR, GenerateLR1, Grammar, Nothing, Terminal, rule, seq, Rule ARROW = Terminal("Arrow") AS = Terminal("As") @@ -81,6 +81,7 @@ class FineGrammar(Grammar): # (Assoc.NONE, [self.is_expression]), ], + generator=GenerateLALR, ) @rule("File") diff --git a/harness.py b/harness.py index 268b6cd..acf48ff 100644 --- a/harness.py +++ b/harness.py @@ -258,11 +258,10 @@ class DynamicModule: class DynamicGrammarModule(DynamicModule): - def __init__(self, file_name, member_name, start_rule, generator): + def __init__(self, file_name, member_name, start_rule): super().__init__(file_name, member_name) self.start_rule = start_rule - self.generator = generator def _predicate(self, member) -> bool: if not super()._predicate(member): @@ -274,7 +273,7 @@ class DynamicGrammarModule(DynamicModule): return False def _transform(self, value): - return value().build_table(start=self.start_rule, generator=self.generator) + return value().build_table(start=self.start_rule) class DynamicLexerModule(DynamicModule): @@ -319,7 +318,7 @@ class Harness: self.max_entries = 0 self.grammar_module = DynamicGrammarModule( - self.grammar_file, self.grammar_member, self.start_rule, generator=parser.GenerateLALR + self.grammar_file, self.grammar_member, self.start_rule ) self.lexer_module = DynamicLexerModule(self.lexer_file, self.lexer_member) diff --git a/parser.py b/parser.py index 583d8bd..813d91d 100644 --- a/parser.py +++ b/parser.py @@ -1850,8 +1850,14 @@ class Grammar: _precedence: dict[str, typing.Tuple[Assoc, int]] _start: str + _generator: type[GenerateLR0] - def __init__(self, start: str, precedence: PrecedenceList | None = None): + def __init__( + self, + start: str, + precedence: PrecedenceList | None = None, + generator: type[GenerateLR0] = GenerateLALR, + ): if precedence is None: precedence = getattr(self, "precedence", []) assert precedence is not None @@ -1870,6 +1876,7 @@ class Grammar: self._precedence = precedence_table self._start = start + self._generator = generator def generate_nonterminal_dict( self, start: str | None = None @@ -1940,7 +1947,7 @@ class Grammar: return grammar, transparents - def build_table(self, start: str | None, generator=GenerateLALR): + def build_table(self, start: str | None, generator=None): """Construct a parse table for this grammar, starting at the named nonterminal rule. """ @@ -1948,6 +1955,8 @@ class Grammar: start = self._start desugared, transparents = self.desugar(start) + if generator is None: + generator = self._generator gen = generator(start, desugared, precedence=self._precedence, transparents=transparents) table = gen.gen_table() return table