//
// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "DirectiveParser.h"

#include <cassert>
#include <cstdlib>
#include <sstream>

#include "DiagnosticsBase.h"
#include "DirectiveHandlerBase.h"
#include "ExpressionParser.h"
#include "MacroExpander.h"
#include "Token.h"
#include "Tokenizer.h"

namespace {
enum DirectiveType
{
    DIRECTIVE_NONE,
    DIRECTIVE_DEFINE,
    DIRECTIVE_UNDEF,
    DIRECTIVE_IF,
    DIRECTIVE_IFDEF,
    DIRECTIVE_IFNDEF,
    DIRECTIVE_ELSE,
    DIRECTIVE_ELIF,
    DIRECTIVE_ENDIF,
    DIRECTIVE_ERROR,
    DIRECTIVE_PRAGMA,
    DIRECTIVE_EXTENSION,
    DIRECTIVE_VERSION,
    DIRECTIVE_LINE
};

DirectiveType getDirective(const pp::Token *token)
{
    const char kDirectiveDefine[] = "define";
    const char kDirectiveUndef[] = "undef";
    const char kDirectiveIf[] = "if";
    const char kDirectiveIfdef[] = "ifdef";
    const char kDirectiveIfndef[] = "ifndef";
    const char kDirectiveElse[] = "else";
    const char kDirectiveElif[] = "elif";
    const char kDirectiveEndif[] = "endif";
    const char kDirectiveError[] = "error";
    const char kDirectivePragma[] = "pragma";
    const char kDirectiveExtension[] = "extension";
    const char kDirectiveVersion[] = "version";
    const char kDirectiveLine[] = "line";

    if (token->type != pp::Token::IDENTIFIER)
        return DIRECTIVE_NONE;

    if (token->text == kDirectiveDefine)
        return DIRECTIVE_DEFINE;
    if (token->text == kDirectiveUndef)
        return DIRECTIVE_UNDEF;
    if (token->text == kDirectiveIf)
        return DIRECTIVE_IF;
    if (token->text == kDirectiveIfdef)
        return DIRECTIVE_IFDEF;
    if (token->text == kDirectiveIfndef)
        return DIRECTIVE_IFNDEF;
    if (token->text == kDirectiveElse)
        return DIRECTIVE_ELSE;
    if (token->text == kDirectiveElif)
        return DIRECTIVE_ELIF;
    if (token->text == kDirectiveEndif)
        return DIRECTIVE_ENDIF;
    if (token->text == kDirectiveError)
        return DIRECTIVE_ERROR;
    if (token->text == kDirectivePragma)
        return DIRECTIVE_PRAGMA;
    if (token->text == kDirectiveExtension)
        return DIRECTIVE_EXTENSION;
    if (token->text == kDirectiveVersion)
        return DIRECTIVE_VERSION;
    if (token->text == kDirectiveLine)
        return DIRECTIVE_LINE;

    return DIRECTIVE_NONE;
}

bool isConditionalDirective(DirectiveType directive)
{
    switch (directive)
    {
      case DIRECTIVE_IF:
      case DIRECTIVE_IFDEF:
      case DIRECTIVE_IFNDEF:
      case DIRECTIVE_ELSE:
      case DIRECTIVE_ELIF:
      case DIRECTIVE_ENDIF:
        return true;
      default:
        return false;
    }
}

// Returns true if the token represents End Of Directive.
bool isEOD(const pp::Token *token)
{
    return (token->type == '\n') || (token->type == pp::Token::LAST);
}

void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
{
    while(!isEOD(token))
    {
        lexer->lex(token);
    }
}

bool isMacroNameReserved(const std::string &name)
{
    // Names prefixed with "GL_" are reserved.
    if (name.substr(0, 3) == "GL_")
        return true;

    // Names containing two consecutive underscores are reserved.
    if (name.find("__") != std::string::npos)
        return true;

    return false;
}

bool isMacroPredefined(const std::string &name,
                       const pp::MacroSet &macroSet)
{
    pp::MacroSet::const_iterator iter = macroSet.find(name);
    return iter != macroSet.end() ? iter->second.predefined : false;
}

}  // namespace anonymous

namespace pp
{

class DefinedParser : public Lexer
{
  public:
    DefinedParser(Lexer *lexer,
                  const MacroSet *macroSet,
                  Diagnostics *diagnostics)
        : mLexer(lexer),
          mMacroSet(macroSet),
          mDiagnostics(diagnostics)
    {
    }

  protected:
    virtual void lex(Token *token)
    {
        const char kDefined[] = "defined";

        mLexer->lex(token);
        if (token->type != Token::IDENTIFIER)
            return;
        if (token->text != kDefined)
            return;

        bool paren = false;
        mLexer->lex(token);
        if (token->type == '(')
        {
            paren = true;
            mLexer->lex(token);
        }

        if (token->type != Token::IDENTIFIER)
        {
            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                 token->location, token->text);
            skipUntilEOD(mLexer, token);
            return;
        }
        MacroSet::const_iterator iter = mMacroSet->find(token->text);
        std::string expression = iter != mMacroSet->end() ? "1" : "0";

        if (paren)
        {
            mLexer->lex(token);
            if (token->type != ')')
            {
                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                     token->location, token->text);
                skipUntilEOD(mLexer, token);
                return;
            }
        }

        // We have a valid defined operator.
        // Convert the current token into a CONST_INT token.
        token->type = Token::CONST_INT;
        token->text = expression;
    }

  private:
    Lexer *mLexer;
    const MacroSet *mMacroSet;
    Diagnostics *mDiagnostics;
};

DirectiveParser::DirectiveParser(Tokenizer *tokenizer,
                                 MacroSet *macroSet,
                                 Diagnostics *diagnostics,
                                 DirectiveHandler *directiveHandler)
    : mPastFirstStatement(false),
      mTokenizer(tokenizer),
      mMacroSet(macroSet),
      mDiagnostics(diagnostics),
      mDirectiveHandler(directiveHandler)
{
}

void DirectiveParser::lex(Token *token)
{
    do
    {
        mTokenizer->lex(token);

        if (token->type == Token::PP_HASH)
        {
            parseDirective(token);
            mPastFirstStatement = true;
        }

        if (token->type == Token::LAST)
        {
            if (!mConditionalStack.empty())
            {
                const ConditionalBlock &block = mConditionalStack.back();
                mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED,
                                     block.location, block.type);
            }
            break;
        }

    }
    while (skipping() || (token->type == '\n'));

    mPastFirstStatement = true;
}

void DirectiveParser::parseDirective(Token *token)
{
    assert(token->type == Token::PP_HASH);

    mTokenizer->lex(token);
    if (isEOD(token))
    {
        // Empty Directive.
        return;
    }

    DirectiveType directive = getDirective(token);

    // While in an excluded conditional block/group,
    // we only parse conditional directives.
    if (skipping() && !isConditionalDirective(directive))
    {
        skipUntilEOD(mTokenizer, token);
        return;
    }

    switch(directive)
    {
      case DIRECTIVE_NONE:
        mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        break;
      case DIRECTIVE_DEFINE:
        parseDefine(token);
        break;
      case DIRECTIVE_UNDEF:
        parseUndef(token);
        break;
      case DIRECTIVE_IF:
        parseIf(token);
        break;
      case DIRECTIVE_IFDEF:
        parseIfdef(token);
        break;
      case DIRECTIVE_IFNDEF:
        parseIfndef(token);
        break;
      case DIRECTIVE_ELSE:
        parseElse(token);
        break;
      case DIRECTIVE_ELIF:
        parseElif(token);
        break;
      case DIRECTIVE_ENDIF:
        parseEndif(token);
        break;
      case DIRECTIVE_ERROR:
        parseError(token);
        break;
      case DIRECTIVE_PRAGMA:
        parsePragma(token);
        break;
      case DIRECTIVE_EXTENSION:
        parseExtension(token);
        break;
      case DIRECTIVE_VERSION:
        parseVersion(token);
        break;
      case DIRECTIVE_LINE:
        parseLine(token);
        break;
      default:
        assert(false);
        break;
    }

    skipUntilEOD(mTokenizer, token);
    if (token->type == Token::LAST)
    {
        mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE,
                             token->location, token->text);
    }
}

