Stmt *new_stmt_goto(SrcPos pos, char *label) { Stmt *s = new_stmt(STMT_GOTO, pos); s->label = label; return(s); }
Stmt *parse_stmt_for(SrcPos pos) { Stmt *init = null; Expr *cond = null; Stmt *next = null; if (!is_token(TOKEN_LBRACE)) { expect_token(TOKEN_LPAREN); if (!is_token(TOKEN_SEMICOLON)) { init = parse_simple_stmt(); } if (match_token(TOKEN_SEMICOLON)) { if (!is_token(TOKEN_SEMICOLON)) { cond = parse_expr(); } if (match_token(TOKEN_SEMICOLON)) { if (!is_token(TOKEN_RPAREN)) { next = parse_simple_stmt(); if (next->kind == STMT_INIT) { error_here("Init statements not allowed in for-statement's next clause"); } } } } } expect_token(TOKEN_RPAREN); return(new_stmt_for(pos, init, cond, next, parse_stmt_block())); }
Stmt *new_stmt_label(SrcPos pos, char *label) { Stmt *s = new_stmt(STMT_LABEL, pos); s->label = label; return(s); }
Stmt *new_stmt_note(SrcPos pos, Note note) { Stmt *s = new_stmt(STMT_NOTE, pos); s->note = note; return(s); }
Stmt *new_stmt_for(SrcPos pos, Stmt *init, Expr *cond, Stmt *next, StmtList block) { var s = new_stmt(STMT_FOR, pos); s->for_stmt.init = init; s->for_stmt.cond = cond; s->for_stmt.next = next; s->for_stmt.block = block; return(s); }
Note *get_stmt_note(Stmt *stmt, char *name) { for (var i = 0; i < stmt->notes.num_notes; i++) { Note *note = stmt->notes.notes + i; if (note->name == name) { return(note); } } return(null); }
Stmt *new_stmt_if(SrcPos pos, Stmt *init, Expr *cond, StmtList then_block, ElseIf **elseifs, int num_elseifs, StmtList else_block) { var s = new_stmt(STMT_IF, pos); s->if_stmt.cond = cond; s->if_stmt.init = init; s->if_stmt.then_block = then_block; s->if_stmt.elseifs = elseifs; s->if_stmt.num_elseifs = num_elseifs; s->if_stmt.else_block = else_block; return(s); }
Stmt *parse_stmt_if(SrcPos pos) { expect_token(TOKEN_LPAREN); Expr *cond = parse_expr(); Stmt *init = parse_init_stmt(cond); if (init != null) { if (match_token(TOKEN_SEMICOLON)) { cond = parse_expr(); } else { cond = null; } } expect_token(TOKEN_RPAREN); var then_block = parse_stmt_block(); var else_block = default(StmtList); var buf = PtrBuffer.Create(); while (match_keyword(else_keyword)) { if (!match_keyword(if_keyword)) { else_block = parse_stmt_block(); break; } var elseif_cond = parse_paren_expr(); var elseif_block = parse_stmt_block(); var elif = (ElseIf *)xmalloc(sizeof(ElseIf)); elif->cond = elseif_cond; elif->block = elseif_block; buf->Add(elif); } return(new_stmt_if(pos, init, cond, then_block, (ElseIf **)buf->_begin, buf->count, else_block)); }
Stmt *parse_simple_stmt() { SrcPos pos = token.pos; Expr * expr = parse_expr(); Stmt * stmt = parse_init_stmt(expr); if (stmt == null) { if (is_assign_op()) { TokenKind op = token.kind; next_token(); stmt = new_stmt_assign(pos, op, expr, parse_expr()); } else { stmt = new_stmt_expr(pos, expr); } } return(stmt); }
Stmt *parse_init_stmt(Expr *left) { var pos = token.pos; Stmt *stmt = null; if (match_token(TOKEN_COLON_ASSIGN)) { if (left->kind != EXPR_NAME) { fatal_error_here(":= must be preceded by a name"); return(null); } return(new_stmt_init(left->pos, left->name, null, parse_expr(), false)); } else if (match_token(TOKEN_COLON)) { if (left->kind != EXPR_NAME) { fatal_error_here(": must be preceded by a name"); return(null); } char * name = left->name; Typespec *type = parse_type(); Expr * expr = null; bool is_undef = false; if (match_token(TOKEN_ASSIGN)) { is_undef = match_keyword(undef_keyword); if (!is_undef) { expr = parse_expr(); } } return(new_stmt_init(left->pos, name, type, expr, is_undef)); } return(null); }
Stmt *parse_stmt() { Notes notes = parse_notes(); var pos = token.pos; Stmt *stmt = null; if (match_keyword(if_keyword)) { stmt = parse_stmt_if(pos); } else if (match_keyword(while_keyword)) { stmt = parse_stmt_while(pos); } else if (match_keyword(do_keyword)) { stmt = parse_stmt_do_while(pos); } else if (match_keyword(for_keyword)) { stmt = parse_stmt_for(pos); } else if (match_keyword(switch_keyword)) { stmt = parse_stmt_switch(pos); } else if (is_token(TOKEN_LBRACE)) { stmt = new_stmt_block(pos, parse_stmt_block()); } else if (match_keyword(break_keyword)) { expect_token(TOKEN_SEMICOLON); stmt = new_stmt_break(pos); } else if (match_keyword(continue_keyword)) { expect_token(TOKEN_SEMICOLON); stmt = new_stmt_continue(pos); } else if (match_keyword(return_keyword)) { Expr *expr = null; if (!is_token(TOKEN_SEMICOLON)) { expr = parse_expr(); } expect_token(TOKEN_SEMICOLON); stmt = new_stmt_return(pos, expr); } else if (match_token(TOKEN_POUND)) { Note note = parse_note(); expect_token(TOKEN_SEMICOLON); stmt = new_stmt_note(pos, note); } else if (match_token(TOKEN_COLON)) { stmt = new_stmt_label(pos, parse_name()); } else if (match_keyword(goto_keyword)) { stmt = new_stmt_goto(pos, parse_name()); expect_token(TOKEN_SEMICOLON); } else { stmt = parse_simple_stmt(); expect_token(TOKEN_SEMICOLON); } stmt->notes = notes; return(stmt); }
void print_stmt(Stmt *stmt) { var s = stmt; switch (s->kind) { case STMT_DECL: print_decl(s->decl); break; case STMT_RETURN: printf("(return"); if (s->expr != null) { printf(" "); print_expr(s->expr); } printf(")"); break; case STMT_BREAK: printf("(break)"); break; case STMT_CONTINUE: printf("(continue)"); break; case STMT_BLOCK: print_stmt_block(s->block); break; case STMT_IF: printf("(if "); print_expr(s->if_stmt.cond); _indent++; print_newline(); print_stmt_block(s->if_stmt.then_block); for (var it = s->if_stmt.elseifs; it != s->if_stmt.elseifs + s->if_stmt.num_elseifs; it++) { print_newline(); printf("elseif "); print_expr((*it)->cond); print_newline(); print_stmt_block((*it)->block); } if (s->if_stmt.else_block.num_stmts != 0) { print_newline(); printf("else "); print_newline(); print_stmt_block(s->if_stmt.else_block); } _indent--; printf(")"); break; case STMT_WHILE: printf("(while "); print_expr(s->while_stmt.cond); _indent++; print_newline(); print_stmt_block(s->while_stmt.block); _indent--; printf(")"); break; case STMT_DO_WHILE: printf("(do-while "); print_expr(s->while_stmt.cond); _indent++; print_newline(); print_stmt_block(s->while_stmt.block); _indent--; printf(")"); break; case STMT_FOR: printf("(for "); print_stmt(s->for_stmt.init); print_expr(s->for_stmt.cond); print_stmt(s->for_stmt.next); _indent++; print_newline(); print_stmt_block(s->for_stmt.block); _indent--; printf(")"); break; case STMT_SWITCH: printf("(switch "); print_expr(s->switch_stmt.expr); _indent++; for (var it = s->switch_stmt.cases; it != s->switch_stmt.cases + s->switch_stmt.num_cases; it++) { print_newline(); printf("(case ({0}", it->is_default ? " default" : ""); for (var pattern = it->patterns; pattern != it->patterns + it->num_patterns; pattern++) { printf(" "); print_expr(pattern->start); if (pattern->end != null) { printf(", "); print_expr(pattern->end); } } printf(" ) "); _indent++; print_newline(); print_stmt_block(it->block); _indent--; } _indent--; printf(")"); break; case STMT_ASSIGN: printf("({0} ", token_kind_names[(long)s->assign.op]); print_expr(s->assign.left); if (s->assign.right != null) { printf(" "); print_expr(s->assign.right); } printf(")"); break; case STMT_INIT: printf("(:= {0} ", s->init.name); print_expr(s->init.expr); printf(")"); break; case STMT_EXPR: print_expr(s->expr); break; default: assert(false); break; } }