expressions::Expression* Parser::parseExpression()
{
    Expression* lhs = parsePrimaryExpression();

    if(!lhs)
        return NULL;

    Expression* expr =  parseBinaryOperationRHS(0, lhs);

    if(lhs != expr)
        lhs->drop();

    return expr;
}
expressions::ArrayIndexExpression* Parser::parseArrayIndexExpression(expressions::Expression* array)
{
    array->grab();
    readNextToken(true); // Eat the '['.

    Expression* index = parseExpression(); // Parse the index.

    expect(TokenRightSquareBracket); // Expect a ']'.

    // Create the expression.
    ArrayIndexExpression* expr = new ArrayIndexExpression(array, index);

    // Drop temps.
    array->drop(); // We made a copy, drop our copy.
    index->drop();

    return expr;
}
expressions::Expression* Parser::parsePrimaryExpression()
{
    if(isEndOfStream())
        return NULL;

    if(m_currentToken == TokenMinusSign)
    {
        readNextToken(true); // Eat the '-'.

        Expression* expr = parseExpression();

        NegativeExpression* result = new NegativeExpression(expr);

        expr->drop();

        return result;
    }
    if(m_currentToken.getType() == Token::TokenType::NumericLiteral) // Check for a numeric literal.
    {
        return parseNumericLiteralExpression();
    }
    else if(m_currentToken.getType() == Token::TokenType::StringLiteral) // Check for a string literal.
    {
        return parseStringLiteralExpression();
    }
    else if(m_currentToken.getType() == Token::TokenType::Word) // Check for a word.
    {
        return parseWordExpression();
    }
    else if(Token::Compare(m_strCmp, m_currentToken, TokenLeftParenthesis)) // Check for a parentheses expression.
    {
        return parseParenthesesExpression();
    }
    else // Unexpected token.
    {
        onError("unexpected token");
        return nullptr;
    }

}
expressions::Expression* Parser::parseWordExpression()
{
    std::string first = m_currentToken.getValue();

    readNextToken(false); // Eat the identifier.

    if(m_currentToken == TokenPeriod)
    {
        readNextToken(true); // Eat the '.'.

        // Parse the name.
        while(1)
        {
            if((m_currentToken.getType() == Token::TokenType::Word))
                first += "." + m_currentToken.getValue();
            else
            {
                break;
            }

            readNextToken(true); // Eat the last part of the name.

            if(m_currentToken == TokenPeriod)
            {
                readNextToken(true);
                continue;
            }
            else if((m_currentToken == TokenLeftParenthesis))
                break;
        }
    }

    // It has a '(', it is a function call expression.
    if(m_currentToken == TokenLeftParenthesis)
    {
        std::vector<Expression*> args;

        parseFunctionCall(args); // Parse the argument list.

        // Create the function call expression.
        Expression* expr = new FunctionCallExpression(first, args);

        // Check if we're indexing an item from the return value.
        if(m_currentToken == TokenLeftSquareBracket)
        {
            ArrayIndexExpression* indexExpr = parseArrayIndexExpression(expr);

            expr->drop(); // Drop the old expression.

            expr = indexExpr; // The expression is now the new index expression.
        }

        // Drop the argument list.
        for(unsigned int i=0; i<args.size(); i++)
            args[i]->drop();

        return expr;
    }

    Expression* expr = new VariableExpression(first);

    while(m_currentToken == TokenLeftSquareBracket)
    {
        Expression* array = expr;

        expr = parseArrayIndexExpression(array);

        array->drop();
    }

    return expr;
}
expressions::Expression* Parser::parseBinaryOperationRHS(int expressionPrecedence, expressions::Expression* lhs)
{
    Expression* origLHS = lhs;

    while(1)
    {
        int tokPrec = getOperatorPrecedence(m_currentToken);

        if(tokPrec < expressionPrecedence)
            return lhs;

        Token op = m_currentToken;
        readNextToken(true);

        Expression* rhs = parsePrimaryExpression();

        if(!rhs) return nullptr;

        int nextPrec = getOperatorPrecedence(m_currentToken);

        if(tokPrec < nextPrec)
        {
            Expression* oldRHS = rhs;

            rhs = parseBinaryOperationRHS(tokPrec+1, rhs);

            oldRHS->drop();

            if(!rhs) return nullptr;
        }

        Expression* oldLHS = lhs;

        // Check the operator.
        if(op == TokenPlusSign)
        {
            lhs = new AdditionExpression(lhs, rhs); // Operator is addition.
        }
        else if(op == TokenMinusSign)
        {
            lhs = new SubtractionExpression(lhs, rhs); // Operator is subtraction.
        }
        else if(op == TokenMulSign)
        {
            lhs = new MultipicationExpression(lhs, rhs); // Operator is multipication.
        }
        else if(op == TokenDivSign)
        {
            lhs = new DivisionExpression(lhs, rhs); // Operator is division.
        }
        else if(op == TokenEquals)
        {
            lhs = new EqualExpression(lhs, rhs);    // Operator is equal comparison.
        }
        else if(op == TokenLessThan)
        {
            lhs = new LessThanExpression(lhs, rhs);  // Operator is less than.
        }
        else if(op == TokenGreaterThan)
        {
            lhs = new GreaterThanExpression(lhs, rhs); // Operator is greater than.
        }
        else if(op == TokenLessThanOrEqualTo)
        {
            lhs = new LessThanOrEqualToExpression(lhs, rhs); // Operator is less than or equal to.
        }
        else if(op == TokenGreaterThenOrEqualTo)
        {
            lhs = new GreaterThanOrEqualToExpression(lhs, rhs); // Operator is greater than or equal to.
        }
        else if(op == TokenNotEquals)
        {
            lhs = new NotEqualExpression(lhs, rhs);   // Operator is not equal.
        }
        else if(Token::Compare(m_strCmp, op, TokenAnd))
        {
            lhs = new AndExpression(lhs, rhs);
        }
        else if(Token::Compare(m_strCmp, op, TokenOr))
        {
            lhs = new OrExpression(lhs, rhs);
        }
        else
        {
            onError("undefined operator '" + op.getValue() + "'");
            return nullptr;
        }

        if(oldLHS !=origLHS)
            oldLHS->drop(); // TODO:

        rhs->drop();

    }
}
statements::Statement* Parser::parseIdentifierStatement()
{
    std::string first = m_currentToken.getValue();

    // Attempt to read a token.
    if(readNextToken(false))
    {
        if(m_currentToken == TokenColon) // The statement is a label.
        {
            readNextToken(true); // Eat the ':'.

            expectEOL(); // Expect a new line.

            return new LabelStatement(first);
        }


        if(m_currentToken == TokenPeriod)
        {
            readNextToken(true); // Eat the '.'.

            // Parse the name.
            while(1)
            {
                if((m_currentToken.getType() == Token::TokenType::Word))
                    first += "." + m_currentToken.getValue();
                else
                {
                    onError("expected identifier, '.', '=' or '('");
                    return nullptr;
                }

                readNextToken(true); // Eat the last part of the name.

                if(m_currentToken == TokenPeriod)
                {
                    readNextToken(true);
                    continue;
                }
                else if((m_currentToken == TokenLeftParenthesis) || (m_currentToken == TokenEquals))
                    break;
            }
        }

        // The statement is a function call statement.
        if(m_currentToken == TokenLeftParenthesis)
        {
            std::vector<Expression*> args; // The arguments to the function.

            parseFunctionCall(args); // Parse the function call.

            expectEOL(); // Expect an EOL.

            FunctionCallStatement* statement = new FunctionCallStatement(first, args);

            // Drop the argument list.
            for(unsigned int i=0; i<args.size(); i++)
                args[i]->drop();

            return statement;
        }

        Expression* lhs = new VariableExpression(first);

        while(m_currentToken == TokenLeftSquareBracket)
        {
            Expression* array = lhs;

            lhs = parseArrayIndexExpression(array);

            array->drop();
        }

        if(m_currentToken == TokenEquals) // The statement is in the form 'x = y'.
        {
            readNextToken(true); // Eat the '='.

            Expression* rhs = parseExpression();

            expectEOL();

            AssignmentStatement* statement = new AssignmentStatement(lhs, rhs);

            rhs->drop();

            return statement;
        }
    }


    onError("expected '(', '=' or ':'");

    return nullptr;
}