如何解决这个“冲突:1班/减少”

时间:2013-03-26 02:44:11

标签: bison yacc lex flex-lexer

我写一个语法来解析速度,它在“if elseif else”

上有冲突

flex文件:

%{
#include<stdio.h>
#include<string.h>
#include "context.h"
#include "bool.h"
#include "vtl4.tab.h"
%}
INT ([0-9]*)
%%
{INT} {return INTEGER;}
">" {return yytext[0];}
"(" {return yytext[0];}
")" {return yytext[0];}
"in" {return IN;}
"#foreach" {return FOREACH;}
"#end" {return END;}
"#if" {return IF;}
"#else" {return ELSE;}
"#elseif" {return ELSEIF;}
[^ \t] {yylval.string = yytext;return CONTENT;}
[ \t] {}
%%

野牛档案:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bool.h"
#include "parser.h"
#include "context.h"
#include "vtl4.tab.h"

extern FILE * yyin;
extern FILE * yyout;
extern int yylex();
extern int yywrap();
%}

%union {
struct simpleNode *ast;
double d;
int i;
bool b;
char* string;
struct symbol *sym;
}

%token <string> CONTENT NAME

%token IF ELSEIF ELSE END HASH DOLLAR PARENTHESIS PARENTHESIS_CLOSE LOGIC_EQUAL NEWLINE   INTEGER GL
%token FOREACH IN
%type <ast> stmts stmt

%nonassoc ELSEIF
%nonassoc ELSE

%%
stmts
: stmt{}
| stmts stmt{}
;

stmt:CONTENT {}
|directive {printf("stmt ---directive\n");}
|INTEGER {}
;

directive:FOREACH '(' exp ')' stmts END {printf("directive ---foreach\n");}
|if {printf("directive ---if\n");}
;

if:IF '(' cond ')' stmts END {printf("if\n");}
|IF '(' cond ')' stmts ELSE stmts END {printf("if else end\n");}
|IF '(' cond ')' stmts elseif END {printf("if elseif end\n");}
|IF '(' cond ')' stmts elseif ELSE stmts END {printf("if elseif ... else end\n");}
;

elseif:ELSEIF '(' cond ')' stmts {printf("one elseif\n");}
|elseif elseif {printf("Mul elseif\n");}
;

cond:INTEGER '>' INTEGER {printf("cond\n");}

exp:INTEGER IN INTEGER {printf("exp\n");}


%%
int main(){
FILE *src;
src = fopen("test.vm","r");
yyin = src;
yyparse();
fclose(src);
return 1;
}

int yywrap(){
return 1;
}

输出文件说:

State 34 conflicts: 1 shift/reduce
...
state 34

12 elseif: . ELSEIF '(' cond ')' stmts
13       | . elseif elseif  [ELSEIF, ELSE, END]
13       | elseif . elseif  [ELSEIF, ELSE, END]
13       | elseif elseif .  [ELSEIF, ELSE, END]

 ELSEIF  shift, and go to state 25

 ELSEIF    [reduce using rule 13 (elseif)]
 $default  reduce using rule 13 (elseif)

 elseif  go to state 34

我查找了一些信息,并为ELSE和ELSEIF添加了优先级,但是没有解决它。请帮助我!也许我不太了解优先级机制

2 个答案:

答案 0 :(得分:2)

我不知道您希望解析的语言是如何工作的,所以这必须是猜测,但您的问题可能就在这里:

elseif : ELSEIF '(' cond ')' stmts
   | elseif elseif
   ;

一个elseif可以由两个elsifs组成。所以如果你有三个elseif,它们应该分组为((elseif elseif)elseif)还是(elseif(elseif elseif))?野牛不知道,并报告冲突。

另一件事是,如果你只使用语法而不是很多其他代码,理解和使用语法要简单得多。 Bison文件的最小可编辑和更易读格式的版本看起来像这样(假设我在编辑时没有犯任何错误):

%token IF ELSEIF ELSE END INTEGER FOREACH IN

%nonassoc ELSEIF
%nonassoc ELSE

%%

stmts : stmt
      | stmts stmt
      ;

stmt: directive | INTEGER ;

directive : FOREACH '(' exp ')' stmts END
          | if
          ;

if : IF '(' cond ')' stmts END
   | IF '(' cond ')' stmts ELSE stmts END
   | IF '(' cond ')' stmts elseif END
   | IF '(' cond ')' stmts elseif ELSE stmts END
   ;

elseif : ELSEIF '(' cond ')' stmts
       | elseif elseif
       ;

cond : INTEGER '>' INTEGER ;

exp : INTEGER IN INTEGER ;

%%

我建议使用这种新语法,它不会产生任何转移/减少冲突。

编辑:我删除了%nonassoc优先级规范,因为它们不是必需的。对于每个IF,您使用带有END的语法,因此您没有在类C语法中获得的if-if-else冲突,并且您可以通过指定优先级来删除它。

%token IF ELSEIF ELSE END INTEGER FOREACH IN

%%

stmts : stmt
      | stmts stmt
      ;

stmt: directive | INTEGER ;

directive : FOREACH '(' exp ')' stmts END
          | if
          ;

if : IF '(' cond ')' stmts END
   | IF '(' cond ')' stmts ELSE stmts END
   | IF '(' cond ')' stmts elseifs END
   | IF '(' cond ')' stmts elseifs ELSE stmts END
   ;

elseifs : elseif | elseifs elseif ;

elseif : ELSEIF '(' cond ')' stmts
       ;

cond : INTEGER '>' INTEGER ;

exp : INTEGER IN INTEGER ;

%%

答案 1 :(得分:1)

您是否阅读过有关冲突的各种文件和其他SO问题?你应该。你会发现你的问题与ELSE无关(你引用的输出部分在冲突中没有提到它!)。

你的语法

elseifs: "#elseif" | elseifs elseifs

显然是模棱两可的。尝试

elseifs: "#elseif" | elseifs "#elseif"

或可能

elseifs: | elseifs "#elseif"