void DirectiveParser::parseDefine(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_DEFINE);

    mTokenizer->lex(token);
    if (token->type != Token::IDENTIFIER)
    {
        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                             token->location, token->text);
        return;
    }
    if (isMacroPredefined(token->text, *mMacroSet))
    {
        mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
                             token->location, token->text);
        return;
    }
    if (isMacroNameReserved(token->text))
    {
        mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED,
                             token->location, token->text);
        return;
    }

    Macro macro;
    macro.type = Macro::kTypeObj;
    macro.name = token->text;

    mTokenizer->lex(token);
    if (token->type == '(' && !token->hasLeadingSpace())
    {
        // Function-like macro. Collect arguments.
        macro.type = Macro::kTypeFunc;
        do
        {
            mTokenizer->lex(token);
            if (token->type != Token::IDENTIFIER)
                break;
            macro.parameters.push_back(token->text);

            mTokenizer->lex(token);  // Get ','.
        }
        while (token->type == ',');

        if (token->type != ')')
        {
            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                 token->location,
                                 token->text);
            return;
        }
        mTokenizer->lex(token);  // Get ')'.
    }

    while ((token->type != '\n') && (token->type != Token::LAST))
    {
        // Reset the token location because it is unnecessary in replacement
        // list. Resetting it also allows us to reuse Token::equals() to
        // compare macros.
        token->location = SourceLocation();
        macro.replacements.push_back(*token);
        mTokenizer->lex(token);
    }
    if (!macro.replacements.empty())
    {
        // Whitespace preceding the replacement list is not considered part of
        // the replacement list for either form of macro.
        macro.replacements.front().setHasLeadingSpace(false);
    }

    // Check for macro redefinition.
    MacroSet::const_iterator iter = mMacroSet->find(macro.name);
    if (iter != mMacroSet->end() && !macro.equals(iter->second))
    {
        mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED,
                             token->location,
                             macro.name);
        return;
    }
    mMacroSet->insert(std::make_pair(macro.name, macro));
}

void DirectiveParser::parseUndef(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_UNDEF);

    mTokenizer->lex(token);
    if (token->type != Token::IDENTIFIER)
    {
        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                             token->location, token->text);
        return;
    }

    MacroSet::iterator iter = mMacroSet->find(token->text);
    if (iter != mMacroSet->end())
    {
        if (iter->second.predefined)
        {
            mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
                                 token->location, token->text);
        }
        else
        {
            mMacroSet->erase(iter);
        }
    }

    mTokenizer->lex(token);
}

void DirectiveParser::parseIf(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_IF);
    parseConditionalIf(token);
}

void DirectiveParser::parseIfdef(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_IFDEF);
    parseConditionalIf(token);
}

void DirectiveParser::parseIfndef(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_IFNDEF);
    parseConditionalIf(token);
}

void DirectiveParser::parseElse(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_ELSE);

    if (mConditionalStack.empty())
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        return;
    }

    ConditionalBlock &block = mConditionalStack.back();
    if (block.skipBlock)
    {
        // No diagnostics. Just skip the whole line.
        skipUntilEOD(mTokenizer, token);
        return;
    }
    if (block.foundElseGroup)
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        return;
    }

    block.foundElseGroup = true;
    block.skipGroup = block.foundValidGroup;
    block.foundValidGroup = true;

    // Warn if there are extra tokens after #else.
    mTokenizer->lex(token);
    if (!isEOD(token))
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
    }
}

void DirectiveParser::parseElif(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_ELIF);

    if (mConditionalStack.empty())
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        return;
    }

    ConditionalBlock &block = mConditionalStack.back();
    if (block.skipBlock)
    {
        // No diagnostics. Just skip the whole line.
        skipUntilEOD(mTokenizer, token);
        return;
    }
    if (block.foundElseGroup)
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        return;
    }
    if (block.foundValidGroup)
    {
        // Do not parse the expression.
        // Also be careful not to emit a diagnostic.
        block.skipGroup = true;
        skipUntilEOD(mTokenizer, token);
        return;
    }

    int expression = parseExpressionIf(token);
    block.skipGroup = expression == 0;
    block.foundValidGroup = expression != 0;
}

void DirectiveParser::parseEndif(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_ENDIF);

    if (mConditionalStack.empty())
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        return;
    }

    mConditionalStack.pop_back();

    // Warn if there are tokens after #endif.
    mTokenizer->lex(token);
    if (!isEOD(token))
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
    }
}

