1

问题描述

在我的 yacc 解析器语法中,我定义了以下规则和相应的操作(参见下面的program.y)。解析int X;应该有推导type => TOK_INTand variable_list => TOK_VARIABLE,然后这些与以 a 结尾的声明匹配statment ;。但是,将其读作int Xand ;。也就是说,两个单独的语句。谁能明白为什么?

程序.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:这是使用系统提供的 Yacc(实际上是 Bison 2.3)在 MacOS X 10.6.7 上编译的——我在我的机器上得到了与 Yacc 的其他 2 个变体基本相同的输出。GCC 是 4.2.1 (XCode 3)。

于 2011-04-01T04:43:41.143 回答
0

您的词法分析器实际上可能有问题。调试的一种方法是删除除直接涉及的子句之外的所有子句,然后逐个添加子句以查看哪个子句引入了错误。

于 2011-04-01T04:44:03.623 回答