2014-09-06 130 views
0

我写了下面的语法,Bison警告我减少/减少冲突。无法找到减少/减少语法冲突

parser.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] 

如何检测文法的哪一部分产生冲突?是否有一个由Bison生成的日志,我可以看到冲突?而且,我怎么能解决这个问题?

语法:

%left TK_OC_OR TK_OC_AND 
%left '<' '>' TK_OC_LE TK_OC_GE TK_OC_EQ TK_OC_NE 
%left '+' '-' 
%left '*' '/' 

%nonassoc LOWER_THAN_ELSE 
%nonassoc TK_PR_ELSE 

%start s 

%type<symbol> decl_var 
%type<symbol> cabecalho 

%% 

s: decl_global s 
    | def_funcao s 
    | 
    ; 

decl_global: decl_var ';' 
    | decl_vetor ';' 
    | decl_var {error("Faltando o ';' no final do comando.", $1->line); return IKS_SYNTAX_ERRO;} 
    ; 

decl_local: decl_var ';' decl_local 
    | 
    ; 

decl_var 
    : tipo_var TK_IDENTIFICADOR {$$ = $2;} 
    ; 

decl_vetor 
    : tipo_var TK_IDENTIFICADOR '[' TK_LIT_INT ']' 
    ; 


tipo_var: TK_PR_INT 
     | TK_PR_FLOAT 
     | TK_PR_BOOL 
     | TK_PR_CHAR 
     | TK_PR_STRING 
     ; 

def_funcao: cabecalho decl_local bloco_comando 
    | cabecalho decl_local bloco_comando ';' {error("Declaração de função com ';' no final do comando.\n",$1->line); return IKS_SYNTAX_ERRO;} 
    ; 

chamada_funcao 
    : TK_IDENTIFICADOR '(' lista_expressoes ')' 
    ; 

cabecalho: decl_var '(' lista_parametros ')' {$$ = $1;} 
    ; 

lista_parametros: lista_parametros_nao_vazia 
    | 
    ; 

lista_parametros_nao_vazia: parametro ',' lista_parametros_nao_vazia 
    | parametro 
    ; 

parametro: decl_var 
    ; 

comando: bloco_comando 
    | controle_fluxo 
    | atribuicao 
    | entrada 
    | saida 
    | retorna 
    | decl_var ';' 
    | chamada_funcao 
    | ';' 
    ; 

bloco_comando: '{' seq_comando '}' 
    ; 

seq_comando: comando seq_comando 
    | comando 
    | 
    ; 

atribuicao: TK_IDENTIFICADOR '=' expressao 
    | TK_IDENTIFICADOR '[' expressao ']' '=' expressao 
    ; 

entrada 
    : TK_PR_INPUT TK_IDENTIFICADOR 
    ; 

saida 
    : TK_PR_OUTPUT lista_expressoes_nao_vazia 
    ; 

lista_expressoes_nao_vazia: expressao ',' lista_expressoes_nao_vazia 
    | expressao 
    ; 

retorna: TK_PR_RETURN expressao ';' 
    ; 

controle_fluxo 
    : TK_PR_IF '(' expressao ')' TK_PR_THEN comando %prec LOWER_THAN_ELSE 
    | TK_PR_IF '(' error ')' TK_PR_THEN comando 
    | TK_PR_IF '(' expressao ')' TK_PR_THEN comando TK_PR_ELSE comando 
    | TK_PR_WHILE '(' expressao ')' TK_PR_DO comando 
    | TK_PR_DO comando TK_PR_WHILE '(' expressao ')' 
    | TK_PR_DO comando TK_PR_WHILE '(' error ')' 
    ; 

expressao: TK_IDENTIFICADOR 
    | TK_IDENTIFICADOR '[' expressao ']' 
    | TK_LIT_INT 
    | TK_LIT_FLOAT 
    | TK_LIT_FALSE 
    | TK_LIT_TRUE 
    | TK_LIT_CHAR 
    | TK_LIT_STRING 
    | expressao '+' expressao 
    | expressao '-' expressao 
    | expressao '*' expressao 
    | expressao '/' expressao 
    | expressao '<' expressao 
    | expressao '>' expressao 
    | '+' expressao 
    | '-' expressao 
    | '(' expressao ')' 
    | expressao TK_OC_LE expressao 
    | expressao TK_OC_GE expressao 
    | expressao TK_OC_EQ expressao 
    | expressao TK_OC_NE expressao 
    | expressao TK_OC_AND expressao 
    | expressao TK_OC_OR expressao 
    | chamada_funcao 
    ; 

lista_expressoes: lista_expressoes_nao_vazia 
    | 
    ; 

回答

2

我如何检测其语法的一部分是产生冲突?是否有一个由Bison生成的日志,我可以看到冲突?而且,我怎么能解决这个问题?

是的。如果您在bison命令行上使用-v,它将生成一个名为<filename>.output的文件中的所有状态的报告。报告将包括各种冲突,并且您可以从指示状态看到冲突模式是什么。在阅读本答案的其余部分之前,您应该尝试一下。

如果你这样做,你会看到这个问题:

seq_comando: comando seq_comando 
    | comando 
    | 
    ; 

由于seq_comando可以为空,单个comando可以匹配:

seq_comando: comando seq_comando 

seq_comando: comando 

简单的解决方案是摆脱seq_comando: comando规则。您可能还想考虑将右递归更改为左递归(seq_comando: seq_comando comando | /* empty */;),因为这将需要更少的解析器堆栈。