This repository has been archived on 2024-11-05. You can view files and clone it, but cannot push or open issues/pull-requests.
lamb/lamb_engine/parser.py

101 lines
2.5 KiB
Python
Raw Normal View History

2022-10-20 11:02:49 -07:00
import pyparsing as pp
2022-10-21 21:01:06 -07:00
2022-10-22 12:59:42 -07:00
# Packrat gives a significant speed boost.
2022-10-22 08:28:05 -07:00
pp.ParserElement.enablePackrat()
2022-10-22 12:59:42 -07:00
class LambdaParser:
def make_parser(self):
self.lp = pp.Suppress("(")
self.rp = pp.Suppress(")")
self.pp_expr = pp.Forward()
2022-10-20 11:02:49 -07:00
2022-10-22 12:59:42 -07:00
# 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 + "_")
2022-11-10 09:08:58 -08:00
self.pp_bound = pp.Regex("[a-z][₀₁₂₃₄₅₆₈₉]*")
2022-10-22 12:59:42 -07:00
self.pp_name = self.pp_bound ^ self.pp_macro
self.pp_church = pp.Word(pp.nums)
2022-10-29 15:44:17 -07:00
self.pp_history = pp.Char("$")
2022-10-20 11:02:49 -07:00
2022-10-22 12:59:42 -07:00
# Function calls.
#
# <exp> <exp>
# <exp> <exp> <exp>
self.pp_call = pp.Forward()
2022-10-29 15:44:17 -07:00
self.pp_call <<= (self.pp_expr | self.pp_bound | self.pp_history)[2, ...]
2022-10-20 11:02:49 -07:00
2022-10-22 12:59:42 -07:00
# 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)
)
2022-10-21 19:39:37 -07:00
2022-10-22 12:59:42 -07:00
# 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("=") +
2022-10-29 15:44:17 -07:00
(self.pp_expr ^ self.pp_call ^ self.pp_history)
2022-10-22 12:59:42 -07:00
)
2022-10-21 19:55:15 -07:00
2022-10-22 12:59:42 -07:00
self.pp_expr <<= (
2022-10-25 13:26:55 -07:00
self.pp_church ^
2022-10-22 12:59:42 -07:00
self.pp_lambda_fun ^
self.pp_name ^
(self.lp + self.pp_expr + self.rp) ^
2022-10-29 15:44:17 -07:00
(self.lp + self.pp_call + self.rp) ^
(self.lp + self.pp_history + self.rp)
2022-10-22 12:59:42 -07:00
)
2022-10-20 11:02:49 -07:00
2022-11-07 19:58:11 -08:00
self.pp_command = pp.Suppress(":") + pp.Word(pp.alphas + "_") + pp.Word(pp.alphas + pp.nums + "_.")[0, ...]
2022-10-20 11:02:49 -07:00
2022-10-22 12:59:42 -07:00
self.pp_all = (
self.pp_expr ^
self.pp_macro_def ^
2022-10-28 14:19:29 -07:00
self.pp_command ^
2022-10-29 15:44:17 -07:00
self.pp_call ^
self.pp_history
2022-10-22 12:59:42 -07:00
)
2022-10-20 11:02:49 -07:00
2022-10-22 12:59:42 -07:00
def __init__(
self,
*,
2022-10-23 11:24:27 -07:00
action_command,
action_macro_def,
action_church,
2022-10-22 12:59:42 -07:00
action_func,
action_bound,
action_macro,
2022-10-29 15:44:17 -07:00
action_call,
action_history
2022-10-22 12:59:42 -07:00
):
2022-10-21 19:55:15 -07:00
2022-10-22 12:59:42 -07:00
self.make_parser()
2022-10-21 19:55:15 -07:00
2022-10-23 11:24:27 -07:00
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)
2022-10-22 12:59:42 -07:00
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)
2022-10-23 08:53:26 -07:00
self.pp_call.set_parse_action(action_call)
2022-10-29 15:44:17 -07:00
self.pp_history.set_parse_action(action_history)
2022-10-22 12:59:42 -07:00
def parse_line(self, line: str):
return self.pp_all.parse_string(
2022-10-21 14:41:24 -07:00
line,
parse_all = True
)[0]
2022-10-20 11:02:49 -07:00
2022-10-22 12:59:42 -07:00
def run_tests(self, lines: list[str]):
return self.pp_all.run_tests(lines)