0

我写了一个语法来解析速度,它在“if elseif else”处有冲突

弹性文件:

%{
#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添加了优先级,但没有解决。请帮帮我!可能我不是很了解优先级机制

4

2 回答 2

2

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

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

一个 elseif 可以由两个相互接连的 elsif 组成。所以如果你有三个 elseif,它们应该被分组为((elseif elseif) elseif)还是(elseif (elseif elseif))?Bison 不知道,并报告了冲突。

另一件事是,如果您只使用语法而不是许多其他代码,那么理解和使用语法会更简单。您的 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 ;

%%
于 2013-03-26T06:28:59.173 回答
1

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

你的语法

elseifs: "#elseif" | elseifs elseifs

显然是模棱两可的。尝试

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

或者可能

elseifs: | elseifs "#elseif"
于 2013-03-26T06:32:27.820 回答