2017-03-06 53 views
0

我打算用野牛解析一些腳本語言移減少衝突,在這種語言,我可以寫類似下面的代碼:我怎樣才能消除同一操作

a = input() 
b = a + 1 
function myfunc 
    a = input() 
    b = a + 1 
end function 

我發現,該塊

a = input() 
b = a + 1 

其中進出函數定義的同時出現可以通過相同的規則stmts被減小,所以我寫如下代碼

%{ 
#include <stdio.h> 
#include <string> 
#include <sstream> 
#include <iostream> 
#include <stdarg.h> 
#include <tuple> 

using namespace std; 
%} 

%debug 

%token CRLF EXP FUNCTIONBEGIN FUNCTIONEND 

%start program 

%% 

stmt : EXP 
    | 
stmts : stmt CRLF stmts 
    | stmt 
function : FUNCTIONBEGIN CRLF stmts CRLF FUNCTIONEND 
unit : function 
    | stmts 
program : unit 
    | unit CRLF program 

%% 

當然這個代碼不能工作,由於一個班次/減少衝突

State 3 

    3 stmts: stmt . CRLF stmts 
    4  | stmt . 

    CRLF shift, and go to state 9 

    CRLF  [reduce using rule 4 (stmts)] 
    $default reduce using rule 4 (stmts) 

我認爲這是衝突由於我的兩個program規則和stmts規則中使用相同的終端CRLF作爲「二元運算符」 ,所以我不能通過給操作員設置優先級來解決這個衝突。

也許我可以通過某種方式將另外兩個規則合併program規則和stmts規則一起指向stmt

stmts : function CRLF stmts 
    | function 

但是我認爲這個方法(它是否能實際工作)是不是很漂亮,所以我問還有其他一些解決方案

回答

3

該問題與CRLF令牌無關。相反,它是你的定義program。 A program是一系列unit,其中每個單位是functionstmts。但stmts不是一個「單位」,這是由其名稱是複數的事實暗示。 A stmts是一系列stmt s。

所以假設我們有一個由三個語句組成的程序。那是多少個unit?這是一個由所有三個陳述組成的stmts嗎?或者其中兩個,一個有兩個陳述,另一個只有一個?或者相反呢?甚至三個unit s,每個包含一個stmts包含單個語句?

由於語法不明確,解析器無法確定哪些替代方法是需要的。這就是造成衝突的原因。

最簡單的解決方案是將生產unit: stmts更改爲單數:unit: stmt。那麼沒有歧義;三條語句program恰好有三個unit s,每個單個stmt

順便說一下,在編寫LR語法時,您應該總是喜歡左遞歸。正確的遞歸通常不會產生衝突,並且與當前的問題無關,但它確實會導致不必要的Iarge解析堆棧,並且像unitsstmts這樣的列表的減少將從右到左執行,因爲組件從堆棧中彈出,這往往不是預期的。