2017-01-16 111 views
0

我有以下yacc語法:警告:2減少/減少衝突[-Wconflicts-RR]在yacc語法

%{ 
#include <stdio.h> 
extern FILE* yyin; 
extern char* yytext; 

%} 

%token VAR ID_NAME TYPE_STRING TYPE_BOOL TYPE_NUMBER 
%token CONST VALUE_STRING VALUE_BOOL VALUE_NUMBER 

%% 

program 
    : declarations 
    ; 

declarations 
    : declaration 
    | declarations declaration 
    ; 

declaration 
    : var_declaration 
    | const_declaration 
    ; 

value 
    : VALUE_BOOL 
    | VALUE_STRING 
    | VALUE_NUMBER 
    ; 

assignment 
    : ID_NAME '=' value 
    ; 

assignments 
    : assignment 
    | assignments ',' assignment 
    ; 

id_list 
    : ID_NAME 
    | id_list ',' ID_NAME 
    ; 

declaration_expression 
    : assignments 
    | id_list 
    | assignments ',' declaration_expression 
    | id_list ',' declaration_expression 
    ; 

var_declaration 
    : VAR ':' type declaration_expression ';' { printf("%s var\n", $1); } 
    ; 

const_declaration: CONST ':' type assignments ';' {printf("const\n");} 
    ; 

type: TYPE_NUMBER 
    | TYPE_STRING 
    | TYPE_BOOL 
    ; 

%% 
void yyerror (char const *s) { 
    fprintf (stderr, "%s\n", s); 
} 

int main(int argc, char** argv[]) 
{ 

    yyparse(); 
    return 0; 
} 

它應該描述一個小語言,使形式的變量和常量聲明:var:<type> <variables_names or variables_initializations>const:<type> <constants_initialization>

我想補充以下語法的支持:

var:<type> var1, var2=<value>, var3; 

事情是這樣的:var:<type> (<variables_names>|<variable_initializations>)+

爲了實現這個目標我已經添加了以下修改我的語法:

assignments 
    : assignment 
    | assignments ',' assignment 
    ; 

id_list 
    : ID_NAME 
    | id_list ',' ID_NAME 
    ; 

declaration_expression 
    : assignments 
    | id_list 
    | assignments ',' declaration_expression 
    | id_list ',' declaration_expression 
    ; 

而且我認爲他將啓用(<variables_names>|<variable_initializations>)+部分。但我得到一個reduce/reduce衝突,因爲這些行:

| assignments ',' declaration_expression 
    | id_list ',' declaration_expression 

我在做什麼錯?

+0

我想你的第一個片段是不工作的修改之後。如果你仍然有工作版本踢,那會很有幫助。 – rici

+0

@rici這是http://pastebin.com/xb9V3N8G的最新版本。但是,它只支持格式的變量聲明:'var: | <初始化>'。它不允許混合'variables_names'和'initializations'。 – cristid9

+0

我認爲這是它的樣子,但我不確定。謝謝。爲了清晰起見,編輯你的問題會更好。 「我使用了這個declarative_expression的定義:」(來自pastebin),但我想改變它,以便'var'聲明可以是混合項的列表,可以是ID或賦值。所以我把它改爲:「(從當前的問題),這讓我減少/減少衝突。 – rici

回答

1

如果我理解正確,您希望在var聲明中允許混合使用裸露變量名稱和變量初始化,並且只允許const聲明中的初始化。這是相當直接:

initialization : ID '=' value 
init_list  : initialization | init_list ',' initialization 
init_or_id  : initialization | ID 
init_or_id_list: init_or_id 
       | init_or_id_list ',' init_or_id 

const_declaration: CONST ':' type init_list 
var_declaration : VAR ':' type init_or_id_list 

你做了什麼錯是通過延長混合列表與列表,而與項目使混合列表。這是不明確的,所以會導致減少/減少衝突。

上述工作(與原來的一樣),因爲init_listinit_or_id_list永遠不會出現(作爲非終端)在派生中的同一點。其中一個明確地遵循const關鍵字,另一個明確地遵循關鍵字var。這很幸運,因爲一個純粹的作業清單可以同時滿足兩個作品,如果他們共享一個上下文,這會產生減少/減少衝突。這個問題也是可以解決的,因爲它偶爾會出現,所以我會添加解決方案,儘管我強調它對這個特定問題是不相關。 (這可能與稍後一些類似問題的讀者有關)

爲了使兩個可能的列表語法明確無誤,必須確保潛在的純粹的賦值列表始終是從不同的生產派生混合名單。因此,我們可以這樣寫:

init_list: initialization | init_list initialization 
init_or_id_list: ID 
       | init_list ',' ID 
       | init_or_id_list ',' init_or_id 

現在,一個init_or_id_list必然包含至少一個ID項目,因此它不能與init_list混淆。但是,現在我們使用的最終結果,我們必須記住,它接受一個混合列表上下文需要允許這兩個名單的可能性:

pure_list: init_list 
mixed_list: init_list | init_or_id_list