2014-10-25 3 views
0

Я делаю C-компилятор, следующий за [Конструкция компилятора, принципы и практика]. и я почти сделал парсер, используя yacc, но одно правило в yacc делает ошибку.yacc получает нулевое значение от non-терминала

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

при разборе оператора возврата с помощью "RETURN выражения SEMI" правило $ 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 выражения SEMI» имеет правильное значение (указателя tree node). что не так с этим файлом yacc?

ответ

2

$1 - токен return. $2 должно быть выражением.

+0

oh ...... было очень трудно найти это. спасибо вам за орлиный глаз. – user3703559