void DirectiveParser::parseError(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_ERROR);

    std::ostringstream stream;
    mTokenizer->lex(token);
    while ((token->type != '\n') && (token->type != Token::LAST))
    {
        stream << *token;
        mTokenizer->lex(token);
    }
    mDirectiveHandler->handleError(token->location, stream.str());
}

// Parses pragma of form: #pragma name[(value)].
void DirectiveParser::parsePragma(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_PRAGMA);

    enum State
    {
        PRAGMA_NAME,
        LEFT_PAREN,
        PRAGMA_VALUE,
        RIGHT_PAREN
    };

    bool valid = true;
    std::string name, value;
    int state = PRAGMA_NAME;

    mTokenizer->lex(token);
    bool stdgl = token->text == "STDGL";
    if (stdgl)
    {
        mTokenizer->lex(token);
    }
    while ((token->type != '\n') && (token->type != Token::LAST))
    {
        switch(state++)
        {
          case PRAGMA_NAME:
            name = token->text;
            valid = valid && (token->type == Token::IDENTIFIER);
            break;
          case LEFT_PAREN:
            valid = valid && (token->type == '(');
            break;
          case PRAGMA_VALUE:
            value = token->text;
            valid = valid && (token->type == Token::IDENTIFIER);
            break;
          case RIGHT_PAREN:
            valid = valid && (token->type == ')');
            break;
          default:
            valid = false;
            break;
        }
        mTokenizer->lex(token);
    }

    valid = valid && ((state == PRAGMA_NAME) ||     // Empty pragma.
                      (state == LEFT_PAREN) ||      // Without value.
                      (state == RIGHT_PAREN + 1));  // With value.
    if (!valid)
    {
        mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA,
                             token->location, name);
    }
    else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.
    {
        mDirectiveHandler->handlePragma(token->location, name, value, stdgl);
    }
}

void DirectiveParser::parseExtension(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_EXTENSION);

    enum State
    {
        EXT_NAME,
        COLON,
        EXT_BEHAVIOR
    };

    bool valid = true;
    std::string name, behavior;
    int state = EXT_NAME;

    mTokenizer->lex(token);
    while ((token->type != '\n') && (token->type != Token::LAST))
    {
        switch (state++)
        {
          case EXT_NAME:
            if (valid && (token->type != Token::IDENTIFIER))
            {
                mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME,
                                     token->location, token->text);
                valid = false;
            }
            if (valid) name = token->text;
            break;
          case COLON:
            if (valid && (token->type != ':'))
            {
                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                     token->location, token->text);
                valid = false;
            }
            break;
          case EXT_BEHAVIOR:
            if (valid && (token->type != Token::IDENTIFIER))
            {
                mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
                                     token->location, token->text);
                valid = false;
            }
            if (valid) behavior = token->text;
            break;
          default:
            if (valid)
            {
                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                     token->location, token->text);
                valid = false;
            }
            break;
        }
        mTokenizer->lex(token);
    }
    if (valid && (state != EXT_BEHAVIOR + 1))
    {
        mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE,
                             token->location, token->text);
        valid = false;
    }
    if (valid)
        mDirectiveHandler->handleExtension(token->location, name, behavior);
}

void DirectiveParser::parseVersion(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_VERSION);

    if (mPastFirstStatement)
    {
        mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        return;
    }

    enum State
    {
        VERSION_NUMBER,
        VERSION_PROFILE,
        VERSION_ENDLINE
    };

    bool valid = true;
    int version = 0;
    int state = VERSION_NUMBER;

    mTokenizer->lex(token);
    while (valid && (token->type != '\n') && (token->type != Token::LAST))
    {
        switch (state)
        {
          case VERSION_NUMBER:
            if (token->type != Token::CONST_INT)
            {
                mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER,
                                     token->location, token->text);
                valid = false;
            }
            if (valid && !token->iValue(&version))
            {
                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
                                     token->location, token->text);
                valid = false;
            }
            if (valid)
            {
                state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
            }
            break;
          case VERSION_PROFILE:
            if (token->type != Token::IDENTIFIER || token->text != "es")
            {
                mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
                                     token->location, token->text);
                valid = false;
            }
            state = VERSION_ENDLINE;
            break;
          default:
            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                 token->location, token->text);
            valid = false;
            break;
        }

        mTokenizer->lex(token);
    }

    if (valid && (state != VERSION_ENDLINE))
    {
        mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
                             token->location, token->text);
        valid = false;
    }

    if (valid)
    {
        mDirectiveHandler->handleVersion(token->location, version);
    }
}

