我如何消除同一操作员的转移冲突



我打算使用野牛解析一些脚本语言,用这种语言,我可以写下代码:

a = input()
b = a + 1
function myfunc
    a = input()
    b = a + 1
end function

我发现块

a = input()
b = a + 1

可以通过相同的规则stmts降低功能定义的出现和外出,因此我像以下代码一样编写代码

%{
#include <stdio.h>
#include <string>
#include <sstream>
#include <iostream>
#include <stdarg.h>
#include <tuple>
using namespace std;
%}
%debug
%token CRLF EXP FUNCTIONBEGIN FUNCTIONEND
%start program
%%
stmt : EXP
    |
stmts : stmt CRLF stmts
    | stmt
function : FUNCTIONBEGIN CRLF stmts CRLF FUNCTIONEND
unit : function
    | stmts
program : unit
    | unit CRLF program
%%

当然,由于一次轮班/减少冲突

,此代码无法工作
State 3
    3 stmts: stmt . CRLF stmts
    4      | stmt .
    CRLF  shift, and go to state 9
    CRLF      [reduce using rule 4 (stmts)]
    $default  reduce using rule 4 (stmts)

我认为这种冲突既是我的program规则和stmts规则都使用相同的终端CRLF作为"二进制运算符",因此我无法通过将优先级设置为操作员来解决这一冲突。

也许我可以通过以某种方式将另外两个规则添加到STMT

来合并program规则和stmts规则
stmts : function CRLF stmts
    | function

但是,我认为这种方法(是否可以实际工作)不是很漂亮,所以我问是否还有其他解决方案

问题与CRLF令牌无关。相反,这是您对program的定义。program是一系列unit s,每个单元是functionstmts。但是stmts不是一个"单位",这是由于其名称是复数的事实所暗示的。stmts是一系列stmt s。

因此,假设我们有一个由三个语句组成的程序。那是多少 unit s?它是由所有三个语句组成的stmts吗?还是其中两个,一个带有两个陈述,另一个只有一个?还是另一方面?甚至三个unit s,每个s由包含单个语句的stmts组成?

解析器无法说出这些选择中的哪个是因为语法模棱两可。这就是造成冲突的原因。

最简单的解决方案是将生产unit: stmts更改为单数:unit: stmt。然后就没有歧义。三键program完全具有三个unit s,每个stmt

顺便说一句,在编写LR语法时,您应该始终更喜欢左递归。正确的递归通常不会造成冲突,它与您当前的问题无关,但是它确实导致了不必要的IARGE解析堆栈,并且降低诸如unitsstmts之类的列表将从右至左执行的组件执行从堆栈中弹出,通常不是意图的。

相关内容

  • 没有找到相关文章

最新更新