Fixed parser, added macro printout
parent
ee744b5245
commit
8558c484c5
|
@ -2,7 +2,6 @@
|
|||
|
||||
|
||||
## Todo (pre-release):
|
||||
- Fix parser (call parentheses)
|
||||
- Good command parsing (`:save`, `:load`, are a bare minimum)
|
||||
- Python files: installable, package list, etc
|
||||
- $\alpha$-equivalence check
|
||||
|
@ -18,6 +17,7 @@
|
|||
- Warn when overwriting macro
|
||||
- Syntax highlighting: parenthesis, bound variables, macros, etc
|
||||
- Pin header to top of screen
|
||||
- Parser is a bit slow. Maybe we can do better?
|
||||
|
||||
## Mention in Docs
|
||||
- lambda functions only work with single-letter arguments
|
||||
|
|
10
main.py
10
main.py
|
@ -43,7 +43,7 @@ r.run_lines([
|
|||
"OR = λab.(a T b)",
|
||||
"XOR = λab.(a (NOT a b) b)",
|
||||
"w = λx.(x x)",
|
||||
"W = (w w)",
|
||||
"W = w w",
|
||||
"Y = λf.( (λx.(f (x x))) (λx.(f (x x))) )",
|
||||
"PAIR = λabi.( i a b )",
|
||||
"inc = λnfa.(f (n f a))",
|
||||
|
@ -90,7 +90,13 @@ while True:
|
|||
|
||||
# If this line defined a macro, print nothing.
|
||||
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):
|
||||
printf(x.formatted_text)
|
||||
|
|
66
parser.py
66
parser.py
|
@ -3,16 +3,6 @@ import tokens
|
|||
import utils
|
||||
|
||||
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("(")
|
||||
rp = pp.Suppress(")")
|
||||
|
||||
|
@ -24,6 +14,15 @@ class Parser:
|
|||
pp_church = pp.Word(pp.nums)
|
||||
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.
|
||||
# Right associative.
|
||||
#
|
||||
|
@ -32,41 +31,44 @@ class Parser:
|
|||
(pp.Suppress("λ") | pp.Suppress("\\")) +
|
||||
pp.Group(pp.Char(pp.alphas)[1, ...]) +
|
||||
pp.Suppress(".") +
|
||||
pp_expr
|
||||
(pp_expr ^ pp_call)
|
||||
)
|
||||
pp_lambda_fun.set_parse_action(tokens.lambda_func.from_parse)
|
||||
|
||||
# Assignment.
|
||||
# Can only be found at the start of a line.
|
||||
#
|
||||
# <var> = <exp>
|
||||
pp_macro_def = pp.line_start() + pp_macro + pp.Suppress("=") + pp_expr
|
||||
# <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)
|
||||
|
||||
# Function calls.
|
||||
# `tokens.lambda_func.from_parse` handles chained calls.
|
||||
#
|
||||
# <var>(<exp>)
|
||||
# <var>(<exp>)(<exp>)(<exp>)
|
||||
# (<exp>)(<exp>)
|
||||
# (<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_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_command.set_parse_action(tokens.command.from_parse)
|
||||
|
||||
|
||||
pp_all = (
|
||||
pp_expr ^
|
||||
pp_macro_def ^
|
||||
pp_command ^
|
||||
pp_call
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def parse_line(line):
|
||||
k = (
|
||||
Parser.pp_expr ^
|
||||
Parser.pp_macro_def ^
|
||||
Parser.pp_command ^ Parser.pp_call
|
||||
).parse_string(
|
||||
k = Parser.pp_all.parse_string(
|
||||
line,
|
||||
parse_all = True
|
||||
)[0]
|
||||
|
@ -75,4 +77,4 @@ class Parser:
|
|||
|
||||
@staticmethod
|
||||
def run_tests(lines):
|
||||
return Parser.pp_macro_def.run_tests(lines)
|
||||
return Parser.pp_all.run_tests(lines)
|
|
@ -77,7 +77,8 @@ class Runner:
|
|||
|
||||
return MacroStatus(
|
||||
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.
|
||||
|
|
|
@ -17,16 +17,19 @@ class MacroStatus(RunStatus):
|
|||
Values:
|
||||
`was_rewritten`: If true, an old macro was replaced.
|
||||
`macro_label`: The name of the macro we just made.
|
||||
`macro_expr`: The expr of the macro we just made.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
was_rewritten: bool,
|
||||
macro_label: str
|
||||
macro_label: str,
|
||||
macro_expr
|
||||
):
|
||||
self.was_rewritten = was_rewritten
|
||||
self.macro_label = macro_label
|
||||
self.macro_expr = macro_expr
|
||||
|
||||
|
||||
class StopReason(enum.Enum):
|
||||
|
|
Reference in New Issue