在我的yacc解析器语法中,我定义了以下规则和相应的操作(请参阅下面的 program.y )。解析 int X;
应该有 type => TOK_INT
和 variable_list => TOK_VARIABLE
,然后这些与声明匹配以 statment ;
结尾。但是,请将其读作 int X
和 ;
。也就是说,两个单独的陈述。谁能明白为什么?
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); }
;
答案 0 :(得分:3)
由于'expr'和'赋值'可能与问题没有密切关系,我从测试装置中省略了它们。由于您没有提供演示问题的最小可编译代码,因此我为您创建了它:
%{
#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上编译的 - 我在我的机器上获得了与其他2个Yacc变体基本相同的输出。海湾合作委员会是4.2.1(XCode 3)。
答案 1 :(得分:0)
你的lexer实际上可能有问题。 调试的一种方法是删除除直接涉及的所有子句之外的所有子句,然后逐个添加子句以查看哪一个引入了错误。