Allow the grammar to specify a preference for a generator

Overridable, like start production
This commit is contained in:
John Doty 2024-06-01 05:42:40 -07:00
parent 55c4675fe5
commit e203e27407
3 changed files with 16 additions and 7 deletions

View file

@ -1,7 +1,7 @@
# This is an example grammar. # This is an example grammar.
import re 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") ARROW = Terminal("Arrow")
AS = Terminal("As") AS = Terminal("As")
@ -81,6 +81,7 @@ class FineGrammar(Grammar):
# #
(Assoc.NONE, [self.is_expression]), (Assoc.NONE, [self.is_expression]),
], ],
generator=GenerateLALR,
) )
@rule("File") @rule("File")

View file

@ -258,11 +258,10 @@ class DynamicModule:
class DynamicGrammarModule(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) super().__init__(file_name, member_name)
self.start_rule = start_rule self.start_rule = start_rule
self.generator = generator
def _predicate(self, member) -> bool: def _predicate(self, member) -> bool:
if not super()._predicate(member): if not super()._predicate(member):
@ -274,7 +273,7 @@ class DynamicGrammarModule(DynamicModule):
return False return False
def _transform(self, value): 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): class DynamicLexerModule(DynamicModule):
@ -319,7 +318,7 @@ class Harness:
self.max_entries = 0 self.max_entries = 0
self.grammar_module = DynamicGrammarModule( 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) self.lexer_module = DynamicLexerModule(self.lexer_file, self.lexer_member)

View file

@ -1850,8 +1850,14 @@ class Grammar:
_precedence: dict[str, typing.Tuple[Assoc, int]] _precedence: dict[str, typing.Tuple[Assoc, int]]
_start: str _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: if precedence is None:
precedence = getattr(self, "precedence", []) precedence = getattr(self, "precedence", [])
assert precedence is not None assert precedence is not None
@ -1870,6 +1876,7 @@ class Grammar:
self._precedence = precedence_table self._precedence = precedence_table
self._start = start self._start = start
self._generator = generator
def generate_nonterminal_dict( def generate_nonterminal_dict(
self, start: str | None = None self, start: str | None = None
@ -1940,7 +1947,7 @@ class Grammar:
return grammar, transparents 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 """Construct a parse table for this grammar, starting at the named
nonterminal rule. nonterminal rule.
""" """
@ -1948,6 +1955,8 @@ class Grammar:
start = self._start start = self._start
desugared, transparents = self.desugar(start) desugared, transparents = self.desugar(start)
if generator is None:
generator = self._generator
gen = generator(start, desugared, precedence=self._precedence, transparents=transparents) gen = generator(start, desugared, precedence=self._precedence, transparents=transparents)
table = gen.gen_table() table = gen.gen_table()
return table return table