我需要编写一个检查F1类型系统类型的程序,而且我不知道如何制定能够建立正确关联运算符的规则。
我需要的是,如果我解析像Nat这样的东西 - > Nat - > Nat,应解析为Nat - > (Nat - > Nat),而不是(Nat - > Nat) - > Nat(我想建立一个AST并做一些事情)
我现在拥有的是:
Node Type2() {Node t1;}
{
"Nat" { return Node("Nat", null, null);}
|
"Bool" { return Node("Bool", null, null);}
|
"(" t1=Type() ")" {return t1;}
}
Node Type() {Node t1; Node t2;}
{
t1 = Type2() (" -> " t2 = Type2() { return Node("->", t1, t2); }
}
但它是关联的,我怎么能做到这一点?
语法是:
type = "Bool" | "Nat" | type, "->", type | "(", type, ")";
lambda_expression = variable
| "\", variable, ":", type, ".", lambda_expression
| lambda_expression, " ", lambda_expression
| "(", lambda_expression, ")";
type_context = variable, ":", type, { ",", variable, ":", type };
expression = [ type_context ], "|-", lambda_expression, ":", type;
感谢
答案 0 :(得分:0)
使用循环代替递归
Node Type() :
{Node t1; Node t2;}
{
t1 = Type2()
( " -> "
t2 = Type2()
{ t1 = Node("->", t1, t2); }
)*
{return t1 ; }
}
或者 - 相同的东西 - 使用正确的递归。
Node Type() :
{Node t1;}
{
t1 = Type2()
t1 = MoreType( t1 ) ;
{return t1 ; }
}
Node MoreType(Node t1) :
{Node t2;}
{
" -> " t2 = Type2() t1 = MoreType( new Node( "->", t1, t2 ) ) {return t1; }
|
{return t1; }
}
答案 1 :(得分:0)
以下是直接使用LL(1)语法的解决方案:
Type2 =
| "Nat"
| "Bool"
| "(" Type ")"
Type =
| Type2 ( "->" Type )?
以解析Nat -> Bool -> Nat
为例:
Type
开始,Nat
与Type2
匹配。->
,因此它知道( ... )?
中的所有内容都应被解析而不是被忽略。现在,它尝试将Type
与其余的Bool -> Nat
递归匹配。Type
的递归解析中,首先,Bool
与Type2
匹配,然后解析器看到->
。因此,它再次尝试将Type
与其余输入Nat
进行递归匹配。Type
的第三次解析中,Nat
与Type2
匹配,但是解析器在其后看不到->
,因此决定忽略{{1} }并终止。在上面的解析中,( ... )?
在步骤2〜4中一起解析,Bool -> Nat
在步骤1〜4中一起解析。这样就获得了正确的关联性。
对应的JavaCC代码:
Nat -> (Bool -> Nat)