无法 fix/understand 一个简单的 "shift/reduce conflict" 野牛
Unable to fix/understand a simple "shift/reduce conflict" of bison
我正在尝试消除 Bison 语法文件中的所有冲突。我无法理解有几个实例的冲突来源。我缩小了问题的范围并创建了这个小的 Bison 文件来准确说明原始文件中出现的问题:
注意:自首次发布以来代码已更改。
%token terminalA terminalB
%token INTEGER
%%
START : startEntries
startEntries: terminalBLine
terminalALines //Optional
{
}
terminalALines : terminalALine
| terminalALines terminalALine
| //To allow terminalALine to be not present at all.
terminalALine : terminalA INTEGER
terminalBLine : terminalB INTEGER
%%
~
运行 bison 文件输出:
bison -v -y test.y
test.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
是的,我知道用于查看冲突的 -v 选项。 .output 文件中的相关部分是:
State 4
2 startEntries: terminalBLine . terminalALines
terminalA shift, and go to state 7
terminalA [reduce using rule 5 (terminalALines)]
$default reduce using rule 5 (terminalALines)
terminalALines go to state 8
terminalALine go to state 9
如果我删除带有独奏“|”的注释行那么冲突就解决了。但是没有 terminalALines 也是有效的输入,我相信如果我删除“|”将不可能线。
如果我将注释行移动到 "terminalALine : terminalA INTEGER" 之后的行,它应该有相同的目的(?)但会导致更多的冲突。
我删除了所有错误处理和操作语句以专注于核心问题。
我在发布问题后意识到前缀 "terminal" 没有语义含义。
让我们关注规则:
terminalALines : terminalALine
| terminalALines terminalALine
| //To allow terminalALine to be not present at all.
terminalALine : terminalA INTEGER
假设我的输入是 terminalA INTEGER
.
terminalALines
允许递归 terminalALines
。此外,terminalALines
可以为空。所以让我们从解析一个空的 terminalALines
开始,然后递归。现在,terminalALines
可以以 terminalALines
开头,它可以是空的,所以...
错误或多或少是说,如果它试图解析 terminalALines
并看到 terminalA
标记,它无法决定是否递归 运行 terminalALines
再次规则或从中解析单个 terminalALine
。
您可以通过重新安排规则使递归大小写为 second
来解决此问题
terminalALines : terminalALine terminalALines
| // empty
terminalALine : terminalA INTEGER
现在如果你看到 terminalA
,事情就很清楚了:你必须解析出一个 terminalALine
,然后寻找另一个 terminalALines
,它可能为空也可能不为空。
我正在尝试消除 Bison 语法文件中的所有冲突。我无法理解有几个实例的冲突来源。我缩小了问题的范围并创建了这个小的 Bison 文件来准确说明原始文件中出现的问题:
注意:自首次发布以来代码已更改。
%token terminalA terminalB
%token INTEGER
%%
START : startEntries
startEntries: terminalBLine
terminalALines //Optional
{
}
terminalALines : terminalALine
| terminalALines terminalALine
| //To allow terminalALine to be not present at all.
terminalALine : terminalA INTEGER
terminalBLine : terminalB INTEGER
%%
~
运行 bison 文件输出:
bison -v -y test.y
test.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
是的,我知道用于查看冲突的 -v 选项。 .output 文件中的相关部分是:
State 4
2 startEntries: terminalBLine . terminalALines
terminalA shift, and go to state 7
terminalA [reduce using rule 5 (terminalALines)]
$default reduce using rule 5 (terminalALines)
terminalALines go to state 8
terminalALine go to state 9
如果我删除带有独奏“|”的注释行那么冲突就解决了。但是没有 terminalALines 也是有效的输入,我相信如果我删除“|”将不可能线。 如果我将注释行移动到 "terminalALine : terminalA INTEGER" 之后的行,它应该有相同的目的(?)但会导致更多的冲突。
我删除了所有错误处理和操作语句以专注于核心问题。
我在发布问题后意识到前缀 "terminal" 没有语义含义。
让我们关注规则:
terminalALines : terminalALine
| terminalALines terminalALine
| //To allow terminalALine to be not present at all.
terminalALine : terminalA INTEGER
假设我的输入是 terminalA INTEGER
.
terminalALines
允许递归 terminalALines
。此外,terminalALines
可以为空。所以让我们从解析一个空的 terminalALines
开始,然后递归。现在,terminalALines
可以以 terminalALines
开头,它可以是空的,所以...
错误或多或少是说,如果它试图解析 terminalALines
并看到 terminalA
标记,它无法决定是否递归 运行 terminalALines
再次规则或从中解析单个 terminalALine
。
您可以通过重新安排规则使递归大小写为 second
来解决此问题terminalALines : terminalALine terminalALines
| // empty
terminalALine : terminalA INTEGER
现在如果你看到 terminalA
,事情就很清楚了:你必须解析出一个 terminalALine
,然后寻找另一个 terminalALines
,它可能为空也可能不为空。