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(); }
std::unique_ptr<expression> parser::parse_expression() { while (tokenizer_.current().type() == lex::token_type::separator) { tokenizer_.consume(); } auto e = parse_expression_1(parse_primary_expression(), 0); assert(e); while (tokenizer_.current().type() == lex::token_type::separator) { tokenizer_.consume(); } return e; }
static double parse_term() { double v1, v2; Token token; v1 = parse_primary_expression(); for(;;) { my_get_token(&token); if(token.kind != MUL_OPERATOR_TOKEN && token.kind != DIV_OPERATOR_TOKEN) { unget_token(&token); break; } v2 = parse_primary_expression(); if(token.kind == MUL_OPERATOR_TOKEN) { v1 *= v2; } else if(token.kind == DIV_OPERATOR_TOKEN) { v1 /= v2; } } return v1; }
void parse_pow (void) { Token t; parse_primary_expression(); for (;;) { t = get_token(); if (t.type != T_POW) { unget_token(); break; } parse_pow(); if (t.type == T_POW) { vm_add_opcode(OP_POW); } } }
// http://en.wikipedia.org/wiki/Operator-precedence_parser std::unique_ptr<expression> parser::parse_expression_1(std::unique_ptr<expression> lhs, int min_precedence) { for (;;) { // while lookahead is a binary operator whose precedence is >= min_precedence auto lookahead = tokenizer_.current(); auto lhs_opinfo = try_get_op_info(lookahead); if (!lhs_opinfo) { break; } if (lhs_opinfo->precedence < min_precedence) { // Precedence is not >= min_precedence break; } tokenizer_.consume(); std::unique_ptr<expression> rhs = parse_primary_expression(); for (;;) { // while lookahead is a binary operator whose precedence is greater // than op's, or a right-associative operator whose precedence is equal to op's lookahead = tokenizer_.current(); auto rhs_opinfo = try_get_op_info(lookahead); if (!rhs_opinfo) { break; } if (rhs_opinfo->precedence == lhs_opinfo->precedence) { if (rhs_opinfo->is_left_associative) { break; } // right-associative and equal precedence } else if (rhs_opinfo->precedence < lhs_opinfo->precedence) { break; } // the rhs operator has greater precedence (or equal but is right-associative) // recurse rhs = parse_expression_1(std::move(rhs), rhs_opinfo->precedence); } // lhs := the result of applying op with operands lhs and rhs lhs = std::unique_ptr<expression>{new binary_operation{std::move(lhs), std::move(rhs), lhs_opinfo->repr[0]}}; } return lhs; }
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); }