Last active
February 5, 2023 17:27
-
-
Save pervognsen/e36305710f4cf103bf08146c0d363ea8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void parse_expr(Value *dest); | |
Sym *parse_ident(void) { | |
if (tok != TOK_IDENT) { | |
error("Expected identifier"); | |
} | |
Sym *ident = tok_sym; | |
next(); | |
return ident; | |
} | |
void parse_operand_expr(Value *dest) { | |
if (tok == TOK_INT) { | |
do_int_expr(dest, tok_int); | |
next(); | |
} else if (tok == TOK_FLOAT) { | |
do_float_expr(dest, tok_float); | |
next(); | |
} else if (tok == TOK_STR) { | |
do_str_expr(dest, tok_str); | |
next(); | |
} else if (tok == TOK_IDENT) { | |
do_ident_expr(dest, tok_sym); | |
next(); | |
} else if (match("(")) { | |
parse_expr(dest); | |
expect(")"); | |
} else { | |
error("Unexpected token in expression"); | |
} | |
} | |
void parse_base_expr(Value *dest) { | |
parse_operand_expr(dest); | |
for (;;) { | |
if (match("(")) { | |
Value args[MAX_ARGS]; | |
int num_args = 0; | |
if (!match(")")) { | |
parse_expr(&args[num_args++]); | |
while (match(",")) { | |
if (num_args == MAX_ARGS) { | |
error("Exceeded argument limit"); | |
} | |
parse_expr(&args[num_args++]); | |
} | |
expect(")"); | |
} | |
do_call_expr(dest, args, num_args); | |
} else if (match("[")) { | |
Value index; | |
parse_expr(&index); | |
do_index_expr(dest, &index); | |
} else if (match(".")) { | |
do_field_expr(dest, parse_ident()); | |
} else if (match("++")) { | |
do_postinc_expr(dest); | |
} else if (match("--")) { | |
do_postinc_expr(dest); | |
} else { | |
break; | |
} | |
} | |
} | |
void parse_unary_expr(Value *dest) { | |
if (match("-")) { | |
parse_unary_expr(dest); | |
do_neg_expr(dest); | |
} else if (match("!")) { | |
parse_unary_expr(dest); | |
do_not_expr(dest); | |
} else if (match("~")) { | |
parse_unary_expr(dest); | |
do_bnot_expr(dest); | |
} else if (match("*")) { | |
parse_unary_expr(dest); | |
do_deref_expr(dest); | |
} else if (match("&")) { | |
parse_unary_expr(dest); | |
do_addr_expr(dest); | |
} else { | |
parse_base_expr(dest); | |
} | |
} | |
void parse_mul_expr(Value *dest) { | |
parse_unary_expr(dest); | |
for (;;) { | |
Value src; | |
if (match("*")) { | |
parse_unary_expr(&src); | |
do_mul_expr(dest, &src); | |
} else if (match("/")) { | |
parse_unary_expr(&src); | |
do_div_expr(dest, &src); | |
} else if (match("%")) { | |
parse_unary_expr(&src); | |
do_mod_expr(dest, &src); | |
} else if (match("&")) { | |
parse_unary_expr(&src); | |
do_band_expr(dest, &src); | |
} else if (match("<<")) { | |
parse_unary_expr(&src); | |
do_lsh_expr(dest, &src); | |
} else if (match(">>")) { | |
parse_unary_expr(&src); | |
do_rsh_expr(dest, &src); | |
} else { | |
break; | |
} | |
} | |
} | |
void parse_add_expr(Value *dest) { | |
parse_mul_expr(dest); | |
for (;;) { | |
Value src; | |
if (match("+")) { | |
parse_mul_expr(&src); | |
do_add_expr(dest, &src); | |
} else if (match("-")) { | |
parse_mul_expr(&src); | |
do_sub_expr(dest, &src); | |
} else if (match("^")) { | |
parse_mul_expr(&src); | |
do_xor_expr(dest, &src); | |
} else if (match("|")) { | |
parse_mul_expr(&src); | |
do_bor_expr(dest, &src); | |
} else { | |
break; | |
} | |
} | |
} | |
void parse_cmp_expr(Value *dest) { | |
parse_add_expr(dest); | |
for (;;) { | |
Value src; | |
if (match("==")) { | |
parse_add_expr(&src); | |
do_eq_expr(dest, &src); | |
} else if (match("!=")) { | |
parse_add_expr(&src); | |
do_ne_expr(dest, &src); | |
} else if (match("<=")) { | |
parse_add_expr(&src); | |
do_le_expr(dest, &src); | |
} else if (match(">=")) { | |
parse_add_expr(&src); | |
do_ge_expr(dest, &src); | |
} else if (match("<")) { | |
parse_add_expr(&src); | |
do_lt_expr(dest, &src); | |
} else if (match(">")) { | |
parse_add_expr(&src); | |
do_gt_expr(dest, &src); | |
} else { | |
break; | |
} | |
} | |
} | |
// TODO: The way they call the do_functions right now is wrong because of short circuiting. | |
void parse_and_expr(Value *dest) { | |
parse_cmp_expr(dest); | |
while (match("&&")) { | |
Value src; | |
parse_cmp_expr(&src); | |
do_and_expr(dest, &src); | |
} | |
} | |
void parse_or_expr(Value *dest) { | |
parse_and_expr(dest); | |
while (match("||")) { | |
Value src; | |
parse_and_expr(&src); | |
do_or_expr(dest, &src); | |
} | |
} | |
void parse_cond_expr(Value *dest) { | |
parse_or_expr(dest); | |
while (match("?")) { | |
Value true_src; | |
parse_cond_expr(&true_src); | |
Value false_src; | |
expect(":"); | |
parse_cond_expr(&false_src); | |
do_cond_expr(dest, &true_src, &false_src); | |
} | |
} | |
void parse_expr(Value *dest) { | |
parse_cond_expr(dest); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment