// multi-rest ::= '*' primary expr (multi-rest) // '/' primary expr (multi-rest) // '%' primary expr (multi-rest) // // assuming the first primary expr and operator has already been parsed // this parses the 'rest' of the expression Expr* parse_mult_rest(Parser& p, Token_stream& ts, Token const* tok, Expr* e1) { // look for the next operand if (Expr* e2 = parse_unary_expr(p, ts)) { // if there is another operator after the primary expr // and it is a multiplicative operator // then consume it. // the expr so far becomes the lhs operand // and we recurse until there are no more multiplicative operators. if (Token const* t = ts.next()) { if (is_mult_op(t->kind())) return parse_mult_rest(p, ts, ts.advance(), p.on_binary(tok, e1, e2)); // return once we're done eating up multiplicative operators else return p.on_binary(tok, e1, e2); } else return p.on_binary(tok, e1, e2); } error("Expected expression after multiplicative expr: "); print(e1); print(tok); print("\n"); return nullptr; }
static node_t *get_factortail(token_stack_t *stack, node_t *left_expr, GError **err) { const token_t *token; node_t *op, *expr; GError *tmp_err = NULL; token = token_peak(stack); /* First check if we really have a factortail here. If not, return the * factor. */ if (token == NULL) { g_free(token_pop(stack)); return left_expr; } else if (!(token->type == TOK_OPERATOR && is_mult_op(token->val.op))) return left_expr; op = g_malloc(sizeof(node_t)); op->left = left_expr; op->type = NODE_OPERATOR; switch (token->val.op) { case '*': op->val.op = OP_TIMES; break; case '/': op->val.op = OP_DIV; break; default: set_error(err, "Expected '*' or '/'", token); g_free(op); return left_expr; } g_free(token_pop(stack)); /* Then there should be a factor. */ op->right = get_factor(stack, &tmp_err); if (tmp_err) { g_propagate_error(err, tmp_err); return op; } /* and finally another factortail */ expr = get_factortail(stack, op, &tmp_err); if (tmp_err) g_propagate_error(err, tmp_err); return expr; }