解决jison中的S / R冲突

时间:2017-07-29 18:57:39

标签: jison

我已经在jison中编写了一个非常简单的解析器,但是这个语法中似乎存在S / R冲突:

/* lexical grammar */
%lex
%%

\s+                   /* skip whitespace */
":"                   return ':'
"."                   return '.'
[a-zA-Z_][a-zA-Z0-9_]* return 'IDENTIFIER'
<<EOF>>               return 'EOF'
.                     return 'INVALID'

/lex
/* operator associations and precedence */


%start expressions

%% /* language grammar */

expressions
    : statements EOF
        {return $1;}
    ;

statements: statements statement {$$ = [$1].concat($2);} | statement {$$ =
 [$1];};

statement:
    IDENTIFIER ":" grammar_and {[$$ = ["grammar_rule",$1,$3]]};

grammar_and:
    grammar_and IDENTIFIER {$$= [$1,$2]} | IDENTIFIER;

它旨在解析像这样的文档,其中包含4个语句:

first: this is a sentence
second: this is another sentence
something: more words here another: more words here

但它没有像我预期的那样工作:

Conflicts encountered:
Resolve S/R conflict (shift by default.)
(1,10, 2,4) -> 1,10

是否可以在不修改正在解析的语言的语法的情况下解决此冲突?

1 个答案:

答案 0 :(得分:1)

所写的语法(实际上,该语言的任何合理语法)是LR(2),因为无法知道IDENTIFIERgrammar_and的延续还是开始新的statement,直到检查到以下标记。在第二种情况下,有必要减少statement,并且不能使用单个令牌预测来做出决定。

这是一个经典的LR(2)语法 - 事实上,它是野牛制作的自然语法 - 并且有很多方法可以解决它。

语言本身是LR(1)。实际上,没有诸如LR(2)语言之类的东西,因为可以从任何LR(k)语法机械地产生LR(1)语法。 How do I rewrite a context free grammar so that it is LR(1)?的答案中提供了如何使用基本相同的语法执行此操作的示例。

一个更简单的解决方案,类似于大多数yacc-alikes所使用的解决方案,是在词法扫描器中添加额外的前瞻(或者在扫描器和解析器之间使用垫片)。 flex&bison shift/reduce conflict的答案中提供了执行此操作的C代码示例。 (问题不完全相同,但我认为解决方案可以进行调整。)