在BNFC语法中设置优先级

时间:2013-04-28 11:35:59

标签: grammar lalr bnfc

背景:

我正在学习软件语义课程,我们应该为一种名为的玩具语言创建一个小编译器和运行时。 我们获得了Java的代码框架,但我们可以使用我们想要的任何语言。 我认为这是一个排练语法的机会,并认为用C ++实验室很酷。

现在,我在为语句设置优先规则时遇到了一些问题。 这是我的BNFC语法文件:

SSkip.  Stmt    ::= "skip";
SAss.   Stmt    ::= VarName ":=" AExp;
SIf.    Stmt1   ::= "if" BExp "then" Stmt "else" Stmt;
SWhile. Stmt1   ::= "while" BExp "do" Stmt;
SComp.  Stmt    ::= Stmt ";" Stmt;
coercions Stmt 1;

token VarName   (letter (letter | digit) *);

EAdd.   AExp    ::= AExp "+" AExp1;
ESub.   AExp    ::= AExp "-" AExp1;
EMul.   AExp1   ::= AExp1 "*" AExp2;
EDiv.   AExp1   ::= AExp1 "/" AExp2;
EInt.   AExp2   ::= Integer;
EVar.   AExp2   ::= VarName;

coercions   AExp    2;

BTrue.  BExp1   ::= "true";
BFalse. BExp1   ::= "false";
BNeg.   BExp    ::= "not" BExp;
BConj.  BExp    ::= BExp "and" BExp;
BLeq.   BExp    ::= AExp "<=" AExp;

coercions BExp 1;

我想要的是输入

while true do skip; x:=y

根据我的复合规则解析为

(SComp [SWhile [BTrue] [SSkip]] [(SAss "x" [EVar "y"])])

也就是说,我希望赋值不是循环体的一部分。 但是,我得到的是

(SWhile [BTrue] [(SComp SSkip (SAss "x" [(EVar "y")]))])

正如您所看到的,while循环的主体由复合语句组成,这不是我想要的。我应该如何设置我的优先规则才能达到这个效果?

2 个答案:

答案 0 :(得分:3)

我认为问题在于Scomp是一种Stmt,无法在词汇上将它与简单的Stmt区分开来。

如果规则是

Scomp. Stmt ::= "{" Stmt ";" Stmt "}";

没有歧义。您知道的任何常规语言的复合语句都有开始和结束标记的原因;就是这样。

答案 1 :(得分:0)

事实证明我误解了我的任务。 我描述的优先规则是我的课程书中提供的规则, 但由于我主要关注的是与老师给出的解析器兼容,我在上面的代码中尝试了它,并且它也将分配解析到了正文中。

我想写的程序应该“简单地”:

(while true do skip) ; x := y

但是嘿,至少它是兼容的!