1

背景:

我正在学习软件语义方面的课程,我们应该为一种名为while的玩具语言创建一个小型编译器和运行时。我们得到了 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 循环的主体由复合语句组成,这不是我想要的。我应该如何设置我的优先规则来达到这个效果?

4

2 回答 2

3

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

如果规则是

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

不会有歧义。你知道的任何常规语言中的复合语句都有开始和结束标记是有原因的。就是这个。

于 2013-04-28T11:48:43.537 回答
0

原来我误解了我的任务,有点。我描述的优先规则是在我的课程书中介绍的,但由于我主要关心的是与老师给我们的解析器兼容,我在上面的代码上进行了尝试,它也将作业解析到正文中.

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

(while true do skip) ; x := y

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

于 2013-04-28T13:25:10.440 回答