0

我正在尝试使用 JFlex 和 Cup 编写解析器,但是我在处理递归指向符号时遇到了一些问题,例如使用递归属性访问的函数调用,例如:

var x = obj.property1.functionCall(p1, p2).property2;

这是相关的解析器定义:

unary_exp ::= postfix_exp
              | ADD2 unary_exp
              | SUB2 unary_exp
              | unary_operator unary_exp;

unary_operator ::=  ADD
                    | SUB
                    | BIT_NOT
                    | NOT;

postfix_exp ::= primary_exp
                | postfix_exp LPAR_SQ right_value_exp RPAR_SQ
                | postfix_exp LPAR optional_postfix_exp_list RPAR
                | postfix_exp DOT postfix_exp
                | postfix_exp SUB2
                | postfix_exp ADD2;

primary_exp ::= BOOL
                | STRING
                | INTEGER
                | NUMBER
                | NULL;

我得到了以下班次/减少冲突:

Warning : *** Shift/Reduce conflict found in state #190
  between postfix_exp ::= postfix_exp DOT postfix_exp (*) 
  and     postfix_exp ::= postfix_exp (*) LPAR optional_postfix_exp_list RPAR 
  under symbol LPAR
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #190
  between postfix_exp ::= postfix_exp DOT postfix_exp (*) 
  and     postfix_exp ::= postfix_exp (*) LPAR_SQ right_value_exp RPAR_SQ 
  under symbol LPAR_SQ
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #190
  between postfix_exp ::= postfix_exp DOT postfix_exp (*) 
  and     postfix_exp ::= postfix_exp (*) DOT postfix_exp 
  under symbol DOT
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #190
  between postfix_exp ::= postfix_exp DOT postfix_exp (*) 
  and     postfix_exp ::= postfix_exp (*) ADD2 
  under symbol ADD2
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #190
  between postfix_exp ::= postfix_exp DOT postfix_exp (*) 
  and     postfix_exp ::= postfix_exp (*) SUB2 
  under symbol SUB2
  Resolved in favor of shifting.

Error : *** More conflicts encountered than expected -- parser generation aborted

有人可以向我解释如何处理这些冲突,或者在哪里可以找到使用 java cup、yacc 或 bison 的工作示例?

4

1 回答 1

1

你的语法包括这个产生:

postfix_exp ::= postfix_exp DOT postfix_exp

你认为这准确吗?的右操作数 .可以是任意的后缀表达式吗?如果是这样,是什么a.3意思?怎么样x.false?(Aprimary_exp是 a postfix_exp,对吗?这就是语法所说的。)

言归正传,是什么意思a.b++b++的操作数有什么意义.吗?肯定b是 的成员的名称a,而不是自变量。

语法即使没有实现语义也能传达意义。它们指定表达式的不同部分相互关联的方式。(“Parse”和“parts”听起来很相似,因为动词“parse”来自名词“part”,如“to split into parts”。)所以你应该努力使你的语法与语言的结构相对应。

现在,任何时候你看到这样的作品:

foo ::= foo OPERATOR foo;

你知道语法是模棱两可的。它是模棱两可的,因为它为OPERATOR. 例如,如果OPERATOR是,-它将与. 语法歧义总是表现为解析表冲突。(1 - 1) - 1foo11 - (1 - 1)

解决歧义很重要,因为这两个表达式具有不同的值。这就是为什么我们要么必须使用表达式类型的层次结构,要么必须使用运算符优先级声明。(所以我们知道如何解决关联性问题。)

但是在.运算符的情况下,我们确实没有未指定关联性的二元运算符。我们根本没有真正的二元运算符,这就是为什么这里的产生式被称为postfix_exp. 运算符是一个字段选择器,我们可以将其视为不同后缀运算符的集合,一个对应于适当复合类型的每个成员名称。

这就是这里的简单答案。一旦我们说字段选择器具有 form DOT IDENTIFIER,歧义就消失了。

于 2020-10-18T22:35:34.760 回答