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 は、連続する 2 つの elsif で構成できます。では、elseifが 3 つある場合、それらを((elseif elseif) elseif)または(elseif (elseif elseif))としてグループ化する必要がありますか? バイソンはそれを知らず、衝突を報告します。

もう 1 つのことは、他の多くのコードではなく、文法のみを使用する場合、文法を理解して使用することがはるかに簡単になることです。最小限のコンパイル可能で、より読みやすい形式の 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 ;

%%

shift/reduce の競合を発生させない、この新しい文法をお勧めします。

編集: %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 に答える