2017-01-16 92 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