aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-08-26 13:54:35 +0100
committergingerBill <bill@gingerbill.org>2019-08-26 13:54:35 +0100
commit01c10aa9447d135bdda5dc25583a5e1f94cbda6d (patch)
tree10f37633b1cf71e8dcb29afb3418220e71daf733 /src/parser.cpp
parent4908d1ebdd00a8822d9ef59245f2456db4b6dbfc (diff)
`inline for` loops (only for 'in' based for loops)
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp83
1 files changed, 79 insertions, 4 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 9aebc78d6..8c32f35ff 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -51,6 +51,7 @@ Token ast_token(Ast *node) {
case Ast_ReturnStmt: return node->ReturnStmt.token;
case Ast_ForStmt: return node->ForStmt.token;
case Ast_RangeStmt: return node->RangeStmt.token;
+ case Ast_InlineRangeStmt: return node->InlineRangeStmt.inline_token;
case Ast_CaseClause: return node->CaseClause.token;
case Ast_SwitchStmt: return node->SwitchStmt.token;
case Ast_TypeSwitchStmt: return node->TypeSwitchStmt.token;
@@ -257,6 +258,12 @@ Ast *clone_ast(Ast *node) {
n->RangeStmt.expr = clone_ast(n->RangeStmt.expr);
n->RangeStmt.body = clone_ast(n->RangeStmt.body);
break;
+ case Ast_InlineRangeStmt:
+ n->InlineRangeStmt.val0 = clone_ast(n->InlineRangeStmt.val0);
+ n->InlineRangeStmt.val1 = clone_ast(n->InlineRangeStmt.val1);
+ n->InlineRangeStmt.expr = clone_ast(n->InlineRangeStmt.expr);
+ n->InlineRangeStmt.body = clone_ast(n->InlineRangeStmt.body);
+ break;
case Ast_CaseClause:
n->CaseClause.list = clone_ast_array(n->CaseClause.list);
n->CaseClause.stmts = clone_ast_array(n->CaseClause.stmts);
@@ -748,6 +755,18 @@ Ast *ast_range_stmt(AstFile *f, Token token, Ast *val0, Ast *val1, Token in_toke
return result;
}
+Ast *ast_inline_range_stmt(AstFile *f, Token inline_token, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) {
+ Ast *result = alloc_ast_node(f, Ast_InlineRangeStmt);
+ result->InlineRangeStmt.inline_token = inline_token;
+ result->InlineRangeStmt.for_token = for_token;
+ result->InlineRangeStmt.val0 = val0;
+ result->InlineRangeStmt.val1 = val1;
+ result->InlineRangeStmt.in_token = in_token;
+ result->InlineRangeStmt.expr = expr;
+ result->InlineRangeStmt.body = body;
+ return result;
+}
+
Ast *ast_switch_stmt(AstFile *f, Token token, Ast *init, Ast *tag, Ast *body) {
Ast *result = alloc_ast_node(f, Ast_SwitchStmt);
result->SwitchStmt.token = token;
@@ -1119,6 +1138,17 @@ Token advance_token(AstFile *f) {
return prev;
}
+bool peek_token_kind(AstFile *f, TokenKind kind) {
+ for (isize i = f->curr_token_index+1; i < f->tokens.count; i++) {
+ Token tok = f->tokens[i];
+ if (kind != Token_Comment && tok.kind == Token_Comment) {
+ continue;
+ }
+ return tok.kind == kind;
+ }
+ return false;
+}
+
Token expect_token(AstFile *f, TokenKind kind) {
Token prev = f->curr_token;
if (prev.kind != kind) {
@@ -2092,7 +2122,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
bool prev_allow_range = f->allow_range;
f->allow_range = true;
- elem = parse_expr(f, false);
+ elem = parse_expr(f, true);
f->allow_range = prev_allow_range;
if (allow_token(f, Token_Semicolon)) {
underlying = parse_type(f);
@@ -2650,7 +2680,7 @@ Ast *parse_simple_stmt(AstFile *f, u32 flags) {
allow_token(f, Token_in);
bool prev_allow_range = f->allow_range;
f->allow_range = true;
- Ast *expr = parse_expr(f, false);
+ Ast *expr = parse_expr(f, true);
f->allow_range = prev_allow_range;
auto rhs = array_make<Ast *>(heap_allocator(), 0, 1);
@@ -3779,10 +3809,55 @@ Ast *parse_stmt(AstFile *f) {
Token token = f->curr_token;
switch (token.kind) {
// Operands
- case Token_context: // Also allows for `context =`
- case Token_proc:
case Token_inline:
+ if (peek_token_kind(f, Token_for)) {
+ Token inline_token = expect_token(f, Token_inline);
+ Token for_token = expect_token(f, Token_for);
+ Ast *val0 = nullptr;
+ Ast *val1 = nullptr;
+ Token in_token = {};
+ Ast *expr = nullptr;
+ Ast *body = nullptr;
+
+ bool bad_stmt = false;
+
+ if (f->curr_token.kind != Token_in) {
+ Array<Ast *> idents = parse_ident_list(f, false);
+ switch (idents.count) {
+ case 1:
+ val0 = idents[0];
+ break;
+ case 2:
+ val0 = idents[0];
+ val1 = idents[1];
+ break;
+ default:
+ syntax_error(for_token, "Expected either 1 or 2 identifiers");
+ bad_stmt = true;
+ break;
+ }
+ }
+ in_token = expect_token(f, Token_in);
+
+ bool prev_allow_range = f->allow_range;
+ f->allow_range = true;
+ expr = parse_expr(f, true);
+ f->allow_range = prev_allow_range;
+
+ if (allow_token(f, Token_do)) {
+ body = convert_stmt_to_body(f, parse_stmt(f));
+ } else {
+ body = parse_block_stmt(f, false);
+ }
+ if (bad_stmt) {
+ return ast_bad_stmt(f, inline_token, f->curr_token);
+ }
+ return ast_inline_range_stmt(f, inline_token, for_token, val0, val1, in_token, expr, body);
+ }
+ /* fallthrough */
case Token_no_inline:
+ case Token_context: // Also allows for `context =`
+ case Token_proc:
case Token_Ident:
case Token_Integer:
case Token_Float: