在 Rascal 中解析和实现 lambda 演算
Parsing and implementing a lambda calculus in Rascal
我正在尝试在 Rascal 内部实现 lambda 演算,但无法按照我希望的方式获得优先级和解析。目前我的语法看起来像:
keyword Keywords= "if" | "then" | "else" | "end" | "fun";
lexical Ident = [a-zA-Z] !>> [a-zA-Z]+ !>> [a-zA-Z0-9] \ Keywords;
lexical Natural = [0-9]+ !>> [0-9];
lexical LAYOUT = [\t-\n\r\ ];
layout LAYOUTLIST = LAYOUT* !>> [\t-\n\r\ ];
start syntax Prog = prog: Exp LAYOUTLIST;
syntax Exp =
var: Ident
| nat: Natural
| bracket "(" Exp ")"
> left app: Exp Exp
> right func: "fun" Ident "-\>" Exp
当我解析以下形式的程序时:
(fun x -> fun y -> x) 1 2
生成的树是:
prog(app(
app(
func(
"x",
func(
"y",
var("x")
nat(1),
nat(2))))))
我真的在哪里寻找这样的东西(我认为):
prog(app(
func(
"x",
app(
func(
"y",
var("x")),
nat(2))),
nat(1)))
我尝试了语法中优先级的多种变体,我尝试了将 App 规则括在括号中,以及许多其他变体。这里似乎发生了一些我不明白的事情。非常感激任何的帮助。谢谢
我使用了以下语法,它删除了多余的 LAYOUTLIST
和死的 right
,但这应该没有什么区别。当我使用通用 implode
函数时,它似乎如你所愿地工作:
keyword Keywords= "if" | "then" | "else" | "end" | "fun";
lexical Ident = [a-zA-Z] !>> [a-zA-Z]+ !>> [a-zA-Z0-9] \ Keywords;
lexical Natural = [0-9]+ !>> [0-9];
lexical LAYOUT = [\t-\n\r\ ];
layout LAYOUTLIST = LAYOUT* !>> [\t-\n\r\ ];
start syntax Prog = prog: Exp;
syntax Exp =
var: Ident
| nat: Natural
| bracket "(" Exp ")"
> left app: Exp Exp
> func: "fun" Ident "-\>" Exp
;
然后调用解析器并分解为无类型的 AST(为了便于阅读,我删除了位置注释):
rascal>import ParseTree;
ok
rascal>implode(#node, parse(#start[Prog], "(fun x -\> fun y -\> x) 1 2"))
node: "prog"("app"(
"app"(
"func"(
"x",
"func"(
"y",
"var"("x"))),
"nat"("1")),
"nat"("2")))
所以,我猜你的语法适合你想要的树的形状。你如何从具体的解析树到抽象的 AST?也许那里发生了一些有趣的事情。
我正在尝试在 Rascal 内部实现 lambda 演算,但无法按照我希望的方式获得优先级和解析。目前我的语法看起来像:
keyword Keywords= "if" | "then" | "else" | "end" | "fun";
lexical Ident = [a-zA-Z] !>> [a-zA-Z]+ !>> [a-zA-Z0-9] \ Keywords;
lexical Natural = [0-9]+ !>> [0-9];
lexical LAYOUT = [\t-\n\r\ ];
layout LAYOUTLIST = LAYOUT* !>> [\t-\n\r\ ];
start syntax Prog = prog: Exp LAYOUTLIST;
syntax Exp =
var: Ident
| nat: Natural
| bracket "(" Exp ")"
> left app: Exp Exp
> right func: "fun" Ident "-\>" Exp
当我解析以下形式的程序时:
(fun x -> fun y -> x) 1 2
生成的树是:
prog(app(
app(
func(
"x",
func(
"y",
var("x")
nat(1),
nat(2))))))
我真的在哪里寻找这样的东西(我认为):
prog(app(
func(
"x",
app(
func(
"y",
var("x")),
nat(2))),
nat(1)))
我尝试了语法中优先级的多种变体,我尝试了将 App 规则括在括号中,以及许多其他变体。这里似乎发生了一些我不明白的事情。非常感激任何的帮助。谢谢
我使用了以下语法,它删除了多余的 LAYOUTLIST
和死的 right
,但这应该没有什么区别。当我使用通用 implode
函数时,它似乎如你所愿地工作:
keyword Keywords= "if" | "then" | "else" | "end" | "fun";
lexical Ident = [a-zA-Z] !>> [a-zA-Z]+ !>> [a-zA-Z0-9] \ Keywords;
lexical Natural = [0-9]+ !>> [0-9];
lexical LAYOUT = [\t-\n\r\ ];
layout LAYOUTLIST = LAYOUT* !>> [\t-\n\r\ ];
start syntax Prog = prog: Exp;
syntax Exp =
var: Ident
| nat: Natural
| bracket "(" Exp ")"
> left app: Exp Exp
> func: "fun" Ident "-\>" Exp
;
然后调用解析器并分解为无类型的 AST(为了便于阅读,我删除了位置注释):
rascal>import ParseTree;
ok
rascal>implode(#node, parse(#start[Prog], "(fun x -\> fun y -\> x) 1 2"))
node: "prog"("app"(
"app"(
"func"(
"x",
"func"(
"y",
"var"("x"))),
"nat"("1")),
"nat"("2")))
所以,我猜你的语法适合你想要的树的形状。你如何从具体的解析树到抽象的 AST?也许那里发生了一些有趣的事情。