Allow nonterminals to be renamed

This commit is contained in:
John Doty 2024-05-30 19:15:20 -07:00
parent 4b8fef9ad6
commit 561dcd87ff
3 changed files with 43 additions and 11 deletions

View file

@ -76,7 +76,7 @@ class FineGrammar(Grammar):
] ]
) )
@rule @rule("File")
def file(self) -> Rule: def file(self) -> Rule:
return self._file_statement_list return self._file_statement_list
@ -94,7 +94,7 @@ class FineGrammar(Grammar):
def import_statement(self) -> Rule: def import_statement(self) -> Rule:
return seq(IMPORT, STRING, AS, IDENTIFIER, SEMICOLON) return seq(IMPORT, STRING, AS, IDENTIFIER, SEMICOLON)
@rule @rule("ClassDeclaration")
def class_declaration(self) -> Rule: def class_declaration(self) -> Rule:
return seq(CLASS, IDENTIFIER, self.class_body) return seq(CLASS, IDENTIFIER, self.class_body)

View file

@ -18,6 +18,11 @@ import parser
# from parser import Token, Grammar, rule, seq # from parser import Token, Grammar, rule, seq
###############################################################################
# Parsing Stuff
###############################################################################
def trace_state(stack, input, input_index, action): def trace_state(stack, input, input_index, action):
print( print(
"{stack: <20} {input: <50} {action: <5}".format( "{stack: <20} {input: <50} {action: <5}".format(
@ -133,6 +138,10 @@ def parse(table: parser.ParseTable, tokens, trace=None) -> typing.Tuple[Tree | N
raise ValueError(f"Unknown action type: {action}") raise ValueError(f"Unknown action type: {action}")
###############################################################################
# Screen Stuff
###############################################################################
# https://en.wikipedia.org/wiki/ANSI_escape_code # https://en.wikipedia.org/wiki/ANSI_escape_code
# https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 # https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
@ -176,6 +185,11 @@ def leave_alt_screen():
sys.stdout.buffer.write(CSI(b"?1049l")) sys.stdout.buffer.write(CSI(b"?1049l"))
###############################################################################
# Dynamic Modules: Detect and Reload Modules when they Change
###############################################################################
class DynamicModule: class DynamicModule:
file_name: str file_name: str
member_name: str | None member_name: str | None
@ -384,7 +398,7 @@ if __name__ == "__main__":
enter_alt_screen() enter_alt_screen()
h = Harness( h = Harness(
start_rule="file", start_rule="File",
source_path=source_path, source_path=source_path,
) )
h.run() h.run()

View file

@ -1745,15 +1745,19 @@ def seq(*args: Rule) -> Rule:
return result return result
# @typing.overload @typing.overload
# def rule(f: None | str = None) -> typing.Callable[[typing.Callable], Rule]: ... def rule(f: typing.Callable, /) -> Rule: ...
# @typing.overload @typing.overload
# def rule(f: typing.Callable) -> Rule: ... def rule(
name: str | None = None, transparent: bool | None = None
) -> typing.Callable[[typing.Callable[[typing.Any], Rule]], Rule]: ...
def rule(f: typing.Callable) -> Rule: def rule(
name: str | None | typing.Callable = None, transparent: bool | None = None
) -> Rule | typing.Callable[[typing.Callable[[typing.Any], Rule]], Rule]:
"""The decorator that marks a method in a Grammar object as a nonterminal """The decorator that marks a method in a Grammar object as a nonterminal
rule. rule.
@ -1761,10 +1765,24 @@ def rule(f: typing.Callable) -> Rule:
If called with one argument, that argument is a name that overrides the name If called with one argument, that argument is a name that overrides the name
of the nonterminal, which defaults to the name of the function. of the nonterminal, which defaults to the name of the function.
""" """
if callable(name):
return rule()(name)
def wrapper(f: typing.Callable[[typing.Any], Rule]):
nonlocal name
nonlocal transparent
if name is None:
name = f.__name__ name = f.__name__
assert isinstance(name, str)
if transparent is None:
transparent = name.startswith("_") transparent = name.startswith("_")
return NonTerminal(f, name, transparent) return NonTerminal(f, name, transparent)
return wrapper
PrecedenceList = list[typing.Tuple[Assoc, list[Rule]]] PrecedenceList = list[typing.Tuple[Assoc, list[Rule]]]