static AVEvalExpr * parse_expr(Parser *p) { AVEvalExpr * e; if(p->stack_index <= 0) //protect against stack overflows return NULL; p->stack_index--; e = parse_subexpr(p); while(*p->s == ';') { p->s++; e= new_eval_expr(e_last, 1, e, parse_subexpr(p)); }; p->stack_index++; return e; }
static GnmExprTop const * expr_new_from_formula (const psiconv_sheet_cell psi_cell, const psiconv_formula_list psi_formulas) { psiconv_formula formula = psiconv_get_formula (psi_formulas, psi_cell->ref_formula); if (NULL != formula) { GnmExpr const *expr = parse_subexpr (formula); if (NULL != expr) return gnm_expr_top_new (expr); } return NULL; }
static GnmExpr const * parse_subexpr(const psiconv_formula psi_formula) { int nrargs=0; /* -1 for variable */ int kind=-1; /* 0 for dat, 1 for operator, 2 for formula, 3 for special, -1 for unknown */ psiconv_formula psi_form1,psi_form2; GnmExpr const *expr1=NULL,*expr2=NULL; switch(psi_formula->type) { /* Translates values */ case psiconv_formula_dat_float: case psiconv_formula_dat_int: case psiconv_formula_dat_string: case psiconv_formula_dat_cellblock: case psiconv_formula_dat_vcellblock: nrargs = 0; kind = 0; break; /* Translates to binary operators */ case psiconv_formula_op_lt: case psiconv_formula_op_le: case psiconv_formula_op_gt: case psiconv_formula_op_ge: case psiconv_formula_op_ne: case psiconv_formula_op_eq: case psiconv_formula_op_add: case psiconv_formula_op_sub: case psiconv_formula_op_mul: case psiconv_formula_op_div: /* case psiconv_formula_op_pow: */ /* case psiconv_formula_op_and: */ /* case psiconv_formula_op_or: */ /* case psiconv_formula_op_con: */ nrargs = 2; kind = 1; break; /* Translates to unary operators */ case psiconv_formula_op_pos: case psiconv_formula_op_neg: case psiconv_formula_op_not: nrargs = 1; kind = 1; break; /* Specially handled */ case psiconv_formula_dat_cellref: case psiconv_formula_op_bra: nrargs = 1; kind = 3; break; /* Should never happen; caught by the default */ /* case psiconv_formula_mark_eof: */ /* case psiconv_formula_mark_opsep: */ /* case psiconv_formula_mark_opend: */ default: kind = -1; break; } if (kind == -1) { /* Unknown value */ return NULL; } else if (kind == 0) { /* Handling data */ GnmValue *v = NULL; switch(psi_formula->type) { case psiconv_formula_dat_float: v = value_new_float(psi_formula->data.dat_float); break; case psiconv_formula_dat_int: v = value_new_int(psi_formula->data.dat_int); break; case psiconv_formula_dat_string: v = psi_new_string(psi_formula->data.dat_string); break; case psiconv_formula_dat_cellblock: { GnmCellRef cr1, cr2; p_cellref_init (&cr1, psi_formula->data.dat_cellblock.first.row.offset, psi_formula->data.dat_cellblock.first.row.absolute, psi_formula->data.dat_cellblock.first.column.offset, psi_formula->data.dat_cellblock.first.column.absolute); p_cellref_init (&cr2, psi_formula->data.dat_cellblock.last.row.offset, psi_formula->data.dat_cellblock.last.row.absolute, psi_formula->data.dat_cellblock.last.column.offset, psi_formula->data.dat_cellblock.last.column.absolute); v = value_new_cellrange (&cr1, &cr2, 1, 1); break; } default: break; } if (!v) return NULL; return gnm_expr_new_constant(v); } else if (kind == 1) { /* Handling the operators */ if (nrargs >= 1) { if (!(psi_form1 = psiconv_list_get (psi_formula->data.fun_operands,0))) return NULL; if (!(expr1 = parse_subexpr(psi_form1))) return NULL; } if (nrargs >= 2) { if (!(psi_form2 = psiconv_list_get (psi_formula->data.fun_operands,1))) { gnm_expr_free(expr1); return NULL; } if (!(expr2 = parse_subexpr(psi_form2))) { gnm_expr_free(expr1); return NULL; } } switch(psi_formula->type) { case psiconv_formula_op_lt: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_LT,expr2); case psiconv_formula_op_le: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_LTE,expr2); case psiconv_formula_op_gt: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_GT,expr2); case psiconv_formula_op_ge: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_GTE,expr2); case psiconv_formula_op_ne: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_NOT_EQUAL,expr2); case psiconv_formula_op_eq: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_EQUAL,expr2); case psiconv_formula_op_add: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_ADD,expr2); case psiconv_formula_op_sub: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_SUB,expr2); case psiconv_formula_op_mul: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_MULT,expr2); case psiconv_formula_op_div: return gnm_expr_new_binary (expr1,GNM_EXPR_OP_DIV,expr2); case psiconv_formula_op_pos: return gnm_expr_new_unary (GNM_EXPR_OP_UNARY_PLUS,expr1); case psiconv_formula_op_neg: return gnm_expr_new_unary (GNM_EXPR_OP_UNARY_NEG,expr1); default: gnm_expr_free(expr1); gnm_expr_free(expr2); return NULL; } } else if (kind == 3) { switch(psi_formula->type) { case psiconv_formula_dat_cellref: { GnmCellRef cr; return gnm_expr_new_cellref (p_cellref_init (&cr, psi_formula->data.dat_cellref.row.offset, psi_formula->data.dat_cellref.row.absolute, psi_formula->data.dat_cellref.column.offset, psi_formula->data.dat_cellref.column.absolute)); } case psiconv_formula_op_bra: if (!(psi_form1 = psiconv_list_get (psi_formula->data.fun_operands,0))) return NULL; return parse_subexpr(psi_form1); default: break; } } return NULL; }