【问题标题】:Shift/reduce LALR(1) conflict due to parentheses由于括号而移位/减少 LALR(1) 冲突
【发布时间】:2017-02-23 00:01:43
【问题描述】:

我目前正在编写一个类似于 Visual Basic 的 LALR(1) 语法,并面临这个特殊的移位/减少冲突,我不知道如何正确解决它。

语法有问题的部分是(请参阅 EDIT 1EDIT 2 进行澄清):

Expression
    : IndexExpression
    | /* other expressions */

IndexExpression
    : MemberExpression
    | MemberExpression '(' ArgumentList ')'

MemberExpression
    : ParenthesizedExpression
    | Identifier

ParenthesizedExpression
    : '(' Expression ')'

ArgumentList
    : Expression
    | Expression ',' ArgumentList
    | ',' ArgumentList

移位/减少冲突是这样的:

State 109
  237 ParenthesizedExpression: '(' Expression ')' .
    $default    reduce using rule 237 (ParenthesizedExpression)

...
State 295

  231 IndexExpression: MemberExpression '(' . ArgumentList ')'
  237 ParenthesizedExpression: '(' . Expression ')'
    ...
    Expression    go to state 352

...
State 352
  182 ArgumentList: Expression .
  183             | Expression . ',' ArgumentList
  237 ParenthesizedExpression: '(' Expression . ')'
    ...
    ')'    shift, and go to state 109

    ')'    [reduce using rule 182 (ArgumentList)]

换句话说,解析器在面对一个用括号包裹的表达式时,不确定它是带有单个表达式的 ArgumentList 还是 ParenthesizedExpression

有没有办法解决这个冲突,同时保持语法为 LALR(1)?

谢谢。

编辑 1:

/* 其他表达式 */ in Expression 其实并不是空的表达式,我只是为了简洁而写成这样。实际上它还有其他替代表达方式:

Expression
    : IndexExpression
    | Expression '+' Expression
    | ...

编辑 2:

以下是@rici 指出可能有问题的语法的其他部分(尤其是语句的第一右手规则):

Statement
    : MemberExpression ArgumentList
    | MemberExpression '=' Expression
    | MemberExpression '(' ArgumentList ')' '=' Expression
    | ...

【问题讨论】:

  • 你需要展示更多你的语法。或者,更好的是,创建一个真正可编译的语法,具有相同的问题,但只有几个产生式。顺便说一句,argument_list 语法很奇怪。为什么您发现使用左递归编写它很有用,而在 LALR(1) 解析器中通常应该避免这种情况?多个缺失的参数是什么意思?如果所有其他参数都可以省略,为什么最后一个参数不能呢?
  • 您是否允许使用 VB 语法,其中可以在不带括号的情况下调用带有一个参数的函数?如果是这样,那很可能是您的问题。
  • @rici 缺少参数:在这个特殊的 VB 方言中,它允许参数列表有空参数,除了最后一个。因为我真的不希望 Expression 为空,所以我最终将第三条规则放在 ArgumentList 上。 一个不带括号的参数:是的!事实上,在昨天更深入地寻找根本原因之后,我得出一个结论,这可能是原因。您对如何包含此语法有任何建议吗?
  • 当您只能看到一小部分语法时,很难对语法提出建议。这是关于帮助其他人解决问题的一般性声明;如果您只是提供少量信息,则很难为您提供帮助,因为我们必须花时间尝试推断或猜测您没有解释的问题部分。提问的最佳方式是发送minimal reproducible example,这也是开始自己解决问题的好方法,因为它关注的是真正重要的事情(而不是你认为可能有趣的事情)。
  • 我没有从您提供的小摘录中看到任何明显的冲突路径,但可能是您有另一种以表达式开头的语句类型。顺便说一句,我认为用ParenthesizedExpression: '(' Expression ')' 之类的作品来夸大你的语法并不是一种好的风格。这就是冗余评论综合症的语法(++count; /* Increase the count by 1 */

标签: grammar bison yacc lalr


【解决方案1】:

错误是因为Expression被允许为空,因为注释规则/* other expressions */,并且假定不为空。

下面显示了使用Expression 导致两个等效规则的位置:

ArgumentList
    : Expression
    | Expression ',' ArgumentList /* degenerates into "',' ArgumentList" */
    | ',' ArgumentList
    ;

移位/减少冲突的次数是引用ArgumentList 的次数(一次在IndexExpression 中,两次在ArgumentList 本身中)

要消除冲突,请修复 ArgumentList 以解决空 Expression 的情况:

ArgumentList
    : Expression
    | ArgumentList ',' Expression
    ;

或者确保Expression 永远不会为空(删除注释规则)。

【讨论】:

  • 您好 kdhp,请参阅我的编辑 1 进行澄清。很抱歉在我的原始帖子中含糊不清。
  • @SamTatasurya 没有看到表达式列表我只能猜测要么有另一个空值,要么没有将运算符声明为%left/%right,要么有第二条规则@ 987654334@(也通过IndexExpression->MemeberExpression->ParenthesizedExpression出席)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多