mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-23 22:25:00 -07:00
Ternary expression (removed if and block expression)
This commit is contained in:
+117
-139
@@ -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_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);
|
||||
}
|
||||
// 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;
|
||||
// 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;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
// f->expr_level = prev_level;
|
||||
|
||||
if (cond == NULL) {
|
||||
syntax_error(f->curr_token, "Expected condition for if statement");
|
||||
}
|
||||
// if (cond == NULL) {
|
||||
// syntax_error(f->curr_token, "Expected condition for if statement");
|
||||
// }
|
||||
|
||||
body = parse_block_expr(f);
|
||||
// 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]);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// 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:
|
||||
|
||||
Reference in New Issue
Block a user