Fixed parser, added macro printout

master
Mark 2022-10-21 19:55:15 -07:00
parent ee744b5245
commit 8558c484c5
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
5 changed files with 49 additions and 37 deletions

View File

@ -2,7 +2,6 @@
## Todo (pre-release): ## Todo (pre-release):
- Fix parser (call parentheses)
- Good command parsing (`:save`, `:load`, are a bare minimum) - Good command parsing (`:save`, `:load`, are a bare minimum)
- Python files: installable, package list, etc - Python files: installable, package list, etc
- $\alpha$-equivalence check - $\alpha$-equivalence check
@ -18,6 +17,7 @@
- Warn when overwriting macro - Warn when overwriting macro
- Syntax highlighting: parenthesis, bound variables, macros, etc - Syntax highlighting: parenthesis, bound variables, macros, etc
- Pin header to top of screen - Pin header to top of screen
- Parser is a bit slow. Maybe we can do better?
## Mention in Docs ## Mention in Docs
- lambda functions only work with single-letter arguments - lambda functions only work with single-letter arguments

10
main.py
View File

@ -43,7 +43,7 @@ r.run_lines([
"OR = λab.(a T b)", "OR = λab.(a T b)",
"XOR = λab.(a (NOT a b) b)", "XOR = λab.(a (NOT a b) b)",
"w = λx.(x x)", "w = λx.(x x)",
"W = (w w)", "W = w w",
"Y = λf.( (λx.(f (x x))) (λx.(f (x x))) )", "Y = λf.( (λx.(f (x x))) (λx.(f (x x))) )",
"PAIR = λabi.( i a b )", "PAIR = λabi.( i a b )",
"inc = λnfa.(f (n f a))", "inc = λnfa.(f (n f a))",
@ -90,7 +90,13 @@ while True:
# If this line defined a macro, print nothing. # If this line defined a macro, print nothing.
if isinstance(x, runner.MacroStatus): if isinstance(x, runner.MacroStatus):
pass printf(FormattedText([
("#FFFFFF", "Set "),
("#FF00FF", x.macro_label),
("#FFFFFF", " to "),
("#FFFFFF", str(x.macro_expr))
]))
if isinstance(x, runner.CommandStatus): if isinstance(x, runner.CommandStatus):
printf(x.formatted_text) printf(x.formatted_text)

View File

@ -3,16 +3,6 @@ import tokens
import utils import utils
class Parser: class Parser:
"""
Macro_def must be on its own line.
macro_def :: var = expr
var :: word
lambda_fun :: var -> expr
call :: '(' (var | expr) ')' +
expr :: define | var | call | '(' expr ')'
"""
lp = pp.Suppress("(") lp = pp.Suppress("(")
rp = pp.Suppress(")") rp = pp.Suppress(")")
@ -24,6 +14,15 @@ class Parser:
pp_church = pp.Word(pp.nums) pp_church = pp.Word(pp.nums)
pp_church.set_parse_action(utils.autochurch) pp_church.set_parse_action(utils.autochurch)
# 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)
# Function definitions. # Function definitions.
# Right associative. # Right associative.
# #
@ -32,41 +31,44 @@ class Parser:
(pp.Suppress("λ") | pp.Suppress("\\")) + (pp.Suppress("λ") | pp.Suppress("\\")) +
pp.Group(pp.Char(pp.alphas)[1, ...]) + pp.Group(pp.Char(pp.alphas)[1, ...]) +
pp.Suppress(".") + pp.Suppress(".") +
pp_expr (pp_expr ^ pp_call)
) )
pp_lambda_fun.set_parse_action(tokens.lambda_func.from_parse) pp_lambda_fun.set_parse_action(tokens.lambda_func.from_parse)
# Assignment. # Assignment.
# Can only be found at the start of a line. # Can only be found at the start of a line.
# #
# <var> = <exp> # <name> = <exp>
pp_macro_def = pp.line_start() + pp_macro + pp.Suppress("=") + pp_expr 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_macro_def.set_parse_action(tokens.macro_expression.from_parse)
# Function calls. pp_expr <<= (
# `tokens.lambda_func.from_parse` handles chained calls. pp_church ^
# pp_lambda_fun ^
# <var>(<exp>) pp_macro ^
# <var>(<exp>)(<exp>)(<exp>) (lp + pp_expr + rp) ^
# (<exp>)(<exp>) (lp + pp_call + rp)
# (<exp>)(<exp>)(<exp>)(<exp>) )
pp_call = pp.Forward()
pp_call <<= pp_expr[2, ...]
pp_call.set_parse_action(tokens.lambda_apply.from_parse)
pp_expr <<= pp_lambda_fun ^ (lp + pp_expr + rp) ^ pp_macro ^ (lp + pp_call + rp) ^ pp_church
pp_all = pp_expr | pp_macro_def
pp_command = pp.Suppress(":") + pp.Word(pp.alphas + "_") pp_command = pp.Suppress(":") + pp.Word(pp.alphas + "_")
pp_command.set_parse_action(tokens.command.from_parse) pp_command.set_parse_action(tokens.command.from_parse)
pp_all = (
pp_expr ^
pp_macro_def ^
pp_command ^
pp_call
)
@staticmethod @staticmethod
def parse_line(line): def parse_line(line):
k = ( k = Parser.pp_all.parse_string(
Parser.pp_expr ^
Parser.pp_macro_def ^
Parser.pp_command ^ Parser.pp_call
).parse_string(
line, line,
parse_all = True parse_all = True
)[0] )[0]
@ -75,4 +77,4 @@ class Parser:
@staticmethod @staticmethod
def run_tests(lines): def run_tests(lines):
return Parser.pp_macro_def.run_tests(lines) return Parser.pp_all.run_tests(lines)

View File

@ -77,7 +77,8 @@ class Runner:
return MacroStatus( return MacroStatus(
was_rewritten = was_rewritten, was_rewritten = was_rewritten,
macro_label = e.label macro_label = e.label,
macro_expr = e.exp
) )
# If this line is a command, do the command. # If this line is a command, do the command.

View File

@ -17,16 +17,19 @@ class MacroStatus(RunStatus):
Values: Values:
`was_rewritten`: If true, an old macro was replaced. `was_rewritten`: If true, an old macro was replaced.
`macro_label`: The name of the macro we just made. `macro_label`: The name of the macro we just made.
`macro_expr`: The expr of the macro we just made.
""" """
def __init__( def __init__(
self, self,
*, *,
was_rewritten: bool, was_rewritten: bool,
macro_label: str macro_label: str,
macro_expr
): ):
self.was_rewritten = was_rewritten self.was_rewritten = was_rewritten
self.macro_label = macro_label self.macro_label = macro_label
self.macro_expr = macro_expr
class StopReason(enum.Enum): class StopReason(enum.Enum):