void DirectiveParser::parseLine(Token *token)
{
    assert(getDirective(token) == DIRECTIVE_LINE);

    enum State
    {
        LINE_NUMBER,
        FILE_NUMBER
    };

    bool valid = true;
    int line = 0, file = 0;
    int state = LINE_NUMBER;

    MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);
    macroExpander.lex(token);
    while ((token->type != '\n') && (token->type != Token::LAST))
    {
        switch (state++)
        {
          case LINE_NUMBER:
            if (valid && (token->type != Token::CONST_INT))
            {
                mDiagnostics->report(Diagnostics::PP_INVALID_LINE_NUMBER,
                                     token->location, token->text);
                valid = false;
            }
            if (valid && !token->iValue(&line))
            {
                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
                                     token->location, token->text);
                valid = false;
            }
            break;
          case FILE_NUMBER:
            if (valid && (token->type != Token::CONST_INT))
            {
                mDiagnostics->report(Diagnostics::PP_INVALID_FILE_NUMBER,
                                     token->location, token->text);
                valid = false;
            }
            if (valid && !token->iValue(&file))
            {
                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
                                     token->location, token->text);
                valid = false;
            }
            break;
          default:
            if (valid)
            {
                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                                     token->location, token->text);
                valid = false;
            }
            break;
        }
        macroExpander.lex(token);
    }

    if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
    {
        mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE,
                             token->location, token->text);
        valid = false;
    }
    if (valid)
    {
        mTokenizer->setLineNumber(line);
        if (state == FILE_NUMBER + 1)
            mTokenizer->setFileNumber(file);
    }
}

bool DirectiveParser::skipping() const
{
    if (mConditionalStack.empty())
        return false;

    const ConditionalBlock& block = mConditionalStack.back();
    return block.skipBlock || block.skipGroup;
}

void DirectiveParser::parseConditionalIf(Token *token)
{
    ConditionalBlock block;
    block.type = token->text;
    block.location = token->location;

    if (skipping())
    {
        // This conditional block is inside another conditional group
        // which is skipped. As a consequence this whole block is skipped.
        // Be careful not to parse the conditional expression that might
        // emit a diagnostic.
        skipUntilEOD(mTokenizer, token);
        block.skipBlock = true;
    }
    else
    {
        DirectiveType directive = getDirective(token);

        int expression = 0;
        switch (directive)
        {
          case DIRECTIVE_IF:
            expression = parseExpressionIf(token);
            break;
          case DIRECTIVE_IFDEF:
            expression = parseExpressionIfdef(token);
            break;
          case DIRECTIVE_IFNDEF:
            expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
            break;
          default:
            assert(false);
            break;
        }
        block.skipGroup = expression == 0;
        block.foundValidGroup = expression != 0;
    }
    mConditionalStack.push_back(block);
}

int DirectiveParser::parseExpressionIf(Token *token)
{
    assert((getDirective(token) == DIRECTIVE_IF) ||
           (getDirective(token) == DIRECTIVE_ELIF));

    DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
    MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);
    ExpressionParser expressionParser(&macroExpander, mDiagnostics);

    int expression = 0;
    macroExpander.lex(token);
    expressionParser.parse(token, &expression);

    // Warn if there are tokens after #if expression.
    if (!isEOD(token))
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
    }

    return expression;
}

int DirectiveParser::parseExpressionIfdef(Token *token)
{
    assert((getDirective(token) == DIRECTIVE_IFDEF) ||
           (getDirective(token) == DIRECTIVE_IFNDEF));

    mTokenizer->lex(token);
    if (token->type != Token::IDENTIFIER)
    {
        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
        return 0;
    }

    MacroSet::const_iterator iter = mMacroSet->find(token->text);
    int expression = iter != mMacroSet->end() ? 1 : 0;

    // Warn if there are tokens after #ifdef expression.
    mTokenizer->lex(token);
    if (!isEOD(token))
    {
        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
                             token->location, token->text);
        skipUntilEOD(mTokenizer, token);
    }
    return expression;
}

}  // namespace pp
