如何解决这个S / R冲突

时间:2013-12-21 19:43:30

标签: bison lr shift-reduce-conflict jison

这是我工作的EBNF语法的简化:

%token NEWLINE BLOCK_MARK A
%start file

file: block+ NEWLINE*;
block: BLOCK_MARK line;
line: A+;

\ n \ n和\ n \ EOF都将NEWLINE作为代币吐出(因此在EOF之前不需要单个结束NEWLINE)。它适用于这样的流:

BLOCK_MARK A A BLOCK_MARK A NEWLINE[actually EOF]

现在我希望在line中有多个block,其中至少有一个是强制性的,其余的则用NEWLINE分隔。 E.g:

BLOCK_MARK A A NEWLINE A A BLOCK_MARK A A A EOF

我试过这样做:

file: block+ NEWLINE*;
block: BLOCK_MARK line moreline*;
line: A+;
moreline: NEWLINE line;

但是当前瞻是NEWLINE时,Jison抱怨S / R冲突。我想状态机很困惑,决定NEWLINE是否是新line的一部分或NEWLINE*中的最终file(这是必需的,因为文件可以以NEWLINE / EOF)。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

你想要的是将换行符作为前一行的一部分,在看到换行符之前推迟减少除行之外的任何内容。所以你最终得到:

file: block+ ;
block: BLOCK_MARK line_nl+ line_nonl? | BLOCK_MARK line_nonl ;
line_nl: line NEWLINE ;
line_nonl: line ;
line: A+ ;

现在唯一的问题是它不允许任何空白行(空行会出现语法错误)。但这与你的原始语法相同。

答案 1 :(得分:0)

根据克里斯多德的想法,但在我的第一次尝试中反转。基本想法就是删除NEWLINE*处的fileline已经涵盖了file: block+; block: BLOCK_MARK line_nonl line_nl* NEWLINE?; line_nl: NEWLINE line_nonl; line_nonl: A+;

{{1}}

我认为这个解决了所有情况。