yacc从非终端获得零值

时间:2014-10-25 09:39:04

标签: c compiler-construction yacc

我正在按照[编译器构造,原理和实践]制作C编译器。 我几乎使用yacc进行解析,但是yacc中的一个规则就是出错。

return_stmt         : RETURN SEMI { $$ = newStmtNode(ReturnK);}
                    | RETURN expression SEMI
                         { $$ = newStmtNode(ReturnK);
                           $$->child[0] = $1;
                         }

使用“RETURN expression SEMI”规则解析return语句时,$ 1的值为零。整个来源如下     %% / * C- * /

的语法
program             : declaration_list
                         { savedTree = $1; } 
                    ;
declaration_list    : declaration_list declaration
                         { YYSTYPE t = $1;
                           if (t != NULL)
                             { while (t->sibling != NULL)
                                  t = t->sibling;
                               t->sibling = $2;
                               $$ = $1; }
                           else $$ = $2;
                         }
                    | declaration { $$ =$1; }
                    ;
declaration         : var_declaration { $$ = $1; }
                    | fun_declaration { $$ = $1; }
                    ;
var_declaration     : type_specifier ID SEMI
                         { $$ = newExpNode(VarK);
                           $$->type = (ExpType)$1;
                           $$->attr.name = nameStackPop();
                           $$->lineno = savedLineNo;
                         }
                    | type_specifier ID LBRACE NUM RBRACE SEMI
                         { $$ = newExpNode(VarArrayK);
                           $$->type = (ExpType)$1;
                           $$->attr.name = nameStackPop();
                           $$->lineno = savedLineNo;
                           $$->child[0] = $4;
                         }
                    ;
type_specifier      : INT { $$ = Integer; }
                    | VOID { $$ = Void; }
                    ;
fun_declaration     : type_specifier ID LPAREN params RPAREN compound_stmt
                         { $$ = newStmtNode(FunctionK);
                           $$->type = (ExpType)$1;
                           $$->attr.name = nameStackPop();
                           $$->lineno = savedLineNo;
                           $$->child[0] = $4;
                           $$->child[1] = $6;
                         }
                    ;
params              : param_list { $$ = $1; }
                    | VOID
                         { $$ = newExpNode(SingleParamK);
                           $$->type = Void;
                         }
                    ;
param_list          : param_list COMMA param
                         { YYSTYPE t = $1;
                           if (t != NULL)
                           { while (t->sibling != NULL)
                                t = t->sibling;
                             t->sibling = $3;
                             $$ = $1; }
                             else $$ = $3;
                         }
                    | param { $$ = $1; }
                    ;
param               : type_specifier ID
                         { $$ = newExpNode(SingleParamK);
                           $$->type = (ExpType)$1;
                           $$->attr.name = nameStackPop();
                         }
                    | type_specifier ID LBRACE RBRACE
                         { $$ = newExpNode(ArrayParamK);
                           $$->type = (ExpType)$1;
                           $$->attr.name = nameStackPop();
                           $$->lineno = savedLineNo;
                         }
                    ;
compound_stmt       : LCURLY local_declarations statement_list RCURLY
                         { $$ = newStmtNode(CompoundK);
                           $$->child[0] = $2;
                           $$->child[1] = $3;
                         }
                    ;
local_declarations  : local_declarations var_declaration
                         { YYSTYPE t = $1;
                           if (t != NULL)
                           { while (t->sibling != NULL)
                                t = t->sibling;
                             t->sibling = $2;
                             $$ = $1; }
                             else $$ = $2;
                         }
                    | empty { $$ = $1; }
                    ;
statement_list      : statement_list statement
                         { YYSTYPE t = $1;
                           if (t != NULL)
                           { while (t->sibling != NULL)
                                t = t->sibling;
                             t->sibling = $2;
                             $$ = $1; }
                             else $$ = $2;
                         }
                    | empty { $$ = $1; }
                    ;
statement           : expression_stmt { $$ = $1; }
                    | compound_stmt { $$ = $1; }
                    | selection_stmt { $$ = $1; }
                    | iteration_stmt { $$ = $1; }
                    | return_stmt { $$ = $1; }
                    ;
expression_stmt     : expression SEMI { $$ = $1;}
                    | SEMI { $$ = NULL; }
                    ;
