Cleaned up parser
This commit is contained in:
+79
-65
@@ -1,82 +1,96 @@
|
||||
import pyparsing as pp
|
||||
|
||||
# Packrat gives a MAD speed boost.
|
||||
# Packrat gives a significant speed boost.
|
||||
pp.ParserElement.enablePackrat()
|
||||
|
||||
import lamb.tokens as tokens
|
||||
import lamb.utils as utils
|
||||
class LambdaParser:
|
||||
def make_parser(self):
|
||||
self.lp = pp.Suppress("(")
|
||||
self.rp = pp.Suppress(")")
|
||||
self.pp_expr = pp.Forward()
|
||||
|
||||
class Parser:
|
||||
lp = pp.Suppress("(")
|
||||
rp = pp.Suppress(")")
|
||||
# Bound variables are ALWAYS lowercase and single-character.
|
||||
# We still create macro objects from them, they are turned into
|
||||
# bound variables after the expression is built.
|
||||
self.pp_macro = pp.Word(pp.alphas + "_")
|
||||
self.pp_bound = pp.Char(pp.srange("[a-z]"))
|
||||
self.pp_name = self.pp_bound ^ self.pp_macro
|
||||
self.pp_church = pp.Word(pp.nums)
|
||||
|
||||
# Simple tokens
|
||||
pp_expr = pp.Forward()
|
||||
pp_macro = pp.Word(pp.alphas + "_")
|
||||
pp_macro.set_parse_action(tokens.macro.from_parse)
|
||||
# Function calls.
|
||||
#
|
||||
# <exp> <exp>
|
||||
# <exp> <exp> <exp>
|
||||
self.pp_call = pp.Forward()
|
||||
self.pp_call <<= (self.pp_expr | self.pp_bound)[2, ...]
|
||||
|
||||
pp_church = pp.Word(pp.nums)
|
||||
pp_church.set_parse_action(utils.autochurch)
|
||||
# Function definitions, right associative.
|
||||
# Function args MUST be lowercase.
|
||||
#
|
||||
# <var> => <exp>
|
||||
self.pp_lambda_fun = (
|
||||
(pp.Suppress("λ") | pp.Suppress("\\")) +
|
||||
pp.Group(self.pp_bound[1, ...]) +
|
||||
pp.Suppress(".") +
|
||||
(self.pp_expr ^ self.pp_call)
|
||||
)
|
||||
|
||||
# Function calls.
|
||||
# `tokens.lambda_apply.from_parse` handles chained calls.
|
||||
#
|
||||
# <exp> <exp>
|
||||
# <exp> <exp> <exp>
|
||||
pp_call = pp.Forward()
|
||||
pp_call <<= pp_expr[2, ...]
|
||||
pp_call.set_parse_action(tokens.lambda_apply.from_parse)
|
||||
# Assignment.
|
||||
# Can only be found at the start of a line.
|
||||
#
|
||||
# <name> = <exp>
|
||||
self.pp_macro_def = (
|
||||
pp.line_start() +
|
||||
self.pp_macro +
|
||||
pp.Suppress("=") +
|
||||
(self.pp_expr ^ self.pp_call)
|
||||
)
|
||||
|
||||
# Function definitions.
|
||||
# Right associative.
|
||||
#
|
||||
# <var> => <exp>
|
||||
pp_lambda_fun = (
|
||||
(pp.Suppress("λ") | pp.Suppress("\\")) +
|
||||
pp.Group(pp.Char(pp.alphas)[1, ...]) +
|
||||
pp.Suppress(".") +
|
||||
(pp_expr ^ pp_call)
|
||||
)
|
||||
pp_lambda_fun.set_parse_action(tokens.lambda_func.from_parse)
|
||||
self.pp_expr <<= (
|
||||
self.pp_church ^
|
||||
self.pp_lambda_fun ^
|
||||
self.pp_name ^
|
||||
(self.lp + self.pp_expr + self.rp) ^
|
||||
(self.lp + self.pp_call + self.rp)
|
||||
)
|
||||
|
||||
# Assignment.
|
||||
# Can only be found at the start of a line.
|
||||
#
|
||||
# <name> = <exp>
|
||||
pp_macro_def = (
|
||||
pp.line_start() +
|
||||
pp_macro +
|
||||
pp.Suppress("=") +
|
||||
(pp_expr ^ pp_call)
|
||||
)
|
||||
pp_macro_def.set_parse_action(tokens.macro_expression.from_parse)
|
||||
|
||||
pp_expr <<= (
|
||||
pp_church ^
|
||||
pp_lambda_fun ^
|
||||
pp_macro ^
|
||||
(lp + pp_expr + rp) ^
|
||||
(lp + pp_call + rp)
|
||||
)
|
||||
|
||||
pp_command = pp.Suppress(":") + pp.Word(pp.alphas + "_") + pp.Word(pp.alphas + "_")[0, ...]
|
||||
pp_command.set_parse_action(tokens.command.from_parse)
|
||||
self.pp_command = pp.Suppress(":") + pp.Word(pp.alphas + "_") + pp.Word(pp.alphas + "_")[0, ...]
|
||||
|
||||
|
||||
pp_all = (
|
||||
pp_expr ^
|
||||
pp_macro_def ^
|
||||
pp_command ^
|
||||
pp_call
|
||||
)
|
||||
self.pp_all = (
|
||||
self.pp_expr ^
|
||||
self.pp_macro_def ^
|
||||
self.pp_command ^
|
||||
self.pp_call
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def parse_line(line):
|
||||
return Parser.pp_all.parse_string(
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
action_command,
|
||||
action_macro_def,
|
||||
action_church,
|
||||
action_func,
|
||||
action_bound,
|
||||
action_macro,
|
||||
action_apply
|
||||
):
|
||||
|
||||
self.make_parser()
|
||||
|
||||
self.pp_command.set_parse_action(action_command)
|
||||
self.pp_macro_def.set_parse_action(action_macro_def)
|
||||
self.pp_church.set_parse_action(action_church)
|
||||
self.pp_lambda_fun.set_parse_action(action_func)
|
||||
self.pp_macro.set_parse_action(action_macro)
|
||||
self.pp_bound.set_parse_action(action_bound)
|
||||
self.pp_call.set_parse_action(action_apply)
|
||||
|
||||
def parse_line(self, line: str):
|
||||
return self.pp_all.parse_string(
|
||||
line,
|
||||
parse_all = True
|
||||
)[0]
|
||||
|
||||
@staticmethod
|
||||
def run_tests(lines):
|
||||
return Parser.pp_all.run_tests(lines)
|
||||
def run_tests(self, lines: list[str]):
|
||||
return self.pp_all.run_tests(lines)
|
||||
Reference in New Issue
Block a user