调试 CUP 语法



我在调试 CUP 语法时遇到了困难。

所以我在 CUP 中有以下语法:

/* Integer operators */
precedence left SUM_OP, SUBS_OP;
precedence left PROD_OP, DIV_OP;
/* Boolean operators */
precedence left EQ_OP, LT_OP, GT_OP, LET_OP, GET_OP;
precedence left OR_OP;
precedence left AND_OP;
start with statements;
statements ::= statement:s 
| statement:s SEPARATOR
| SEPARATOR // Empty statement
| statement:s SEPARATOR statements:ss 
;
statement  ::= IF expression:e SEPARATOR statement:s
| IF expression:e statement:s
| IF expression:e SEPARATOR then_statement:then ELSE SEPARATOR statement:els 
| IF expression:e then_statement:then ELSE SEPARATOR statement:els 
| IF expression:e SEPARATOR then_statement:then ELSE statement:els 
| IF expression:e then_statement:then ELSE statement:els 
| WHILE expression:e SEPARATOR statement:s
| WHILE expression:e statement:s
| non_if_statement:s
;
then_statement ::= IF expression:e SEPARATOR then_statement:then ELSE SEPARATOR then_statement:els 
| IF expression:e then_statement:then ELSE SEPARATOR then_statement:els 
| IF expression:e SEPARATOR then_statement:then ELSE then_statement:els 
| IF expression:e then_statement:then ELSE then_statement:els 
| WHILE expression:e SEPARATOR then_statement:s
| WHILE expression:e then_statement:s
| non_if_statement:s
;
non_if_statement ::= START_BLOCK statements:s END_BLOCK
| declaration:d
| assignment:a
;
// The statement vs then_statement is for disambiguation purposes
// Solution taken from http://goldparser.org/doc/grammars/example-if-then-else.htm
/* Variable manipulation statements */
declaration ::= type:t IDENTIFIER:id 
| type:t IDENTIFIER:id ASSIGN_OP expression:rhs 
;
assignment  ::= variable:lhs ASSIGN_OP expression:rhs
;
/* Variable manipulation auxiliar sintactic elements */
type       ::= T_INT 
| T_BOOL 
| type:t T_ARRAY 
;
variable   ::= IDENTIFIER:id 
| variable:id LBRACKET expression:idx RBRACKET
;
/* Integer or bool expressions */
expression ::= variable:v 
| LPAREN expression:e RPAREN
// Int expressions
|  INTEGER_LITERAL:c 
| expression:op1 SUM_OP expression:op2 
| expression:op1 SUBS_OP expression:op2 
| expression:op1 PROD_OP expression:op2 
| expression:op1 DIV_OP expression:op2 
// Bool expressions
| BOOL_LITERAL:c
| expression:op1 OR_OP expression:op2 
| expression:op1 AND_OP expression:op2 
| NOT_OP expression:op1 
| expression:op1 EQ_OP expression:op2 
| expression:op1 LT_OP expression:op2 
| expression:op1 GT_OP expression:op2 
| expression:op1 LET_OP expression:op2 
| expression:op1 GET_OP expression:op2 
;

词法分析器将以下令牌提供给 CUP 分析器:

int id:i = intLiteral ;    
{ 
if id:i == intLiteral id:i = intLiteral ;
} 

while id:i < intLiteral ;
{ 
id:i = id:i + intLiteral ;
} 
if id:i <= intLiteral ;    
{ 
bool id:a ;
bool id:b = boolLiteral ;
} 
else ;
{ 
int id:j = intLiteral ;
} 
if id:i >= intLiteral ;
{ 
id:i = id:i - intLiteral ;
{ 
id:i = intLiteral + intLiteral ;
} 
} 
else if id:i > intLiteral id:i = intLiteral ;
else id:i = intLiteral 

(;SEPARATOR{ }消除块的位置。

当我运行它时,我得到以下输出:

int 
id:i
type ::= T_INT
= 
intLiteral 
;
expression ::= INTEGER_LITERAL
declaration ::= type IDENTIFIER ASSIGN_OP expression
non_if_statement ::= declaration
statement ::= non_if_statement
{ 
if 
id:i
== 
variable ::= IDENTIFIER
expression ::= variable
intLiteral 
id:i
expression ::= INTEGER_LITERAL
expression ::= expression EQ_OP expression
= 
variable ::= IDENTIFIER
intLiteral 
;
expression ::= INTEGER_LITERAL
assignment ::= variable ASSIGN_OP expression
non_if_statement ::= assignment
statement ::= non_if_statement
statement ::= IF expression statement
} 
statements ::= statement SEPARATOR
while 
Error in line 7, column 1 : Syntax error
Error in line 7, column 1 : Couldn't repair and continue parse

(带有单个单词的行表示对导致打印令牌的词法分析器的调用。带有 CUP 规则的行表示要匹配的规则。第 7 行是带有 while 语句的那行。

似乎块是失败的原因;当我从提供给语法的内容中删除所有块时,一切都按我预期解析。

但是,我不明白为什么没有正确解析块。

关于可能是什么问题或如何进一步测试的任何想法?

编辑:如果您需要我可能省略回答的细节,此存储库中提供了完整的代码

你的语法使用分号的方式有点不正统。它给你带来了麻烦。

特别是,除了语句之间之外,分号似乎在任何地方都是可选的。所以这两个都可以

while i < 3; i = i + 1;   // ex. 1
while i < 3 i = i + 1;    // ex. 2

但你不能写

i = 2 j = 3              // ex. 3

尽管这并不比上面的例2模棱两可。

无分号的语法看起来不那么奇怪:

while i < 3;  { i = i + 1;  } // ex. 4
while i < 3 { i = i + 1;  }  // ex. 5
{ i = 2 } { j = 3 }            // ex. 6 Still illegal

为了被解析,示例 6 需要用分号编写,在我看来,这很丑陋且不必要:

{ i = 2 } ; { j = 3 }            // ex. 7

这就是您的解析器所抱怨的。即使第 2-4 行的语句是大括号括起来的,所以毫无疑问它在哪里结束,你的语法坚持使用分号。但是下一个标记是while,而不是分号,这是一个语法错误。

相关内容

  • 没有找到相关文章

最新更新