|
@@ -168,24 +168,9 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
|
|
|
Token open; \
|
|
|
Token close; \
|
|
|
}) \
|
|
|
- AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \
|
|
|
- AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
|
|
|
- AST_NODE_KIND(BlockExpr, "block expr", struct { \
|
|
|
- AstNodeArray stmts; \
|
|
|
- Token open, close; \
|
|
|
- AstNode *give_node; \
|
|
|
- }) \
|
|
|
- AST_NODE_KIND(GiveExpr, "give expression", struct { \
|
|
|
- Token token; \
|
|
|
- AstNodeArray results; \
|
|
|
- }) \
|
|
|
- AST_NODE_KIND(IfExpr, "if expression", struct { \
|
|
|
- Token token; \
|
|
|
- AstNode *init; \
|
|
|
- AstNode *cond; \
|
|
|
- AstNode *body; \
|
|
|
- AstNode *else_expr; \
|
|
|
- }) \
|
|
|
+ AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \
|
|
|
+ AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
|
|
|
+ AST_NODE_KIND(TernaryExpr, "ternary expression", struct { AstNode *cond, *x, *y; }) \
|
|
|
AST_NODE_KIND(IntervalExpr, "interval expression", struct { Token op; AstNode *left, *right; }) \
|
|
|
AST_NODE_KIND(_ExprEnd, "", i32) \
|
|
|
AST_NODE_KIND(_StmtBegin, "", i32) \
|
|
@@ -465,9 +450,7 @@ Token ast_node_token(AstNode *node) {
|
|
|
case AstNode_CastExpr: return node->CastExpr.token;
|
|
|
case AstNode_FieldValue: return node->FieldValue.eq;
|
|
|
case AstNode_DerefExpr: return node->DerefExpr.op;
|
|
|
- case AstNode_BlockExpr: return node->BlockExpr.open;
|
|
|
- case AstNode_GiveExpr: return node->GiveExpr.token;
|
|
|
- case AstNode_IfExpr: return node->IfExpr.token;
|
|
|
+ case AstNode_TernaryExpr: return ast_node_token(node->TernaryExpr.cond);
|
|
|
case AstNode_IntervalExpr: return ast_node_token(node->IntervalExpr.left);
|
|
|
|
|
|
case AstNode_BadStmt: return node->BadStmt.begin;
|
|
@@ -768,29 +751,11 @@ AstNode *ast_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token o
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-AstNode *ast_block_expr(AstFile *f, AstNodeArray stmts, Token open, Token close) {
|
|
|
- AstNode *result = make_ast_node(f, AstNode_BlockExpr);
|
|
|
- result->BlockExpr.stmts = stmts;
|
|
|
- result->BlockExpr.open = open;
|
|
|
- result->BlockExpr.close = close;
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-AstNode *ast_give_expr(AstFile *f, Token token, AstNodeArray results) {
|
|
|
- AstNode *result = make_ast_node(f, AstNode_GiveExpr);
|
|
|
- result->GiveExpr.token = token;
|
|
|
- result->GiveExpr.results = results;
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-AstNode *ast_if_expr(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body, AstNode *else_expr) {
|
|
|
- AstNode *result = make_ast_node(f, AstNode_IfExpr);
|
|
|
- result->IfExpr.token = token;
|
|
|
- result->IfExpr.init = init;
|
|
|
- result->IfExpr.cond = cond;
|
|
|
- result->IfExpr.body = body;
|
|
|
- result->IfExpr.else_expr = else_expr;
|
|
|
+AstNode *ast_ternary_expr(AstFile *f, AstNode *cond, AstNode *x, AstNode *y) {
|
|
|
+ AstNode *result = make_ast_node(f, AstNode_TernaryExpr);
|
|
|
+ result->TernaryExpr.cond = cond;
|
|
|
+ result->TernaryExpr.x = x;
|
|
|
+ result->TernaryExpr.y = y;
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -1321,13 +1286,13 @@ void expect_semicolon(AstFile *f, AstNode *s) {
|
|
|
return;
|
|
|
}
|
|
|
} else {
|
|
|
- switch (s->kind) {
|
|
|
- case AstNode_GiveExpr:
|
|
|
- if (f->curr_token.kind == Token_CloseBrace) {
|
|
|
- return;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
+ // switch (s->kind) {
|
|
|
+ // case AstNode_GiveExpr:
|
|
|
+ // if (f->curr_token.kind == Token_CloseBrace) {
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ // break;
|
|
|
+ // }
|
|
|
}
|
|
|
syntax_error(prev_token, "Expected `;` after %.*s, got %.*s",
|
|
|
LIT(ast_node_strings[s->kind]), LIT(token_strings[prev_token.kind]));
|
|
@@ -1612,72 +1577,72 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
|
|
|
|
|
|
|
|
|
|
|
|
-AstNode *parse_block_expr(AstFile *f) {
|
|
|
- AstNodeArray stmts = {0};
|
|
|
- Token open, close;
|
|
|
- open = expect_token(f, Token_OpenBrace);
|
|
|
- f->expr_level++;
|
|
|
- stmts = parse_stmt_list(f);
|
|
|
- f->expr_level--;
|
|
|
- close = expect_token(f, Token_CloseBrace);
|
|
|
- return ast_block_expr(f, stmts, open, close);
|
|
|
-}
|
|
|
-
|
|
|
-AstNode *parse_if_expr(AstFile *f) {
|
|
|
- if (f->curr_proc == NULL) {
|
|
|
- syntax_error(f->curr_token, "You cannot use an if expression in the file scope");
|
|
|
- return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
|
- }
|
|
|
-
|
|
|
- Token token = expect_token(f, Token_if);
|
|
|
- AstNode *init = NULL;
|
|
|
- AstNode *cond = NULL;
|
|
|
- AstNode *body = NULL;
|
|
|
- AstNode *else_expr = NULL;
|
|
|
-
|
|
|
- isize prev_level = f->expr_level;
|
|
|
- f->expr_level = -1;
|
|
|
-
|
|
|
- if (allow_token(f, Token_Semicolon)) {
|
|
|
- cond = parse_expr(f, false);
|
|
|
- } else {
|
|
|
- init = parse_simple_stmt(f, false);
|
|
|
- if (allow_token(f, Token_Semicolon)) {
|
|
|
- cond = parse_expr(f, false);
|
|
|
- } else {
|
|
|
- cond = convert_stmt_to_expr(f, init, str_lit("boolean expression"));
|
|
|
- init = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- f->expr_level = prev_level;
|
|
|
-
|
|
|
- if (cond == NULL) {
|
|
|
- syntax_error(f->curr_token, "Expected condition for if statement");
|
|
|
- }
|
|
|
-
|
|
|
- body = parse_block_expr(f);
|
|
|
-
|
|
|
- if (allow_token(f, Token_else)) {
|
|
|
- switch (f->curr_token.kind) {
|
|
|
- case Token_if:
|
|
|
- else_expr = parse_if_expr(f);
|
|
|
- break;
|
|
|
- case Token_OpenBrace:
|
|
|
- else_expr = parse_block_expr(f);
|
|
|
- break;
|
|
|
- default:
|
|
|
- syntax_error(f->curr_token, "Expected if expression block statement");
|
|
|
- else_expr = ast_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
|
|
|
- break;
|
|
|
- }
|
|
|
- } else {
|
|
|
- syntax_error(f->curr_token, "An if expression must have an else clause");
|
|
|
- return ast_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
|
|
|
- }
|
|
|
-
|
|
|
- return ast_if_expr(f, token, init, cond, body, else_expr);
|
|
|
-}
|
|
|
+// AstNode *parse_block_expr(AstFile *f) {
|
|
|
+// AstNodeArray stmts = {0};
|
|
|
+// Token open, close;
|
|
|
+// open = expect_token(f, Token_OpenBrace);
|
|
|
+// f->expr_level++;
|
|
|
+// stmts = parse_stmt_list(f);
|
|
|
+// f->expr_level--;
|
|
|
+// close = expect_token(f, Token_CloseBrace);
|
|
|
+// return ast_block_expr(f, stmts, open, close);
|
|
|
+// }
|
|
|
+
|
|
|
+// AstNode *parse_if_expr(AstFile *f) {
|
|
|
+// if (f->curr_proc == NULL) {
|
|
|
+// syntax_error(f->curr_token, "You cannot use an if expression in the file scope");
|
|
|
+// return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
|
+// }
|
|
|
+
|
|
|
+// Token token = expect_token(f, Token_if);
|
|
|
+// AstNode *init = NULL;
|
|
|
+// AstNode *cond = NULL;
|
|
|
+// AstNode *body = NULL;
|
|
|
+// AstNode *else_expr = NULL;
|
|
|
+
|
|
|
+// isize prev_level = f->expr_level;
|
|
|
+// f->expr_level = -1;
|
|
|
+
|
|
|
+// if (allow_token(f, Token_Semicolon)) {
|
|
|
+// cond = parse_expr(f, false);
|
|
|
+// } else {
|
|
|
+// init = parse_simple_stmt(f, false);
|
|
|
+// if (allow_token(f, Token_Semicolon)) {
|
|
|
+// cond = parse_expr(f, false);
|
|
|
+// } else {
|
|
|
+// cond = convert_stmt_to_expr(f, init, str_lit("boolean expression"));
|
|
|
+// init = NULL;
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// f->expr_level = prev_level;
|
|
|
+
|
|
|
+// if (cond == NULL) {
|
|
|
+// syntax_error(f->curr_token, "Expected condition for if statement");
|
|
|
+// }
|
|
|
+
|
|
|
+// body = parse_block_expr(f);
|
|
|
+
|
|
|
+// if (allow_token(f, Token_else)) {
|
|
|
+// switch (f->curr_token.kind) {
|
|
|
+// case Token_if:
|
|
|
+// else_expr = parse_if_expr(f);
|
|
|
+// break;
|
|
|
+// case Token_OpenBrace:
|
|
|
+// else_expr = parse_block_expr(f);
|
|
|
+// break;
|
|
|
+// default:
|
|
|
+// syntax_error(f->curr_token, "Expected if expression block statement");
|
|
|
+// else_expr = ast_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
|
|
|
+// break;
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// syntax_error(f->curr_token, "An if expression must have an else clause");
|
|
|
+// return ast_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
|
|
|
+// }
|
|
|
+
|
|
|
+// return ast_if_expr(f, token, init, cond, body, else_expr);
|
|
|
+// }
|
|
|
|
|
|
AstNode *parse_operand(AstFile *f, bool lhs) {
|
|
|
AstNode *operand = NULL; // Operand
|
|
@@ -1791,16 +1756,16 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|
|
return type;
|
|
|
}
|
|
|
|
|
|
- case Token_if:
|
|
|
- if (!lhs && f->expr_level >= 0) {
|
|
|
- return parse_if_expr(f);
|
|
|
- }
|
|
|
- break;
|
|
|
- case Token_OpenBrace:
|
|
|
- if (!lhs && f->expr_level >= 0) {
|
|
|
- return parse_block_expr(f);
|
|
|
- }
|
|
|
- break;
|
|
|
+ // case Token_if:
|
|
|
+ // if (!lhs && f->expr_level >= 0) {
|
|
|
+ // return parse_if_expr(f);
|
|
|
+ // }
|
|
|
+ // break;
|
|
|
+ // case Token_OpenBrace:
|
|
|
+ // if (!lhs && f->expr_level >= 0) {
|
|
|
+ // return parse_block_expr(f);
|
|
|
+ // }
|
|
|
+ // break;
|
|
|
|
|
|
default: {
|
|
|
AstNode *type = parse_type_or_ident(f);
|
|
@@ -1984,6 +1949,19 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case Token_Question:
|
|
|
+ if (!lhs && operand != NULL && f->expr_level >= 0) {
|
|
|
+ AstNode *cond = operand;
|
|
|
+ Token token_q = expect_token(f, Token_Question);
|
|
|
+ AstNode *x = parse_expr(f, false);
|
|
|
+ Token token_c = expect_token(f, Token_Colon);
|
|
|
+ AstNode *y = parse_expr(f, false);
|
|
|
+ operand = ast_ternary_expr(f, cond, x, y);
|
|
|
+ } else {
|
|
|
+ loop = false;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
loop = false;
|
|
|
break;
|
|
@@ -2925,27 +2903,27 @@ AstNode *parse_return_stmt(AstFile *f) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-AstNode *parse_give_stmt(AstFile *f) {
|
|
|
- if (f->curr_proc == NULL) {
|
|
|
- syntax_error(f->curr_token, "You cannot use a give statement in the file scope");
|
|
|
- return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
|
- }
|
|
|
- if (f->expr_level == 0) {
|
|
|
- syntax_error(f->curr_token, "A give statement must be used within an expression");
|
|
|
- return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
|
- }
|
|
|
-
|
|
|
- Token token = expect_token(f, Token_give);
|
|
|
- AstNodeArray results;
|
|
|
- if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
|
|
|
- results = parse_rhs_expr_list(f);
|
|
|
- } else {
|
|
|
- results = make_ast_node_array(f);
|
|
|
- }
|
|
|
- AstNode *ge = ast_give_expr(f, token, results);
|
|
|
- expect_semicolon(f, ge);
|
|
|
- return ast_expr_stmt(f, ge);
|
|
|
-}
|
|
|
+// AstNode *parse_give_stmt(AstFile *f) {
|
|
|
+// if (f->curr_proc == NULL) {
|
|
|
+// syntax_error(f->curr_token, "You cannot use a give statement in the file scope");
|
|
|
+// return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
|
+// }
|
|
|
+// if (f->expr_level == 0) {
|
|
|
+// syntax_error(f->curr_token, "A give statement must be used within an expression");
|
|
|
+// return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
|
+// }
|
|
|
+
|
|
|
+// Token token = expect_token(f, Token_give);
|
|
|
+// AstNodeArray results;
|
|
|
+// if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
|
|
|
+// results = parse_rhs_expr_list(f);
|
|
|
+// } else {
|
|
|
+// results = make_ast_node_array(f);
|
|
|
+// }
|
|
|
+// AstNode *ge = ast_give_expr(f, token, results);
|
|
|
+// expect_semicolon(f, ge);
|
|
|
+// return ast_expr_stmt(f, ge);
|
|
|
+// }
|
|
|
|
|
|
AstNode *parse_for_stmt(AstFile *f) {
|
|
|
if (f->curr_proc == NULL) {
|
|
@@ -3227,7 +3205,7 @@ AstNode *parse_stmt(AstFile *f) {
|
|
|
case Token_defer: return parse_defer_stmt(f);
|
|
|
case Token_asm: return parse_asm_stmt(f);
|
|
|
case Token_return: return parse_return_stmt(f);
|
|
|
- case Token_give: return parse_give_stmt(f);
|
|
|
+ // case Token_give: return parse_give_stmt(f);
|
|
|
|
|
|
case Token_break:
|
|
|
case Token_continue:
|