Use an action type alias rather than class
This commit is contained in:
parent
f692e8dcca
commit
b8b6ba708f
37
parse.py
37
parse.py
|
@ -3,18 +3,7 @@ from emis_funky_funktions import *
|
|||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
from operator import contains
|
||||
from typing import Callable, Collection, Mapping, TypeGuard
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Action(Generic[A]):
|
||||
"""
|
||||
Denotes an action annotation.
|
||||
|
||||
See `parser()`
|
||||
"""
|
||||
f: Callable[[Sequence[A]], Sequence[A]]
|
||||
def __call__(self, i: Sequence[A]) -> Sequence[A]:
|
||||
return self.f(i)
|
||||
from typing import Callable, Collection, Mapping, TypeGuard, TypeAlias
|
||||
|
||||
def _expected(row: Mapping[B, Collection[Sequence[Any]]]) -> Collection[B]:
|
||||
"""
|
||||
|
@ -26,8 +15,9 @@ def _expected(row: Mapping[B, Collection[Sequence[Any]]]) -> Collection[B]:
|
|||
if len(expansions)
|
||||
]
|
||||
|
||||
Action: TypeAlias = Callable[[Sequence[C | D]], Sequence[C | D]]
|
||||
def parser(
|
||||
oracle: Mapping[A, Mapping[B, Collection[Sequence[A | B | Action[C | D]]]]],
|
||||
oracle: Mapping[A, Mapping[B, Collection[Sequence[A | B | Action]]]],
|
||||
identify_lexeme: Callable[[D], B],
|
||||
start_symbol: A,
|
||||
) -> Callable[[Sequence[D]], Result[Sequence[C | D], Tuple[D, Collection[B]]]]:
|
||||
|
@ -69,10 +59,10 @@ def parser(
|
|||
... Eof = auto()
|
||||
... def __repr__(self):
|
||||
... return self.name
|
||||
>>> build_S = Action(lambda x: x[1:])
|
||||
>>> build_Sum = Action(lambda x: (x[0](x[1][1]), *x[2:]))
|
||||
>>> build_Sum_1 = Action(lambda x: (lambda y: x[0] + y, *x[2:]))
|
||||
>>> build_Sum_2 = Action(lambda x: (lambda y: y, *x))
|
||||
>>> build_S = lambda x: x[1:]
|
||||
>>> build_Sum = lambda x: (x[0](x[1][1]), *x[2:])
|
||||
>>> build_Sum_1 = lambda x: (lambda y: x[0] + y, *x[2:])
|
||||
>>> build_Sum_2 = lambda x: (lambda y: y, *x)
|
||||
>>> grammar = [
|
||||
... (SimpleVariable.S, [SimpleVariable.Sum, SimpleTerminal.Eof, build_S]),
|
||||
... (SimpleVariable.Sum, [SimpleTerminal.Number, SimpleVariable.Sum_, build_Sum]),
|
||||
|
@ -106,14 +96,11 @@ def parser(
|
|||
is_var: Callable[[Any], TypeGuard[A]] = p_instance(start_symbol.__class__)
|
||||
is_tok: Callable[[Any], TypeGuard[B]] = p_instance(next(iter(oracle[start_symbol].keys())).__class__)
|
||||
def inner(
|
||||
stack: Sequence[A | B | Action[C | D]],
|
||||
stack: Sequence[A | B | Action],
|
||||
ast_stack: Sequence[C | D],
|
||||
lexemes: Sequence[D],
|
||||
) -> Result[Sequence[C | D], Tuple[D, Collection[B]]]:
|
||||
match stack:
|
||||
# Action
|
||||
case [Action(f), *popped_stack]:
|
||||
return inner(popped_stack, f(ast_stack), lexemes)
|
||||
# A [Variable]
|
||||
case [top_of_stack, *popped_stack] if is_var(top_of_stack):
|
||||
expansions = oracle[top_of_stack][identify_lexeme(lexemes[0])]
|
||||
|
@ -125,12 +112,16 @@ def parser(
|
|||
case _:
|
||||
raise Exception('Not an LL(1) grammar!!!')
|
||||
# B [Token] (match)
|
||||
case [top_of_stack, *popped_stack] if top_of_stack == identify_lexeme(lexemes[0]):
|
||||
case [top_of_stack, *popped_stack] if is_tok(top_of_stack) and top_of_stack == identify_lexeme(lexemes[0]):
|
||||
return inner(popped_stack, (lexemes[0], *ast_stack), lexemes[1:])
|
||||
# B [Token] (no match)
|
||||
case [top_of_stack, *popped_stack]:
|
||||
case [top_of_stack, *popped_stack] if is_tok(top_of_stack):
|
||||
assert is_tok(top_of_stack)
|
||||
return Err((lexemes[0], (top_of_stack,)))
|
||||
# Action
|
||||
case [f, *popped_stack]:
|
||||
assert hasattr(f, '__call__')
|
||||
return inner(popped_stack, f(ast_stack), lexemes)
|
||||
# Empty stack (finished parsing)
|
||||
case []:
|
||||
if len(lexemes):
|
||||
|
|
Loading…
Reference in a new issue