无法在语法中找到减少/减少冲突

时间:2014-09-06 21:01:53

标签: parsing bison yacc

我写了下面的语法,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
  |
  ;

1 个答案:

答案 0 :(得分:4)

  

如何检测语法的哪个部分产生冲突?是否有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 */;),因为这将需要更少的解析器堆栈。