Example #1
0
    PExprAST
    Parser::parse_binop_rhs(int precedence_min, PExprAST lhs)
    {
        // We will try to read operators and replace the
        // current lhs by a bigger one, until there is
        // no more tokens.
        while (true)
        {
            int token_precedence = get_token_precedence();

            // If it's not a binop or it's a binop with
            // lower precedence.
            if (token_precedence < precedence_min)
                return lhs;

            //We know it's a binop, so we read [op, prim]
            Token binop = current_tok;
            get_next_token(); // eat the binop
            PExprAST rhs = parse_primary();

            // If the next token have a stronger precedence,
            // we should compute it as belonging to rhs.
            int next_precedence = get_token_precedence();
            if (next_precedence > token_precedence)
                rhs = PExprAST(parse_binop_rhs(token_precedence + 1, rhs));

            //Otherwise, we replace the lhs by 'lhs, op, prim'
            lhs = PExprAST(new BinaryExprAST(binop, lhs, rhs));
        }
    }
/// binoprhs: ([+*/^-] primary)*
ex parser::parse_binop_rhs(int expr_prec, ex& lhs)
{
	exvector args;
	args.push_back(lhs);
	int binop = -1, orig_binop = -1;
	bool need_sign_flip = false;
	while (1) {
		// check if this is a binop
		if (!is_binop(token)) {
			if (args.size() > 1)
				return make_binop_expr(orig_binop, args);
			else
				return lhs;
		}
		
		// Okay, we know this is a binop.
		if (args.size() == 1)
			orig_binop = token;

		binop = token;

		// If this is a binop that binds at least as tightly as
		// the current binop, consume it, otherwise we are done.
		int tok_prec = get_tok_prec(token);
		if (tok_prec < expr_prec) {
			if (args.size() > 1)
				return make_binop_expr(orig_binop, args);
			else 
				return lhs;
		}

		get_next_tok();  // eat binop

		// Parse the primary expression after the binary operator.
		ex rhs = parse_primary();

		// If binop binds less tightly with rhs than the operator after
		// rhs, let the pending operator take rhs as its lhs.
		int next_prec = get_tok_prec(token);
		if (tok_prec < next_prec)
			rhs = parse_binop_rhs(tok_prec + 1, rhs);

		// previous operator was '+', and current one is '-'
		// (or vice a versa).
		if (need_sign_flip)
			rhs = - rhs;

		args.push_back(rhs);

		// Minimize the number of eval() and ctor calls. This is
		// crucial for a reasonable performance. If the next operator
		// is compatible with the pending one (or the same) don't create
		// the expression and continue collecting operands instead.
		if (binop == token)
			continue;
		else if (binop == '+' && token == '-') {
			need_sign_flip = token != orig_binop;
			continue;
		} else if (binop == '-' && token == '+') {
			need_sign_flip = token != orig_binop;
			continue;
		} else { 
			if (args.size() <= 1)
				bug("binop has " << args.size() << " arguments, expected >= 2");
			lhs = make_binop_expr(orig_binop, args);
			args.clear();
			args.push_back(lhs);
		}
	}
}
Example #3
0
 PExprAST
 Parser::parse_expr()
 {
     PExprAST lhs = parse_primary();
     return parse_binop_rhs(0, lhs);
 }