2017-12-21 7 views
0

flexとbisonを使用してmini C言語のコンパイラを作成したいと思います。私の言語の例は次のようになります。ここではFlex/BisonミニCコンパイラの語彙および意味解析シフト/リダクションの競合

/* This is an example uC program. */ 
int fac(int n) 
{ 
    if (n < 2) 
     return n; 
    return n * fac(n - 1); 
} 

int sum(int n, int a[]) 
{ 
    int i; 
    int s; 

    i = 0; 
    s = 0; 
    while (i < n) { 
     s = s + a[i]; 
     i = i + 1; 
    } 
    return s; 
} 

int main(void) 
{ 
    int a[2]; 

    a[0] = fac(5); 
    a[1] = 27; 
    return 0; 
} 

は、言語のこの種を解析するために私の文法である:

program   ::= topdec_list 
topdec_list  ::= /empty/ | topdec topdec_list 
topdec   ::= vardec ";" 
        | funtype ident "(" formals ")" funbody 
vardec   ::= scalardec | arraydec 
scalardec  ::= typename ident 
arraydec  ::= typename ident "[" intconst "]" 
typename  ::= "int" | "char" 
funtype   ::= typename | "void" 
funbody   ::= "{" locals stmts "}" | ";" 
formals   ::= "void" | formal_list 
formal_list  ::= formaldec | formaldec "," formal_list 
formaldec  ::= scalardec | typename ident "[" "]" 
locals   ::= /empty/ | vardec ";" locals 
stmts   ::= /empty/ | stmt stmts 
stmt   ::= expr ";" 
        | "return" expr ";" | "return" ";" 
        | "while" condition stmt 
        | "if" condition stmt else_part 
        | "{" stmts "}" 
        | ";" 
else_part  ::= /empty/ | "else" stmt 
condition  ::= "(" expr ")" 
expr   ::= intconst 
        | ident | ident "[" expr "]" 
        | unop expr 
        | expr binop expr 
        | ident "(" actuals ")" 
        | "(" expr ")" 
unop   ::= "-" | "!" 
binop   ::= "+" | "-" | "*" | "/" 
        | "<" | ">" | "<=" | ">=" | "!=" | "==" 
        | "&&" 
        | "=" 
actuals   ::= /empty/ | expr_list 
expr_list  ::= expr | expr "," expr_list 

フレックスモジュールが正常に動作し、必要に応じて値を返しますが、バイソンが続け私の文法が間違っていることを示す奇妙な誤りを与えています(そうではありません)。ここに私のバイソン・ファイルは次のとおりです。

%{ 
#include <stdio.h> 
#include <stdlib.h> 

extern int yylex(); 
extern int yyparse(); 
FILE* yyin; 
extern int lineNumber; 

void yyerror(const char* s); 
%} 

%union { 
    int intvalue; 
} 

%token<intvalue> INTCONST 
%token IDENT 
%token CHARK 
%token ELSEK 
%token IFK 
%token INTK 
%token RETURNK 
%token VOIDK 
%token WHILEK 
%token NOTK 
%token ANDK 
%token COMMAK 
%token DIVIDEK 
%token MULTIPLYK 
%token MINUSK 
%token PLUSK 
%token SEMICOLONK 
%token NEQUALK 
%token EQUALK 
%token ASSIGNMENTK 
%token RECOMPARATORK 
%token LECOMPARATORK 
%token RCOMPARATORK 
%token LCOMPARATORK 
%token RPARANTESESK 
%token LPARANTESESK 
%token RBRACKETK 
%token LBRACKETK 
%token RCURLY 
%token LCURLY 

%right ASSIGNMENTK 
%left ANDK 
%left EQUALK NEQUALK 
%left LCOMPARATORK RCOMPARATORK LECOMPARATORK RECOMPARATORK 
%left PLUSK 
%left MULTIPLYK DIVIDEK 
%left MINUSK NOTK 

%start program 

%% 

program: topdec_list 
     ; 
topdec_list: /*empty*/ 
        | topdec topdec_list 
       ; 
topdec: vardec SEMICOLONK 
      | funtype IDENT LPARANTESESK formals RPARANTESESK funbody 
     ; 
vardec: scalardec 
      | arraydec 
     ; 
scalardec: typename IDENT 
       ; 
arraydec: typename IDENT LBRACKETK INTCONST RBRACKETK 
       ; 
typename: INTK 
       | CHARK 
       ; 
funtype: typename 
      | VOIDK 
     ; 
funbody: LCURLY locals stmts RCURLY 
      | SEMICOLONK 
     ; 
formals: VOIDK 
      | formal_list 
     ; 
