我被困在调试杯语法上了。
因此,我在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
;lexer正在向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(只有一个单词的行表示对lexer的调用,从而打印出标记。带有杯规则的行表示正在匹配的规则。第7行是带有while语句的行。)
这些块似乎是失败的原因;当我将所有的块从提供给语法的东西中移除时,一切都会像我预期的那样被解析。
但是,我不明白为什么没有正确地分析这些块。
对于什么是问题,或者如何进一步测试,有什么想法吗?
编辑:如果你需要一个细节,我可能已经省略了答案,完整的代码是可用的这个回购
发布于 2018-05-11 20:52:32
你的语法使用分号的方式有点不正统。这会给你带来麻烦。
特别是,除了语句之间,分号似乎在任何地方都是可选的。所以这两个都没问题
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,而不是分号,这是语法错误。
https://stackoverflow.com/questions/50297794
复制相似问题