语法冲突:可能采取多种行动

时间:2016-04-23 16:23:01

标签: parsing bison lalr jison

我已经尝试用jison(http://zaa.ch/jison/docs/)编写简单的解析器来处理描述文本。

%lex

%%
[\s\n\t]+                   return 'TK_SPACE';
[0-9]+("."[0-9]+)?\b        return 'TK_NUMBER';
[a-zA-Z]+([a-zA-Z0-9]+)?\b  return 'TK_WORD';
<<EOF>>                     return 'EOF';

/lex

%start document

%%

document
  : nodes EOF
    { console.log($1); }
  | EOF
  ;

nodes
  : nodes node
    { $1.push($2); $$ = $1; }
  | node
    { $$ = [$1]; }
  ;

node
  : text
  ;

text
  : text text_element
    { $$ = $1 + $2; }
  | text_element
  ;

text_element
  : TK_NUMBER
  | TK_WORD
  | TK_SPACE
  ;

这个语法汇编了警告。

Conflict in grammar: multiple actions possible when lookahead token is TK_SPACE in state 5
- reduce by rule: node -> text
- shift token (then go to state 9)
Conflict in grammar: multiple actions possible when lookahead token is TK_WORD in state 5
- reduce by rule: node -> text
- shift token (then go to state 8)
Conflict in grammar: multiple actions possible when lookahead token is TK_NUMBER in state 5
- reduce by rule: node -> text
- shift token (then go to state 7)

States with conflicts:
State 5
  node -> text . #lookaheads= TK_SPACE TK_WORD TK_NUMBER EOF
  text -> text .text_element #lookaheads= EOF TK_NUMBER TK_WORD TK_SPACE
  text_element -> .TK_NUMBER
  text_element -> .TK_WORD
  text_element -> .TK_SPACE

但是,如果我尝试解析文本,它可以正常工作。这不是完整版本的代码,只是带有文本的版本。我想在功能中添加node处的节点。

1 个答案:

答案 0 :(得分:4)

问题是你的语法含糊不清 - nodes由一个序列组成,或者模式node没有分隔符。 nodetext,它由一个或多个text_element组成,没有分隔符。因此,当一个node结束而下一个开始时,无法判断。

例如,如果您输入的序列为3 text_elements,那么它可能是一个node全部为3,或者可能是3 node,每个都有一个

野牛会解决问题&#34;这种冲突始终倾向于转换为reduce,它总是倾向于生成更大的text对象,因此规则nodes: nodes node永远不会减少,也可能只是从语法中删除。由于这是一个纯粹的模糊性(不是前瞻性问题),因此得到的语法匹配相同的语言,因此这可能不是问题。我认为jison(或者你实际使用的任何解析器生成器)是相同的。

但是,一般情况下,冲突是一个问题,因为它意味着生成的解析器解析的语法不是您指定的语法。弄清楚生成的解析器实际解析了什么语法是非常重要的,需要仔细了解shoft-reduce解析的工作原理以及解析器生成器实际生成的状态。这些信息都在.output文件中(由bison与-v生成 - 其他生成器可能不同),但您需要阅读并理解它。