/* add_expr * : mul_expr * | add_expr ADD mul_expr * | add_expr SUB mul_expr */ static void add_expr(ApexParser *parser) { mul_expr(parser); for (;;) { ApexAstNode *left, *right; ApexAstOpr opr; if (accept(parser, '+')) { opr = '+'; } else if (accept(parser, '-')) { opr = '-'; } else { break; } left = apex_ast_pop(parser->ast); mul_expr(parser); right = apex_ast_pop(parser->ast); apex_ast_opr2(parser->ast, opr, left, right); } }
static void add_expr(void) { switch(token.type) { case TOKEN_INTEGER: case TOKEN_LPARENTH: mul_expr(); if (err == SYN_ERR) { goto out; } rest_add_expr(); goto out; default: err = SYN_ERR; goto out; } out: return ; }
static void rest_add_expr(void) { number op1, op2; unsigned int tmp, rv, i; while (token.type == TOKEN_PLUS || token.type == TOKEN_MINUS) { tmp = token.type; get_next_token(); mul_expr(); if (err == SYN_ERR) { goto out; } rv = pop_item(&sp, &op2); if (rv != OK) { err = MEM_ERR; goto out; } rv = pop_item(&sp, &op1); if (rv != OK) { err = MEM_ERR; goto out; } if (op1.frac == op2.frac) goto main_part; if (op1.frac > op2.frac) { for (i = 0; i < (op1.frac - op2.frac); i++) rv = mpl_mul_dig(&op2.value, &op2.value, 10); if (rv != MPL_OK) { err = MEM_ERR; goto out; } op2.frac = op1.frac; } else { for (i = 0; i < (op2.frac - op1.frac); i++) rv = mpl_mul_dig(&op1.value, &op1.value, 10); if (rv != MPL_OK) { err = MEM_ERR; goto out; } op1.frac = op2.frac; } main_part: if (tmp == TOKEN_PLUS) { rv = mpl_add(&op1.value, &op1.value, &op2.value); if (rv != MPL_OK) { err = MEM_ERR; goto out; } } else if (tmp == TOKEN_MINUS) { rv = mpl_sub(&op1.value, &op1.value, &op2.value); if (rv != MPL_OK) { err = MEM_ERR; goto out; } } rv = push_item(&sp, &op1); if (rv != OK) { err = MEM_ERR; goto out; } mpl_clear(&op2.value); } if (token.type != TOKEN_EOL && token.type != TOKEN_RPARENTH) { err = SYN_ERR; goto out; } out: return ; }
void eval_expr(expr *in, expr *out, symtab *table) { switch (in->type) { case NOTHING: break; case INTEGER: case REAL: case STRING: out->type = in->type; out->val = in->val; return; case INT_VAR: { int n; if (lookup_int(in->val.string, table, &n)) { out->type = INTEGER; out->val.integer = n; return; } else { fprintf(stderr, "undefined integer variable '%s'\n", in->val.string); exit(1); } } break; case REAL_VAR: { double d; if (lookup_real(in->val.string, table, &d)) { out->type = REAL; out->val.real = d; return; } else { fprintf(stderr, "undefined real variable '%s'\n", in->val.string); exit(1); } } break; case STR_VAR: { char *s = (char *)malloc(MAX_LINE); if (lookup_str(in->val.string, table, &s)) { out->type = STRING; out->val.string = s; return; } else { fprintf(stderr, "undefined string variable '%s'\n", in->val.string); exit(1); } } break; } switch (in->op) { case NOTHING: fprintf(stderr, "No operation for non-constant expression\n"); exit(1); case ADD: add_expr(in, out, table); break; case SUB: sub_expr(in, out, table); break; case EXPT: pow_expr(in, out, table); break; case MUL: mul_expr(in, out, table); break; case DIV: div_expr(in, out, table); break; case LT: eval_expr(in->arg1, out->arg1, table); eval_expr(in->arg2, out->arg2, table); out->type = INTEGER; out->val.integer = compare(out->arg1, out->arg2, LT); break; case LE: eval_expr(in->arg1, out->arg1, table); eval_expr(in->arg2, out->arg2, table); out->type = INTEGER; out->val.integer = compare(out->arg1, out->arg2, LE); break; case EQ: eval_expr(in->arg1, out->arg1, table); eval_expr(in->arg2, out->arg2, table); out->type = INTEGER; out->val.integer = compare(out->arg1, out->arg2, EQ); break; case GE: eval_expr(in->arg1, out->arg1, table); eval_expr(in->arg2, out->arg2, table); out->type = INTEGER; out->val.integer = compare(out->arg1, out->arg2, GE); break; case GT: eval_expr(in->arg1, out->arg1, table); eval_expr(in->arg2, out->arg2, table); out->type = INTEGER; out->val.integer = compare(out->arg1, out->arg2, GT); break; case NE: eval_expr(in->arg1, out->arg1, table); eval_expr(in->arg2, out->arg2, table); out->type = INTEGER; out->val.integer = compare(out->arg1, out->arg2, NE); break; /* Numerical functions */ case RAND: { expr arg; eval_expr(in->arg1, &arg, table); out->type = INTEGER; out->val.integer = rand() % arg.val.integer; } break; case SQRT: { expr arg; eval_expr(in->arg1, &arg, table); out->type = REAL; out->val.real = sqrt(arg.type == REAL ? arg.val.real : (double)arg.val.integer); } break; /* Casting */ case CEIL: { expr arg; eval_expr(in->arg1, &arg, table); out->type = INTEGER; out->val.integer = (int)ceil(arg.val.real); } break; case FLOOR: { expr arg; eval_expr(in->arg1, &arg, table); out->type = INTEGER; out->val.integer = (int)floor(arg.val.real); } break; case REAL_CAST: { expr arg; eval_expr(in->arg1, &arg, table); out->type = REAL; out->val.real = (double)arg.val.integer; } break; case ROUND: { expr arg; eval_expr(in->arg1, &arg, table); out->type = INTEGER; out->val.integer = (int)round(arg.val.real); } break; default: fprintf(stderr, "unrecognised operation\n"); exit(1); } }