1

問題の説明

私のyaccパーサー文法では、次のルールと対応するアクションが定義されています(以下のprogram.yを参照)。構文解析int X;には派生type => TOK_INTとが必要variable_list => TOK_VARIABLEであり、これらは。で終わる宣言と一致しstatment ;ます。ただし、これをint Xおよびとして読み取ります;。つまり、2つの別々のステートメントです。誰もが理由を見ることができますか?

program.y

program:
    function { exit(0); }
    ;

function:
    function line { printf("goal\n"); printtree_print($2); }
        |
        ;

line:
    statement ';' { printf("line\n"); printtree_print($1); }
    ;

statement:
    declaration { printf("declaration\n"); printtree_print($1); }
    | assignment { printf("assignment\n"); printtree_print($1); }
    ;

declaration: 
       type variable_list { printf("varlist\n"); printtree_print($2); $$ = $2;  }
       ;

type:
    TOK_INT { typeMode = typeInt; }
    ;

variable_list: 
         TOK_VARIABLE
         { $$ = node_mkVariable($1, typeMode); 

        printtree_print($$);
        }
         ; 

assignment:  
      TOK_VARIABLE TOK_ASSIGN expr
      { printf("assignment %s = expr\n", $1); 
        node_setInTable($1, $3); 
    $$ = node_getFromTable($1); }
      ;

expr:
    TOK_INTEGER { $$ = node_mkConstant($1); }
| TOK_VARIABLE { $$ = node_mkVariable($1, typeVariable); }
;
4

2 に答える 2

3

'expr'と'assignment'はおそらく問題に密接に関係していないので、テストリグからそれらを省略しました。問題を示す最小限のコンパイル可能なコードを提供しなかったので、私はあなたのためにそれを作成しました:

%{
#include <stdlib.h>
#include <stdio.h>
static void yyerror(const char *str);
static int yylex(void);
static void printtree_print(int);
static int node_mkVariable(int, int);
int typeMode;
enum { typeInt };
%}
%token TOK_INT
%token TOK_VARIABLE
%%
program:
    function
        { exit(0); }
    ;

function:
        /* Nothing */
    |   function line
        { printf("goal\n"); printtree_print($2); }
    ;

line:
    statement ';'
        { printf("line\n"); printtree_print($1); }
    ;

statement:
    declaration
        { printf("declaration\n"); printtree_print($1); }
    ;

declaration: 
    type variable_list
        { printf("varlist\n"); printtree_print($2); $$ = $2;  }
    ;

type:
    TOK_INT
         { typeMode = typeInt; }
    ;

variable_list: 
    TOK_VARIABLE
    {
        $$ = node_mkVariable($1, typeMode); 
        printtree_print($$);
    }
    ; 
%%
void printtree_print(int n)
{
    printf("PT_P: %d\n", n);
}
int yylex(void)
{
    static int counter = 0;
    static int tokens[] = { TOK_INT, TOK_VARIABLE, ';', 0 };
    enum { NUM_TOKENS = sizeof(tokens) / sizeof(tokens[0]) };
    if (counter < NUM_TOKENS)
    {
        printf("Token: %d\n", tokens[counter]);
        return(tokens[counter++]);
    }
    return 0;
}
int node_mkVariable(int var, int mode)
{
    return 23 + var + mode;
}
static void yyerror(const char *str)
{
    fprintf(stderr, "Error: %s\n", str);
    exit(1);
}
int main(void)
{
    while (yyparse() == 0)
        ;
    return 0;
}

コンパイルすると、出力として取得されます。

Token: 258
Token: 259
PT_P: 23
varlist
PT_P: 23
declaration
PT_P: 23
Token: 59
line
PT_P: 23
goal
PT_P: 23
Token: 0

これはインフラストラクチャを考えると正しいように見え、観察された動作の兆候は示されていません。したがって、問題を再現するのに十分な追加コードを提示する必要があります。これは、提供しなかったコードのアーティファクトではなく、文法の機能であることを示すためです。

FWIW:これはMacOS X 10.6.7で、Yaccが提供するシステム(実際にはBison 2.3)を使用してコンパイルされました-マシン上のYaccの他の2つのバリアントと基本的に同じ出力が得られました。GCCは4.2.1(XCode 3)でした。

于 2011-04-01T04:43:41.143 に答える
0

実際には、レクサーに問題がある可能性があります。デバッグする1つの方法は、直接関係する句以外のすべての句を削除してから、句を1つずつ追加して、どの句がエラーを引き起こすかを確認することです。

于 2011-04-01T04:44:03.623 に答える