Skip to content

Instantly share code, notes, and snippets.

@pervognsen pervognsen/expr.c

Last active May 23, 2020
Embed
What would you like to do?
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
You can’t perform that action at this time.