selection_stmt      : IF LPAREN expression RPAREN statement
                         { $$ = newStmtNode(IfK);
                           $$->child[0] = $3;
                           $$->child[1] = $5;
                           $$->attr.withElse = FALSE;
                         }
                    | IF LPAREN expression RPAREN statement ELSE statement
                         { $$ = newStmtNode(IfK);
                           $$->child[0] = $3;
                           $$->child[1] = $5;
                           $$->child[2] = $7;
                           $$->attr.withElse = TRUE;
                         }
                    ;
iteration_stmt      : WHILE LPAREN expression RPAREN statement
                         { $$ = newStmtNode(WhileK);
                           $$->child[0] = $3;
                           $$->child[1] = $5;
                         }
                    ;
return_stmt         : RETURN SEMI { $$ = newStmtNode(ReturnK);}
                    | RETURN expression SEMI
                         { $$ = newStmtNode(ReturnK);
                           $$->child[0] = $1;
                         }
                    ;
expression          : var ASSIGN expression
                         { $$ = newExpNode(AssignK);
                           $$->type = Integer;
                           $$->child[0] = $1;
                           $$->child[1] = $3;
                         }
                    | simple_expression { $$ = $1; }
                    ;
var                 : ID
                         { $$ = newExpNode(IdK);
                           $$->type = Integer;
                           $$->attr.name = nameStackPop();
                         }
                    | ID LBRACE expression RBRACE
                         { $$ = newExpNode(IdK);
                           $$->attr.name = nameStackPop();
                           $$->child[0] = $3;
                         }
                    ;
simple_expression   : additive_expression relop additive_expression
                         { $$ = newExpNode(OpK); 
                           $$->type = Integer;
                           $$->child[0] = $1;
                           $$->child[1] = $3;
                           $$->attr.op = $2;
                         }
                    | additive_expression
                         { $$ = $1; }
                    ;
relop               : LE { $$ = LE; }
                    | LT { $$ = LT; }
                    | GT { $$ = GT; }
                    | GE { $$ = GE; }
                    | EQ { $$ = EQ; }
                    | NE { $$ = NE; }
                    ;
additive_expression : additive_expression addop term
                         { $$ = newExpNode(OpK);
                           $$->type = Integer;
                           $$->child[0] = $1;
                           $$->child[1] = $3;
                           $$->attr.op = $2;
                         }
                    | term { $$ = $1; }
                    ;
addop               : PLUS { $$ = PLUS; }
                    | MINUS { $$ = MINUS; }
                    ;
term                : term mulop factor
                         { $$ = newExpNode(OpK);
                           $$->type = Integer;
                           $$->child[0] = $1;
                           $$->child[1] = $3;
                           $$->attr.op = $2;
                         }
                    | factor { $$ = $1; }
                    ;
mulop               : TIMES { $$ = TIMES; }
                    | OVER { $$ = OVER; }
                    ;
factor              : LPAREN expression RPAREN
                         { $$ = $2; }
                    | var { $$ = $1; }
                    | call { $$ = $1; }
                    | NUM
                         { $$ = newExpNode(ConstK);
                           $$->type = Integer;
                           $$->attr.val = atoi(tokenString);
                         }
                    ;
call                : ID LPAREN args RPAREN
                         { $$ = newExpNode(CallK);
                           $$->attr.name = nameStackPop();
                           $$->child[0] = $3;
                           $$->lineno = savedLineNo;
                         }
                    ;
args                : arg_list
                         { $$ = $1; }
                    | empty
                         { $$ = $1; }
                    ;
arg_list            : arg_list COMMA expression
                         { YYSTYPE t = $1; 
                           if (t != NULL)
                           { while (t->sibling != NULL)
                                t = t->sibling;
                             t->sibling = $3;
                             $$ = $1; }
                             else $$ = $3;
                         }
                    | expression
                         { $$ = $1; }
                    ;
empty               : { $$ = NULL;}
                    ;

%%

当我使用printf进行调试时,我确认规则“RETURN expression SEMI”中的所有其他非终结符都具有正确的值(树节点的指针)。这个yacc文件出了什么问题?

1 个答案:

答案 0 :(得分:2)

$1return令牌。 $2应该是表达式。