Skip to content

Instantly share code, notes, and snippets.

@prathyvsh
Forked from pervognsen/expr.c
Created April 18, 2020 14:19
Show Gist options
  • Select an option

  • Save prathyvsh/d5b0d13eb896d1261994a4a8a7a56450 to your computer and use it in GitHub Desktop.

Select an option

Save prathyvsh/d5b0d13eb896d1261994a4a8a7a56450 to your computer and use it in GitHub Desktop.

Revisions

  1. @pervognsen pervognsen revised this gist Apr 18, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion expr.c
    Original file line number Diff line number Diff line change
    @@ -190,7 +190,7 @@ void parse_cond_expr(Value *dest) {
    Value false_src;
    expect(":");
    parse_cond_expr(&false_src);
    do_cond_expr(dest, true_src, false_src);
    do_cond_expr(dest, &true_src, &false_src);
    }
    }

  2. @pervognsen pervognsen revised this gist Apr 18, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion expr.c
    Original file line number Diff line number Diff line change
    @@ -56,7 +56,7 @@ void parse_base_expr(Value *dest) {
    } else if (match("++")) {
    do_postinc_expr(dest);
    } else if (match("--")) {
    do_preinc_expr(dest);
    do_postinc_expr(dest);
    } else {
    break;
    }
  3. @pervognsen pervognsen created this gist Apr 18, 2020.
    199 changes: 199 additions & 0 deletions expr.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,199 @@
    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_preinc_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);
    }