我写一个语法来解析速度,它在“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添加了优先级,但是没有解决它。请帮助我!也许我不太了解优先级机制
答案 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"