我正在学习软件语义课程,我们应该为一种名为而的玩具语言创建一个小编译器和运行时。 我们获得了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循环的主体由复合语句组成,这不是我想要的。我应该如何设置我的优先规则才能达到这个效果?
答案 0 :(得分:3)
我认为问题在于Scomp是一种Stmt,无法在词汇上将它与简单的Stmt区分开来。
如果规则是
Scomp. Stmt ::= "{" Stmt ";" Stmt "}";
没有歧义。您知道的任何常规语言的复合语句都有开始和结束标记的原因;就是这样。
答案 1 :(得分:0)
事实证明我误解了我的任务。 我描述的优先规则是我的课程书中提供的规则, 但由于我主要关注的是与老师给出的解析器兼容,我在上面的代码中尝试了它,并且它也将分配解析到了正文中。
我想写的程序应该“简单地”:
(while true do skip) ; x := y
但是嘿,至少它是兼容的!