diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-01-27 17:43:42 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-01-27 17:43:42 +0000 |
| commit | 92453369c5558feaaaa116fbc54968b087e1aeab (patch) | |
| tree | a00501fdc52f69c7dd7c415e103b9b13d51e6ad5 /src/parser.c | |
| parent | 832009f33acc573d44dd9dfb470ad8fef72216ff (diff) | |
Remove while loop and readd c-style for loops i.e. all loops are just `for`
Diffstat (limited to 'src/parser.c')
| -rw-r--r-- | src/parser.c | 161 |
1 files changed, 111 insertions, 50 deletions
diff --git a/src/parser.c b/src/parser.c index b3b1822c2..0a9b39ea9 100644 --- a/src/parser.c +++ b/src/parser.c @@ -221,16 +221,18 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \ Token token; \ AstNodeArray results; \ }) \ - AST_NODE_KIND(WhileStmt, "while statement", struct { \ + AST_NODE_KIND(ForStmt, "for statement", struct { \ Token token; \ AstNode *init; \ AstNode *cond; \ + AstNode *post; \ AstNode *body; \ }) \ - AST_NODE_KIND(ForStmt, "range statement", struct { \ + AST_NODE_KIND(RangeStmt, "range statement", struct { \ Token token; \ AstNode *value; \ AstNode *index; \ + Token in_token; \ AstNode *expr; \ AstNode *body; \ }) \ @@ -501,8 +503,10 @@ Token ast_node_token(AstNode *node) { return node->WhenStmt.token; case AstNode_ReturnStmt: return node->ReturnStmt.token; - case AstNode_WhileStmt: - return node->WhileStmt.token; + case AstNode_ForStmt: + return node->ForStmt.token; + case AstNode_RangeStmt: + return node->RangeStmt.token; case AstNode_MatchStmt: return node->MatchStmt.token; case AstNode_CaseClause: @@ -904,24 +908,28 @@ AstNode *make_return_stmt(AstFile *f, Token token, AstNodeArray results) { return result; } -AstNode *make_while_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body) { - AstNode *result = make_node(f, AstNode_WhileStmt); - result->WhileStmt.token = token; - result->WhileStmt.init = init; - result->WhileStmt.cond = cond; - result->WhileStmt.body = body; - return result; -} -AstNode *make_for_stmt(AstFile *f, Token token, AstNode *value, AstNode *index, AstNode *expr, AstNode *body) { + +AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *post, AstNode *body) { AstNode *result = make_node(f, AstNode_ForStmt); result->ForStmt.token = token; - result->ForStmt.value = value; - result->ForStmt.index = index; - result->ForStmt.expr = expr; + result->ForStmt.init = init; + result->ForStmt.cond = cond; + result->ForStmt.post = post; result->ForStmt.body = body; return result; } +AstNode *make_range_stmt(AstFile *f, Token token, AstNode *value, AstNode *index, Token in_token, AstNode *expr, AstNode *body) { + AstNode *result = make_node(f, AstNode_RangeStmt); + result->RangeStmt.token = token; + result->RangeStmt.value = value; + result->RangeStmt.index = index; + result->RangeStmt.in_token = in_token; + result->RangeStmt.expr = expr; + result->RangeStmt.body = body; + return result; +} + AstNode *make_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, AstNode *body) { AstNode *result = make_node(f, AstNode_MatchStmt); result->MatchStmt.token = token; @@ -1258,7 +1266,6 @@ void fix_advance_to_next_stmt(AstFile *f) { case Token_if: case Token_when: case Token_return: - case Token_while: case Token_range: case Token_match: case Token_defer: @@ -1626,7 +1633,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str AstNodeArray parse_lhs_expr_list(AstFile *f); AstNodeArray parse_rhs_expr_list(AstFile *f); -AstNode * parse_simple_stmt (AstFile *f); +AstNode * parse_simple_stmt (AstFile *f, bool in_stmt_ok); AstNode * parse_type (AstFile *f); AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { @@ -1673,7 +1680,7 @@ AstNode *parse_if_expr(AstFile *f) { if (allow_token(f, Token_Semicolon)) { cond = parse_expr(f, false); } else { - init = parse_simple_stmt(f); + init = parse_simple_stmt(f, false); if (allow_token(f, Token_Semicolon)) { cond = parse_expr(f, false); } else { @@ -2261,7 +2268,8 @@ AstNode *parse_value_decl(AstFile *f, AstNodeArray lhs) { return make_value_decl(f, is_mutable, lhs, type, values); } -AstNode *parse_simple_stmt(AstFile *f) { + +AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) { AstNodeArray lhs = parse_lhs_expr_list(f); Token token = f->curr_token; switch (token.kind) { @@ -2293,6 +2301,28 @@ AstNode *parse_simple_stmt(AstFile *f) { return make_assign_stmt(f, token, lhs, rhs); } break; + case Token_in: + if (in_stmt_ok) { + allow_token(f, Token_in); + AstNode *expr = parse_expr(f, false); + switch (f->curr_token.kind) { + case Token_HalfOpenRange: + case Token_Ellipsis: { + Token op = f->curr_token; + next_token(f); + AstNode *right = parse_expr(f, false); + expr = make_interval_expr(f, op, expr, right); + } break; + } + + AstNodeArray rhs = {0}; + array_init_count(&rhs, heap_allocator(), 1); + rhs.e[0] = expr; + + return make_assign_stmt(f, token, lhs, rhs); + } + break; + case Token_Colon: return parse_value_decl(f, lhs); } @@ -2782,7 +2812,7 @@ AstNode *parse_if_stmt(AstFile *f) { if (allow_token(f, Token_Semicolon)) { cond = parse_expr(f, false); } else { - init = parse_simple_stmt(f); + init = parse_simple_stmt(f, false); if (allow_token(f, Token_Semicolon)) { cond = parse_expr(f, false); } else { @@ -2900,47 +2930,78 @@ AstNode *parse_give_stmt(AstFile *f) { return make_expr_stmt(f, ge); } -AstNode *parse_while_stmt(AstFile *f) { +AstNode *parse_for_stmt(AstFile *f) { if (f->curr_proc == NULL) { - syntax_error(f->curr_token, "You cannot use a while statement in the file scope"); + syntax_error(f->curr_token, "You cannot use a for statement in the file scope"); return make_bad_stmt(f, f->curr_token, f->curr_token); } - Token token = expect_token(f, Token_while); + Token token = expect_token(f, Token_for); AstNode *init = NULL; AstNode *cond = NULL; + AstNode *post = NULL; AstNode *body = NULL; + bool is_range = false; - isize prev_level = f->expr_level; - f->expr_level = -1; - + if (f->curr_token.kind != Token_OpenBrace) { + isize prev_level = f->expr_level; + f->expr_level = -1; + if (f->curr_token.kind != Token_Semicolon) { + cond = parse_simple_stmt(f, true); + if (cond->kind == AstNode_AssignStmt && + cond->AssignStmt.op.kind == Token_in) { + is_range = true; + } + } - cond = parse_simple_stmt(f); - if (is_ast_node_complex_stmt(cond)) { - syntax_error(f->curr_token, "You are not allowed that type of statement in a while statement, it is too complex!"); - } + if (!is_range && f->curr_token.kind == Token_Semicolon) { + next_token(f); + init = cond; + cond = NULL; + if (f->curr_token.kind != Token_Semicolon) { + cond = parse_simple_stmt(f, false); + } + expect_semicolon(f, cond); + if (f->curr_token.kind != Token_OpenBrace) { + post = parse_simple_stmt(f, false); + } + } - if (allow_token(f, Token_Semicolon)) { - init = cond; - cond = parse_simple_stmt(f); + f->expr_level = prev_level; } - f->expr_level = prev_level; body = parse_block_stmt(f, false); - cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression")); - - return make_while_stmt(f, token, init, cond, body); -} - + if (is_range) { + GB_ASSERT(cond->kind == AstNode_AssignStmt); + Token in_token = cond->AssignStmt.op; + AstNode *value = NULL; + AstNode *index = NULL; + switch (cond->AssignStmt.lhs.count) { + case 1: + value = cond->AssignStmt.lhs.e[0]; + break; + case 2: + value = cond->AssignStmt.lhs.e[0]; + index = cond->AssignStmt.lhs.e[1]; + break; + default: + error_node(cond, "Expected at 1 or 2 identifiers"); + return make_bad_stmt(f, token, f->curr_token); + } -AstNode *parse_for_stmt(AstFile *f) { - if (f->curr_proc == NULL) { - syntax_error(f->curr_token, "You cannot use a for statement in the file scope"); - return make_bad_stmt(f, f->curr_token, f->curr_token); + AstNode *rhs = NULL; + if (cond->AssignStmt.rhs.count > 0) { + rhs = cond->AssignStmt.rhs.e[0]; + } + return make_range_stmt(f, token, value, index, in_token, rhs, body); } + cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression")); + return make_for_stmt(f, token, init, cond, post, body); + +#if 0 Token token = expect_token(f, Token_for); AstNodeArray names = parse_ident_list(f); parse_check_name_list_for_reserves(f, names); @@ -2977,7 +3038,8 @@ AstNode *parse_for_stmt(AstFile *f) { return make_bad_stmt(f, token, f->curr_token); } - return make_for_stmt(f, token, value, index, expr, body); + return make_range_stmt(f, token, value, index, expr, body); +#endif } AstNode *parse_case_clause(AstFile *f) { @@ -3030,7 +3092,7 @@ AstNode *parse_match_stmt(AstFile *f) { AstNode *var = parse_identifier(f); expect_token_after(f, Token_in, "match type name"); - tag = parse_simple_stmt(f); + tag = parse_simple_stmt(f, false); f->expr_level = prev_level; @@ -3052,13 +3114,13 @@ AstNode *parse_match_stmt(AstFile *f) { isize prev_level = f->expr_level; f->expr_level = -1; if (f->curr_token.kind != Token_Semicolon) { - tag = parse_simple_stmt(f); + tag = parse_simple_stmt(f, false); } if (allow_token(f, Token_Semicolon)) { init = tag; tag = NULL; if (f->curr_token.kind != Token_OpenBrace) { - tag = parse_simple_stmt(f); + tag = parse_simple_stmt(f, false); } } @@ -3151,13 +3213,12 @@ AstNode *parse_stmt(AstFile *f) { case Token_Sub: case Token_Xor: case Token_Not: - s = parse_simple_stmt(f); + s = parse_simple_stmt(f, false); expect_semicolon(f, s); return s; case Token_if: return parse_if_stmt(f); case Token_when: return parse_when_stmt(f); - case Token_while: return parse_while_stmt(f); case Token_for: return parse_for_stmt(f); case Token_match: return parse_match_stmt(f); case Token_defer: return parse_defer_stmt(f); |