parse_tree: Remove Pratt parser

It isn't actually needed; the way we parse expressions as a prefix
followed by zero or more suffixes is enough.
This commit is contained in:
James Westman 2023-03-11 21:05:27 -06:00
parent 9fcb63a013
commit 8874cf60b3
3 changed files with 6 additions and 68 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"python.formatting.provider": "black"
}

View file

@ -23,7 +23,7 @@ from .types import TypeName
from .gtkbuilder_template import Template from .gtkbuilder_template import Template
expr = Pratt() expr = Sequence()
class Expr(AstNode): class Expr(AstNode):
@ -200,9 +200,6 @@ class ClosureExpr(Expr):
expr.children = [ expr.children = [
Prefix(ClosureExpr), AnyOf(ClosureExpr, IdentExpr, ["(", ExprChain, ")"]),
Prefix(IdentExpr), ZeroOrMore(AnyOf(LookupOp, CastExpr)),
Prefix(["(", ExprChain, ")"]),
Infix(10, LookupOp),
Infix(10, CastExpr),
] ]

View file

@ -594,68 +594,6 @@ class Keyword(ParseNode):
return str(token) == self.kw return str(token) == self.kw
class Prefix(ParseNode):
def __init__(self, child):
self.child = to_parse_node(child)
def _parse(self, ctx: ParseContext):
return self.child.parse(ctx).succeeded()
class Infix(ParseNode):
def __init__(self, binding_power: int, child):
self.binding_power = binding_power
self.child = to_parse_node(child)
def _parse(self, ctx: ParseContext):
ctx.binding_power = self.binding_power
return self.child.parse(ctx).succeeded()
def __lt__(self, other):
return self.binding_power < other.binding_power
def __eq__(self, other):
return self.binding_power == other.binding_power
class Pratt(ParseNode):
"""Basic Pratt parser implementation."""
def __init__(self, *children):
self.children = children
@property
def children(self):
return self._children
@children.setter
def children(self, children):
self._children = children
self.prefixes = [child for child in children if isinstance(child, Prefix)]
self.infixes = sorted(
[child for child in children if isinstance(child, Infix)], reverse=True
)
def _parse(self, ctx: ParseContext) -> bool:
for prefix in self.prefixes:
if prefix.parse(ctx).succeeded():
break
else:
# none of the prefixes could be parsed
return False
while True:
succeeded = False
for infix in self.infixes:
if infix.binding_power <= ctx.binding_power:
break
if infix.parse(ctx).succeeded():
succeeded = True
break
if not succeeded:
return True
def to_parse_node(value) -> ParseNode: def to_parse_node(value) -> ParseNode:
if isinstance(value, str): if isinstance(value, str):
return Match(value) return Match(value)