formal_list: formaldec 
        | formaldec COMMAK formal_list 
       ; 
formaldec: scalardec 
     | typename IDENT LBRACKETK RBRACKETK 
      ; 
locals: /*empty*/ 
     | vardec SEMICOLONK locals 
     ; 
stmts: /*empty*/ 
    | stmt stmts 
    ; 
stmt: expr SEMICOLONK 
    | RETURNK expr SEMICOLONK 
     | RETURNK SEMICOLONK 
     | WHILEK condition stmt 
     | IFK condition stmt else_part 
     | LCURLY stmts RCURLY 
     | SEMICOLONK 
     ; 
else_part: /*empty*/ | ELSEK stmt 
       ; 
condition: LPARANTESESK expr RPARANTESESK 
       ; 
expr: INTCONST 
     | IDENT 
     | IDENT LBRACKETK expr RBRACKETK 
     | unop expr 
     | expr binop expr 
     | IDENT LPARANTESESK actuals RPARANTESESK 
     | LPARANTESESK expr RPARANTESESK 
     ; 
unop: MINUSK | NOTK 
    ; 
binop: PLUSK 
    | MINUSK 
     | MULTIPLYK 
     | DIVIDEK 
     | LCOMPARATORK 
     | RCOMPARATORK 
    | LECOMPARATORK 
     | RECOMPARATORK 
     | NEQUALK 
     | EQUALK 
     | ANDK 
     | ASSIGNMENTK 
    ; 
actuals: /*empty*/ 
      | expr_list 
      ; 
expr_list: expr 
       | expr COMMAK expr_list 
       ; 

%% 

int main(int argc, char **argv) 
{ 
    yyin = fopen("input.c", "r"); 
    do 
    { 
     yyparse(); 
    } while (!feof(yyin)); 
    fclose(yyin); 
    return 0; 
} 

void yyerror(const char* error) 
{ 
    fprintf(stderr, "Parse error in line %d: %s\n", lineNumber, error); 
} 

例えば、この入力のために:

int i; 
i = 0; 

私は(私は私のフレックスにトークンを印刷する構文エラーは、それが第二iを区別した直後に起こったエラーを取得しますファイルなので、割り当て文字に達するまで問題はないとわかります)。

それとも別の例として、このラインを通過する際:

int fac(int n); 

を私はそれが構文エラーのような第2 intを見ていることを意味し、右側の最初のparanteses後(正確にParse error in line 1: syntax errorある)同じ構文エラーを取得し、それは私の文法がうまく見えるからではありません。次のように

またバイソンによって生成警告は(FlexとGCCが微細である)である。

semantic_analyzer.y: warning: 26 shift/reduce conflicts [-Wconflicts-sr] 
semantic_analyzer.y:78.10-17: warning: rule useless in parser due to conflicts [-Wother] 
funtype: typename 
      ^^^^^^^^ 

任意の提案や修正は、事前に感謝:)理解されます。

+0

パーサーを生成するときにyacc/bisonが生成する警告については言及していません。 – rici

+0

@riciありがとうございました。 – Mazhar

答えて

1
int i; 
i = 0; 

は、有効なCプログラムではありません。文法によって正しく拒否されます。 (あなたの文法が示すように、プログラムは、宣言i = 10;のシーケンスが宣言されていないです。)あなたが言及して第二の問題は、最初と主張あなたの文法によって引き起こさシフト削減紛争に関連している

intint fac(int n)funtypeに、intのサイズはint ;に、それぞれtypenameである必要があります。パーサーがIDENTをシフトするか、typenamefuntypeに減らすかを決定する必要がある時点で、1つの先読みトークン(IDENT)しか見ることができないため、どちらのアクションを実行するのかわからず、決定は次の先読みトークン(開かれた括弧であってもなくてもよい)。デフォルトでは、yacc/bisonはshift-reduce競合を解決します。つまり、の2番目のプロダクトのプレフィックスはint facにできません。したがって、(はエラーを引き起こします。

+0

ああ、私の最初のプログラムは確かに間違っています。だから、私はtopdec文の最後のトークンを統合する必要があります(1つのfuntypeの代わりにint | char | void)でしょうか? – Mazhar

+1

文法を機能させたい場合は、shift-reduceの競合を修正する必要があります。バイソンは実際に、 'funtype:typename 'ルールは役に立たないと言いました。これは基本的に私が答えて言ったことです。 – rici

+1

@mazhar:簡単な解決策は、可能な 'typename'が文法にあるように' void'を追加することです。文法では変数型と関数戻り型を区別する必要はありません。関連する削減アクションで 'void x;'をチェックすることができます。 – rici

関連する問題