2013-04-04 64 views
4

我正在Jison寫一個簡單的表達式分析器。下面是我的語法:這個語法是如何模糊的?

{ 
    "operators": [ 
     ["left", "+", "-"], 
     ["left", "*", "/", "%"] 
    ], 
    "bnf": { 
     "program": [ 
      ["statement EOF", "return $1;"] 
     ], 
     "statement": [ 
      ["expression NEWLINE", "$$ = $1 + ';';"] 
     ], 
     "expression": [ 
      ["NUMBER",      "$$ = yytext;"], 
      ["expression binary expression", "$$ = $1 + $2 + $3;"] 
     ], 
     "binary": [ 
      ["+",    "$$ = ' + ';"], 
      ["-",    "$$ = ' - ';"], 
      ["*",    "$$ = ' * ';"], 
      ["/",    "$$ = '/';"], 
      ["%",    "$$ = ' % ';"], 
      ["binary NEWLINE", "$$ = $1;"] 
     ] 
    } 
} 

當我嘗試運行它,它給了我下面的錯誤:

Conflict in grammar: multiple actions possible when lookahead token is + in state 
13 
- reduce by rule: expression -> expression binary expression 
- shift token (then go to state 8) 
Conflict in grammar: multiple actions possible when lookahead token is - in state 
13 
- reduce by rule: expression -> expression binary expression 
- shift token (then go to state 9) 
Conflict in grammar: multiple actions possible when lookahead token is * in state 
13 
- reduce by rule: expression -> expression binary expression 
- shift token (then go to state 10) 
Conflict in grammar: multiple actions possible when lookahead token is/in state 
13 
- reduce by rule: expression -> expression binary expression 
- shift token (then go to state 11) 
Conflict in grammar: multiple actions possible when lookahead token is % in state 
13 
- reduce by rule: expression -> expression binary expression 
- shift token (then go to state 12) 

States with conflicts: 
State 13 
    expression -> expression binary expression . #lookaheads= NEWLINE + - */% 
    expression -> expression .binary expression 
    binary -> .+ 
    binary -> .- 
    binary -> .* 
    binary -> ./ 
    binary -> .% 
    binary -> .binary NEWLINE 

但是它仍然產生最終正確的輸出。例如,2 + 3 * 5/7 % 11被正確翻譯爲2 + 3 * 5/7 % 11;

我看到它的方式似乎是明確的,所以Jison爲什麼抱怨?

更新:由於@icktoofay解釋它是一個操作符相關性問題。通過將運算符解析爲非終端符號運算符的優先級並且關聯性信息丟失。因此,我解決了這個問題,如下所示:

{ 
    "operators": [ 
     ["left", "+", "-"], 
     ["left", "*", "/", "%"] 
    ], 
    "bnf": { 
     "program": [ 
      ["statement EOF", "return $1;"] 
     ], 
     "statement": [ 
      ["expression NEWLINE", "$$ = $1 + ';';"] 
     ], 
     "expression": [ 
      ["NUMBER",       "$$ = yytext;"], 
      ["expression + expression",   "$$ = $1 + ' + ' + $3;"], 
      ["expression - expression",   "$$ = $1 + ' - ' + $3;"], 
      ["expression * expression",   "$$ = $1 + ' * ' + $3;"], 
      ["expression/expression",   "$$ = $1 + '/' + $3;"], 
      ["expression % expression",   "$$ = $1 + ' % ' + $3;"], 
      ["expression + NEWLINE expression", "$$ = $1 + ' + ' + $4;"], 
      ["expression - NEWLINE expression", "$$ = $1 + ' - ' + $4;"], 
      ["expression * NEWLINE expression", "$$ = $1 + ' * ' + $4;"], 
      ["expression/NEWLINE expression", "$$ = $1 + '/' + $4;"], 
      ["expression % NEWLINE expression", "$$ = $1 + ' % ' + $4;"] 
     ] 
    } 
} 

話雖這麼說,這個語法只允許一個可選的換行符遵循二元運算符。我如何重寫它以允許任意數量的換行符遵循二元運算符?還有一些方法,我不必爲每個操作員編寫2條規則。

回答

5

我不完全熟悉Jison,但它看起來像你定義的規則,看起來像這樣:

expression ::= number; 
expression ::= expression binary expression; 

考慮表達1 - 2 - 3。這可以解釋爲(1 - 2) - 31 - (2 - 3)。這是什麼?你的語法不明確。正常的數學規則說它應該是左聯合的。你需要讓你的語法反映:

expression ::= number; 
expression ::= expression binary number; 
+0

你說得對。操作員的關聯確實是問題。謝謝。我可以爲其他事情煩惱嗎?我編輯了我的問題,我想知道您對此的看法。也許我應該把它作爲一個單獨的問題發佈? – 2013-04-04 03:50:31

+1

@AaditMShah:我只是修改詞法分析器來合併連續的換行符。至於需要兩個作品與'NEWLINE' /沒有'NEWLINE'的情況下,你可以用兩個作品創作一個新的'maybe_newline':一個是空的,一個是用於'NEWLINE'的。 (事實上​​,如果你不想修改詞法分析器,你可以有一個'maybe_newline',一個空白的製作和一個'maybe_newline NEWLINE'製作。) – icktoofay 2013-04-04 05:24:08