static void parse_unary_expression() { /* add code for unary operators */ if (equals(c_token, "!")) { c_token++; parse_unary_expression(); (void) add_action(LNOT); } else if (equals(c_token, "~")) { c_token++; parse_unary_expression(); (void) add_action(BNOT); } else if (equals(c_token, "-")) { struct at_entry *previous; c_token++; parse_unary_expression(); /* Collapse two operations PUSHC <pos-const> + UMINUS * into a single operation PUSHC <neg-const> */ previous = &(at->actions[at->a_count-1]); if (previous->index == PUSHC && previous->arg.v_arg.type == INTGR) { previous->arg.v_arg.v.int_val = -previous->arg.v_arg.v.int_val; } else if (previous->index == PUSHC && previous->arg.v_arg.type == CMPLX) { previous->arg.v_arg.v.cmplx_val.real = -previous->arg.v_arg.v.cmplx_val.real; previous->arg.v_arg.v.cmplx_val.imag = -previous->arg.v_arg.v.cmplx_val.imag; } else (void) add_action(UMINUS); } else if (equals(c_token, "+")) { /* unary + is no-op */ c_token++; parse_unary_expression(); } else parse_primary_expression(); }
static void parse_multiplicative_expression() { /* add action code for * / and % operators */ while (TRUE) { if (equals(c_token, "*")) { c_token++; parse_unary_expression(); (void) add_action(MULT); } else if (equals(c_token, "/")) { c_token++; parse_unary_expression(); (void) add_action(DIV); } else if (equals(c_token, "%")) { c_token++; parse_unary_expression(); (void) add_action(MOD); } else break; } }
static float parse_power_expression(parser_state_t *self) { float left, right; if(!self->token) return NAN; left = parse_unary_expression(self); while(self->token && self->token->type == T_OPERATOR) { if(self->token->data.operator!= O_POWER) return left; free(self->token); self->token = get_token(self); right = parse_unary_expression(self); left = powf(left, right); } return left; }
static void parse_unary_expression() { /* add code for unary operators */ if (equals(c_token, "!")) { c_token++; parse_unary_expression(); (void) add_action(LNOT); } else if (equals(c_token, "~")) { c_token++; parse_unary_expression(); (void) add_action(BNOT); } else if (equals(c_token, "-")) { c_token++; parse_unary_expression(); (void) add_action(UMINUS); } else if (equals(c_token, "+")) { /* unary + is no-op */ c_token++; parse_unary_expression(); } else parse_primary_expression(); }
static float parse_unary_expression(parser_state_t *self) { if(!self->token) return NAN; if(self->token->type == T_OPERATOR) { if(self->token->data.operator== O_MINUS) { free(self->token); self->token = get_token(self); return -1.0 * parse_unary_expression(self); } if(self->token->data.operator== O_PLUS) { free(self->token); self->token = get_token(self); return parse_unary_expression(self); } } return parse_primary_expression(self); }
/* add action table entries for primary expressions, i.e. either a * parenthesized expression, a variable name, a numeric constant, a * function evaluation, a power operator or postfix '!' (factorial) * expression */ static void parse_primary_expression() { if (equals(c_token, "(")) { c_token++; parse_expression(); /* Expressions may be separated by a comma */ while (equals(c_token,",")) { c_token++; (void) add_action(POP); parse_expression(); } if (!equals(c_token, ")")) int_error(c_token, "')' expected"); c_token++; } else if (equals(c_token, "$")) { struct value a; c_token++; if (equals(c_token,"N")) { /* $N == pseudocolumn -3 means "last column" */ c_token++; Ginteger(&a, -3); at_highest_column_used = -3; } else if (!isanumber(c_token)) { int_error(c_token, "Column number expected"); } else { convert(&a, c_token++); if (a.type != INTGR || a.v.int_val < 0) int_error(c_token, "Positive integer expected"); if (at_highest_column_used < a.v.int_val) at_highest_column_used = a.v.int_val; } add_action(DOLLARS)->v_arg = a; } else if (isanumber(c_token)) { /* work around HP 9000S/300 HP-UX 9.10 cc limitation ... */ /* HBB 20010724: use this code for all platforms, then */ union argument *foo = add_action(PUSHC); convert(&(foo->v_arg), c_token); c_token++; } else if (isletter(c_token)) { /* Found an identifier --- check whether its a function or a * variable by looking for the parentheses of a function * argument list */ if (equals(c_token + 1, "(")) { enum operators whichfunc = is_builtin_function(c_token); struct value num_params; num_params.type = INTGR; #if (1) /* DEPRECATED */ if (whichfunc && (strcmp(ft[whichfunc].f_name,"defined")==0)) { /* Deprecated syntax: if (defined(foo)) ... */ /* New syntax: if (exists("foo")) ... */ struct udvt_entry *udv = add_udv(c_token+2); union argument *foo = add_action(PUSHC); foo->v_arg.type = INTGR; foo->v_arg.v.int_val = udv->udv_undef ? 0 : 1; c_token += 4; /* skip past "defined ( <foo> ) " */ return; } #endif if (whichfunc) { c_token += 2; /* skip fnc name and '(' */ parse_expression(); /* parse fnc argument */ num_params.v.int_val = 1; while (equals(c_token, ",")) { c_token++; num_params.v.int_val++; parse_expression(); } if (!equals(c_token, ")")) int_error(c_token, "')' expected"); c_token++; /* So far sprintf is the only built-in function */ /* with a variable number of arguments. */ if (!strcmp(ft[whichfunc].f_name,"sprintf")) add_action(PUSHC)->v_arg = num_params; /* The column() function has side effects requiring special handling */ if (!strcmp(ft[whichfunc].f_name,"column")) { set_up_columnheader_parsing( &(at->actions[at->a_count-1]) ); } (void) add_action(whichfunc); } else { /* it's a call to a user-defined function */ enum operators call_type = (int) CALL; int tok = c_token; c_token += 2; /* skip func name and '(' */ parse_expression(); if (equals(c_token, ",")) { /* more than 1 argument? */ num_params.v.int_val = 1; while (equals(c_token, ",")) { num_params.v.int_val += 1; c_token += 1; parse_expression(); } add_action(PUSHC)->v_arg = num_params; call_type = (int) CALLN; } if (!equals(c_token, ")")) int_error(c_token, "')' expected"); c_token++; add_action(call_type)->udf_arg = add_udf(tok); } } else if (equals(c_token, "sum") && equals(c_token+1, "[")) { parse_sum_expression(); /* dummy_func==NULL is a flag to say no dummy variables active */ } else if (dummy_func) { if (equals(c_token, c_dummy_var[0])) { c_token++; add_action(PUSHD1)->udf_arg = dummy_func; fit_dummy_var[0]++; } else if (equals(c_token, c_dummy_var[1])) { c_token++; add_action(PUSHD2)->udf_arg = dummy_func; fit_dummy_var[1]++; } else { int i, param = 0; for (i = 2; i < MAX_NUM_VAR; i++) { if (equals(c_token, c_dummy_var[i])) { struct value num_params; num_params.type = INTGR; num_params.v.int_val = i; param = 1; c_token++; add_action(PUSHC)->v_arg = num_params; add_action(PUSHD)->udf_arg = dummy_func; fit_dummy_var[i]++; break; } } if (!param) { /* defined variable */ add_action(PUSH)->udv_arg = add_udv(c_token); c_token++; } } /* its a variable, with no dummies active - div */ } else { add_action(PUSH)->udv_arg = add_udv(c_token); c_token++; } } /* end if letter */ /* Maybe it's a string constant */ else if (isstring(c_token)) { union argument *foo = add_action(PUSHC); foo->v_arg.type = STRING; foo->v_arg.v.string_val = NULL; /* this dynamically allocated string will be freed by free_at() */ m_quote_capture(&(foo->v_arg.v.string_val), c_token, c_token); c_token++; } else int_error(c_token, "invalid expression "); /* add action code for ! (factorial) operator */ while (equals(c_token, "!")) { c_token++; (void) add_action(FACTORIAL); } /* add action code for ** operator */ if (equals(c_token, "**")) { c_token++; parse_unary_expression(); (void) add_action(POWER); } /* Parse and add actions for range specifier applying to previous entity. * Currently only used to generate substrings, but could also be used to * extract vector slices. */ if (equals(c_token, "[") && !isanumber(c_token-1)) { /* handle '*' or empty start of range */ if (equals(++c_token,"*") || equals(c_token,":")) { union argument *empty = add_action(PUSHC); empty->v_arg.type = INTGR; empty->v_arg.v.int_val = 1; if (equals(c_token,"*")) c_token++; } else parse_expression(); if (!equals(c_token, ":")) int_error(c_token, "':' expected"); /* handle '*' or empty end of range */ if (equals(++c_token,"*") || equals(c_token,"]")) { union argument *empty = add_action(PUSHC); empty->v_arg.type = INTGR; empty->v_arg.v.int_val = 65535; /* should be INT_MAX */ if (equals(c_token,"*")) c_token++; } else parse_expression(); if (!equals(c_token, "]")) int_error(c_token, "']' expected"); c_token++; (void) add_action(RANGE); } }
static void accept_multiplicative_expression() { parse_unary_expression(); /* - things */ parse_multiplicative_expression(); /* * / % */ }