Ошибка грамматики парсера Yacc. int X; читать отдельно как int X и; - PullRequest
1 голос
/ 01 апреля 2011

Описание проблемы

В моей грамматике синтаксического анализатора yacc определены следующие правила и соответствующие действия (см. program.y ниже). Синтаксический анализ int X; должен иметь производные type => TOK_INT и variable_list => TOK_VARIABLE, а затем они сопоставляются с объявлением, которое заканчивается на statment ;. Однако читается как int X и ;. То есть два отдельных утверждения. Кто-нибудь может понять почему?

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); }
;

Ответы [ 2 ]

3 голосов
/ 01 апреля 2011

Поскольку '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) - я получил практически тот же вывод с 2 другими вариантами Yacc на моей машине.GCC был 4.2.1 (XCode 3).

0 голосов
/ 01 апреля 2011

Возможно, у вас проблемы с лексером. Один из способов отладки состоит в том, чтобы удалить все предложения, кроме непосредственно участвующих, а затем добавить предложения одно за другим, чтобы увидеть, какое из них приводит к ошибке.

...