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