#include "../parser.h" #include "ast.h" struct ASTNode* parse_stmt(struct Parser* parser) { flushpeektok(parser); enum TokenType ttype = peektoktype(parser); struct ASTNode* node = new_ast_node(); switch (ttype) { case TOKEN_IF: { /** * if (exp) stmt * if (exp) stmt else stmt */ poptok(parser); expecttok(parser, TOKEN_L_PAREN); node->if_stmt.cond = parse_expr(parser); flushpeektok(parser); expecttok(parser, TOKEN_R_PAREN); node->if_stmt.if_stmt = parse_stmt(parser); ttype = peektoktype(parser); if (ttype == TOKEN_ELSE) { poptok(parser); node->if_stmt.else_stmt = parse_stmt(parser); } else { node->if_stmt.else_stmt = NULL; } node->type = NT_STMT_IF; break; } case TOKEN_SWITCH: { /** * switch (exp) stmt */ poptok(parser); expecttok(parser, TOKEN_L_PAREN); node->switch_stmt.cond = parse_expr(parser); expecttok(parser, TOKEN_R_PAREN); node->switch_stmt.body = parse_stmt(parser); node->type = NT_STMT_SWITCH; break; } case TOKEN_WHILE: { /** * while (exp) stmt */ poptok(parser); expecttok(parser, TOKEN_L_PAREN); node->while_stmt.cond = parse_expr(parser); expecttok(parser, TOKEN_R_PAREN); node->while_stmt.body = parse_stmt(parser); node->type = NT_STMT_WHILE; break; } case TOKEN_DO: { /** * do stmt while (exp) */ poptok(parser); node->do_while_stmt.body = parse_stmt(parser); ttype = peektoktype(parser); if (ttype != TOKEN_WHILE) { error("expected while after do"); } poptok(parser); expecttok(parser, TOKEN_L_PAREN); node->do_while_stmt.cond = parse_expr(parser); expecttok(parser, TOKEN_R_PAREN); node->type = NT_STMT_DOWHILE; break; } case TOKEN_FOR: { /** * for (init; [cond]; [iter]) stmt */ // node->children.stmt.for_stmt.init poptok(parser); ttype = peektoktype(parser); if (ttype != TOKEN_L_PAREN) { error("expected ( after for"); } poptok(parser); // init expr or init decl_var // TODO need add this feature node->for_stmt.init = parse_expr(parser); expecttok(parser, TOKEN_SEMICOLON); // cond expr or null ttype = peektoktype(parser); if (ttype != TOKEN_SEMICOLON) { node->for_stmt.cond = parse_expr(parser); expecttok(parser, TOKEN_SEMICOLON); } else { node->for_stmt.cond = NULL; poptok(parser); } // iter expr or null ttype = peektoktype(parser); if (ttype != TOKEN_R_PAREN) { node->for_stmt.iter = parse_expr(parser); expecttok(parser, TOKEN_R_PAREN); } else { node->for_stmt.iter = NULL; poptok(parser); } node->for_stmt.body = parse_stmt(parser); node->type = NT_STMT_FOR; break; } case TOKEN_BREAK: { /** * break ; */ // TODO check 导致外围 for、while 或 do-while 循环或 switch 语句终止。 poptok(parser); expecttok(parser, TOKEN_SEMICOLON); node->type = NT_STMT_BREAK; break; } case TOKEN_CONTINUE: { /** * continue ; */ // TODO check 导致跳过整个 for、 while 或 do-while 循环体的剩余部分。 poptok(parser); expecttok(parser, TOKEN_SEMICOLON); node->type = NT_STMT_CONTINUE; break; } case TOKEN_RETURN: { /** * return [exp] ; */ // TODO 终止当前函数并返回指定值给调用方函数。 poptok(parser); ttype = peektoktype(parser); if (ttype != TOKEN_SEMICOLON) { node->return_stmt.expr_stmt = parse_expr(parser); flushpeektok(parser); expecttok(parser, TOKEN_SEMICOLON); } else { node->return_stmt.expr_stmt = NULL; } poptok(parser); node->type = NT_STMT_RETURN; break; } case TOKEN_GOTO: { /** * goto label ; */ // TODO check label 将控制无条件转移到所欲位置。 //在无法用约定的构造将控制转移到所欲位置时使用。 poptok(parser); // find symbol table ttype = peektoktype(parser); if (ttype != TOKEN_IDENT) { error("expect identifier after goto"); } expecttok(parser, TOKEN_SEMICOLON); // TODO filling label node->goto_stmt.label = parse_ident(parser); node->type = NT_STMT_GOTO; break; } case TOKEN_SEMICOLON: { /** * ; * empty stmt using by : * while () ; * if () ; * for () ; */ poptok(parser); node->type = NT_STMT_EMPTY; break; } case TOKEN_L_BRACE: { /** * stmt_block like: { (decl_var | stmt) ... } */ node->block_stmt.block = parse_block(parser); node->type = NT_STMT_BLOCK; break; } case TOKEN_IDENT: { // TODO label goto if (peektoktype(parser) != TOKEN_COLON) { goto EXP; } node->label_stmt.label = parse_ident(parser); expecttok(parser, TOKEN_COLON); node->type = NT_STMT_LABEL; break; } case TOKEN_CASE: { // TODO label switch poptok(parser); error("unimplemented switch label"); node->label_stmt.label = parse_expr(parser); // TODO 该表达式为const int expecttok(parser, TOKEN_COLON); node->type = NT_STMT_CASE; break; } case TOKEN_DEFAULT: { // TODO label switch default poptok(parser); expecttok(parser, TOKEN_COLON); node->type = NT_STMT_DEFAULT; break; } default: { /** * exp ; */ EXP: node->expr_stmt.expr_stmt = parse_expr(parser); flushpeektok(parser); ttype = peektoktype(parser); if (ttype != TOKEN_SEMICOLON) { error("exp must end with \";\""); } poptok(parser); node->type = NT_STMT_EXPR; break; } } }