104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org//
20bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved.
304d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org// Use of this source code is governed by a BSD-style license that can be
404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org// found in the LICENSE file.
504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org//
604d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org#include "DirectiveParser.h"
804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org#include <cassert>
1051b96855babe208c6c22693f42925cc6458bd158alokp@chromium.org#include <cstdlib>
1136124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org#include <sstream>
1204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
13b3077d086b365b1d54c3d755df19c6f8f349a562daniel@transgaming.com#include "DiagnosticsBase.h"
14b3077d086b365b1d54c3d755df19c6f8f349a562daniel@transgaming.com#include "DirectiveHandlerBase.h"
1504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org#include "ExpressionParser.h"
1604d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org#include "MacroExpander.h"
1704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org#include "Token.h"
1804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org#include "Tokenizer.h"
1904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
2004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.orgnamespace {
21d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.orgenum DirectiveType
22d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
23d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_NONE,
24d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_DEFINE,
25d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_UNDEF,
26d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_IF,
27d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_IFDEF,
28d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_IFNDEF,
29d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_ELSE,
30d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_ELIF,
31d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_ENDIF,
32d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_ERROR,
33d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_PRAGMA,
34d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_EXTENSION,
35d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_VERSION,
36d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DIRECTIVE_LINE
37d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org};
3804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
39d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao MoDirectiveType getDirective(const pp::Token *token)
40d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
41d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveDefine("define");
42d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveUndef("undef");
43d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveIf("if");
44d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveIfdef("ifdef");
45d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveIfndef("ifndef");
46d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveElse("else");
47d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveElif("elif");
48d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveEndif("endif");
49d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveError("error");
50d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectivePragma("pragma");
51d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveExtension("extension");
52d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveVersion("version");
53d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    static const std::string kDirectiveLine("line");
54d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
55d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (token->type != pp::Token::IDENTIFIER)
56d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_NONE;
57d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
585b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org    if (token->text == kDirectiveDefine)
59d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_DEFINE;
60d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveUndef)
61d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_UNDEF;
62d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveIf)
63d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_IF;
64d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveIfdef)
65d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_IFDEF;
66d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveIfndef)
67d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_IFNDEF;
68d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveElse)
69d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_ELSE;
70d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveElif)
71d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_ELIF;
72d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveEndif)
73d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_ENDIF;
74d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveError)
75d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_ERROR;
76d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectivePragma)
77d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_PRAGMA;
78d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveExtension)
79d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_EXTENSION;
80d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveVersion)
81d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_VERSION;
82d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (token->text == kDirectiveLine)
83d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return DIRECTIVE_LINE;
84d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
85d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    return DIRECTIVE_NONE;
86d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
87d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
88d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mobool isConditionalDirective(DirectiveType directive)
89d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
90d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    switch (directive)
91d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
92d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_IF:
93d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_IFDEF:
94d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_IFNDEF:
95d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_ELSE:
96d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_ELIF:
97d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_ENDIF:
98d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return true;
99d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      default:
100d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return false;
101d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
102d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
103d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
104d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org// Returns true if the token represents End Of Directive.
105d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mobool isEOD(const pp::Token *token)
106d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
107d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    return (token->type == '\n') || (token->type == pp::Token::LAST);
108d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
109d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
110d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
111d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
112d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    while(!isEOD(token))
113d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
114d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        lexer->lex(token);
115d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
116d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
117d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
118d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mobool isMacroNameReserved(const std::string &name)
11998d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org{
12098d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    // Names prefixed with "GL_" are reserved.
12198d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    if (name.substr(0, 3) == "GL_")
12298d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        return true;
12398d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
12498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    // Names containing two consecutive underscores are reserved.
12598d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    if (name.find("__") != std::string::npos)
12698d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        return true;
12798d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
12898d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    return false;
12998d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org}
13098d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
131d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mobool isMacroPredefined(const std::string &name,
132d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo                       const pp::MacroSet &macroSet)
133f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org{
134f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org    pp::MacroSet::const_iterator iter = macroSet.find(name);
135f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org    return iter != macroSet.end() ? iter->second.predefined : false;
136f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org}
137f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org
138d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo}  // namespace anonymous
139d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo
14004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.orgnamespace pp
14104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
14204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
14304d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.orgclass DefinedParser : public Lexer
14404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
14504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org  public:
146d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    DefinedParser(Lexer *lexer,
147d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo                  const MacroSet *macroSet,
148d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo                  Diagnostics *diagnostics)
149d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo        : mLexer(lexer),
150d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo          mMacroSet(macroSet),
151d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo          mDiagnostics(diagnostics)
152d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
153d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
15404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
15504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org  protected:
156d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    virtual void lex(Token *token)
15704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    {
158d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        static const std::string kDefined("defined");
159d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
16004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org        mLexer->lex(token);
161d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        if (token->type != Token::IDENTIFIER)
162d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            return;
1635b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org        if (token->text != kDefined)
164d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            return;
165d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
166d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        bool paren = false;
167d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        mLexer->lex(token);
168d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        if (token->type == '(')
169d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        {
170d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            paren = true;
171d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            mLexer->lex(token);
172d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        }
173d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
174d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        if (token->type != Token::IDENTIFIER)
175d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        {
1767f2d7945ee702241829727751bd4c7424662b225Shannon Woods            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
1775b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                 token->location, token->text);
178d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            skipUntilEOD(mLexer, token);
179d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            return;
180d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        }
1815b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org        MacroSet::const_iterator iter = mMacroSet->find(token->text);
182d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        std::string expression = iter != mMacroSet->end() ? "1" : "0";
183d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
184d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        if (paren)
185d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        {
186d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            mLexer->lex(token);
187d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            if (token->type != ')')
188d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            {
1897f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
1905b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
191d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org                skipUntilEOD(mLexer, token);
192d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org                return;
193d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            }
194d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        }
195d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
196d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // We have a valid defined operator.
197d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // Convert the current token into a CONST_INT token.
198d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        token->type = Token::CONST_INT;
1995b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org        token->text = expression;
20004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    }
20104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
20204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org  private:
203d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    Lexer *mLexer;
204d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    const MacroSet *mMacroSet;
205d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    Diagnostics *mDiagnostics;
20604d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org};
20704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
208d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao MoDirectiveParser::DirectiveParser(Tokenizer *tokenizer,
209d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo                                 MacroSet *macroSet,
210d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo                                 Diagnostics *diagnostics,
211d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo                                 DirectiveHandler *directiveHandler)
212d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    : mPastFirstStatement(false),
213d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo      mTokenizer(tokenizer),
214d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo      mMacroSet(macroSet),
215d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo      mDiagnostics(diagnostics),
216d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo      mDirectiveHandler(directiveHandler)
2172c958eefb71f1b939dbda4477df3f0c8fa47a7b8alokp@chromium.org{
2182c958eefb71f1b939dbda4477df3f0c8fa47a7b8alokp@chromium.org}
2192c958eefb71f1b939dbda4477df3f0c8fa47a7b8alokp@chromium.org
220d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::lex(Token *token)
22104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
22204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    do
22304d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    {
22404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org        mTokenizer->lex(token);
225d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
226432d6fc4a28f06292801141cc021c60f1b47f5a8alokp@chromium.org        if (token->type == Token::PP_HASH)
227d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        {
228d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            parseDirective(token);
229d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org            mPastFirstStatement = true;
230d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        }
231d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
232d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        if (token->type == Token::LAST)
233d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        {
234d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            if (!mConditionalStack.empty())
235d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            {
236d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo                const ConditionalBlock &block = mConditionalStack.back();
2377f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED,
238d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org                                     block.location, block.type);
239d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            }
240d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            break;
241d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        }
242d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
243d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    }
244d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    while (skipping() || (token->type == '\n'));
245d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org
246d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org    mPastFirstStatement = true;
24704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
24804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
249d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseDirective(Token *token)
25004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
251432d6fc4a28f06292801141cc021c60f1b47f5a8alokp@chromium.org    assert(token->type == Token::PP_HASH);
25204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
25304d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
254d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org    if (isEOD(token))
255d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org    {
256d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org        // Empty Directive.
257d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org        return;
258d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org    }
259d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org
260d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DirectiveType directive = getDirective(token);
261d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
262d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    // While in an excluded conditional block/group,
263d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    // we only parse conditional directives.
264d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (skipping() && !isConditionalDirective(directive))
265d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
266d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
267d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
268d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
269d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
270d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    switch(directive)
271d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
272d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_NONE:
2737f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME,
2745b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
275d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
276d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
277d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_DEFINE:
278d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseDefine(token);
279d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
280d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_UNDEF:
281d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseUndef(token);
282d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
283d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_IF:
284d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseIf(token);
285d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
286d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_IFDEF:
287d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseIfdef(token);
288d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
289d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_IFNDEF:
290d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseIfndef(token);
291d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
292d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_ELSE:
293d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseElse(token);
294d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
295d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_ELIF:
296d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseElif(token);
297d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
298d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_ENDIF:
299d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseEndif(token);
300d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
301d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_ERROR:
302d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseError(token);
303d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
304d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_PRAGMA:
305d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parsePragma(token);
306d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
307d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_EXTENSION:
308d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseExtension(token);
309d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
310d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_VERSION:
311d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseVersion(token);
312d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
313d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      case DIRECTIVE_LINE:
314d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        parseLine(token);
315d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
316d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org      default:
317d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        assert(false);
318d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        break;
319d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
320d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
321d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    skipUntilEOD(mTokenizer, token);
322d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (token->type == Token::LAST)
323d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
3247f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE,
3255b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
32604d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    }
32704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
32804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
329d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseDefine(Token *token)
33004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
331d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_DEFINE);
33298d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
33304d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
3347c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    if (token->type != Token::IDENTIFIER)
33598d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    {
3367f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
3375b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
338f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org        return;
339f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org    }
3405b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org    if (isMacroPredefined(token->text, *mMacroSet))
341f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org    {
3427f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
3435b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
34498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        return;
34598d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    }
3465b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org    if (isMacroNameReserved(token->text))
34798d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    {
3487f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED,
3495b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
35098d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        return;
35198d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    }
35298d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
35398d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    Macro macro;
35498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    macro.type = Macro::kTypeObj;
3555b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org    macro.name = token->text;
35698d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
35798d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    mTokenizer->lex(token);
35898d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    if (token->type == '(' && !token->hasLeadingSpace())
35998d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    {
36098d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        // Function-like macro. Collect arguments.
36198d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        macro.type = Macro::kTypeFunc;
362d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo        do
363d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo        {
36498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org            mTokenizer->lex(token);
3657c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            if (token->type != Token::IDENTIFIER)
36698d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org                break;
3675b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org            macro.parameters.push_back(token->text);
36898d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
3697fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org            mTokenizer->lex(token);  // Get ','.
370d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo        }
371d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo        while (token->type == ',');
37298d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
37398d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        if (token->type != ')')
37498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        {
3757f2d7945ee702241829727751bd4c7424662b225Shannon Woods            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
37698d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org                                 token->location,
3775b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                 token->text);
37898d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org            return;
37998d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        }
3807fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org        mTokenizer->lex(token);  // Get ')'.
38198d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    }
38298d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
3837c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    while ((token->type != '\n') && (token->type != Token::LAST))
38498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    {
38598d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        // Reset the token location because it is unnecessary in replacement
38698d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        // list. Resetting it also allows us to reuse Token::equals() to
38798d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        // compare macros.
38898d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        token->location = SourceLocation();
38998d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        macro.replacements.push_back(*token);
39098d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        mTokenizer->lex(token);
39198d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    }
3927fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org    if (!macro.replacements.empty())
3937fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org    {
3947fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org        // Whitespace preceding the replacement list is not considered part of
3957fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org        // the replacement list for either form of macro.
3967fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org        macro.replacements.front().setHasLeadingSpace(false);
3977fc38dddd2f5b6349348230475ca359666af583aalokp@chromium.org    }
39898d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
39998d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    // Check for macro redefinition.
40098d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    MacroSet::const_iterator iter = mMacroSet->find(macro.name);
40198d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    if (iter != mMacroSet->end() && !macro.equals(iter->second))
40298d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    {
4037f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED,
40498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org                             token->location,
40598d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org                             macro.name);
40698d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        return;
40798d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    }
40898d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    mMacroSet->insert(std::make_pair(macro.name, macro));
40904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
41004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
411d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseUndef(Token *token)
41204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
413d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_UNDEF);
41498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
41598d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    mTokenizer->lex(token);
4167c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    if (token->type != Token::IDENTIFIER)
41798d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    {
4187f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
4195b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
42098d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org        return;
42198d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    }
42298d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
4235b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org    MacroSet::iterator iter = mMacroSet->find(token->text);
42498d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    if (iter != mMacroSet->end())
425f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org    {
426f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org        if (iter->second.predefined)
427f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org        {
4287f2d7945ee702241829727751bd4c7424662b225Shannon Woods            mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
4295b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                 token->location, token->text);
430f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org        }
431f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org        else
432f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org        {
433f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org            mMacroSet->erase(iter);
434f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org        }
435f3cdb460d1dde723815eecd006274a3da5d81099alokp@chromium.org    }
43698d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org
43704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
43804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
43904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
440d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseIf(Token *token)
44104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
442d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_IF);
443d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    parseConditionalIf(token);
44404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
44504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
446d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseIfdef(Token *token)
44704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
448d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_IFDEF);
449d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    parseConditionalIf(token);
45004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
45104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
452d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseIfndef(Token *token)
45304d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
454d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_IFNDEF);
455d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    parseConditionalIf(token);
45604d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
45704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
458d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseElse(Token *token)
45904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
460d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_ELSE);
461d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
462d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (mConditionalStack.empty())
463d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
4647f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
4655b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
466d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
467d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
468d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
469d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
470d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    ConditionalBlock &block = mConditionalStack.back();
471d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (block.skipBlock)
472d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
473d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // No diagnostics. Just skip the whole line.
474d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
475d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
476d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
477d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (block.foundElseGroup)
478d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
4797f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
4805b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
481d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
482d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
483d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
484d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
485d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    block.foundElseGroup = true;
486d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    block.skipGroup = block.foundValidGroup;
487d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    block.foundValidGroup = true;
488d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
489d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    // Warn if there are extra tokens after #else.
49004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
491d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (!isEOD(token))
492d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
4937f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
4945b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
495d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
496d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
49704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
49804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
499d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseElif(Token *token)
50004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
501d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_ELIF);
502d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
503d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (mConditionalStack.empty())
504d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
5057f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
5065b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
507d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
508d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
509d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
510d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
511d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    ConditionalBlock &block = mConditionalStack.back();
512d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (block.skipBlock)
513d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
514d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // No diagnostics. Just skip the whole line.
515d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
516d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
517d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
518d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (block.foundElseGroup)
519d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
5207f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
5215b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
522d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
523d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
524d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
525d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (block.foundValidGroup)
526d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
527d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // Do not parse the expression.
528d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // Also be careful not to emit a diagnostic.
529d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        block.skipGroup = true;
530d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
531d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
532d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
533d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
534d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    int expression = parseExpressionIf(token);
535d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    block.skipGroup = expression == 0;
536d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    block.foundValidGroup = expression != 0;
53704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
53804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
539d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseEndif(Token *token)
54004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
541d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_ENDIF);
542d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
543d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (mConditionalStack.empty())
544d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
5457f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
5465b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
547d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
548d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return;
549d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
550d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
551d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    mConditionalStack.pop_back();
552d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
553d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    // Warn if there are tokens after #endif.
55404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
555d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (!isEOD(token))
556d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
5577f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
5585b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
559d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
560d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
56104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
56204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
563d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseError(Token *token)
56404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
565d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_ERROR);
56636124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org
5672e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org    std::ostringstream stream;
56804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
5697c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    while ((token->type != '\n') && (token->type != Token::LAST))
57036124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    {
57136124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        stream << *token;
57236124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        mTokenizer->lex(token);
57336124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    }
57436124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    mDirectiveHandler->handleError(token->location, stream.str());
57504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
57604d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
57736124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org// Parses pragma of form: #pragma name[(value)].
578d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parsePragma(Token *token)
57904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
580d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_PRAGMA);
58136124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org
58236124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    enum State
58336124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    {
58436124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        PRAGMA_NAME,
58536124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        LEFT_PAREN,
58636124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        PRAGMA_VALUE,
58736124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        RIGHT_PAREN
58836124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    };
58936124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org
59036124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    bool valid = true;
59136124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    std::string name, value;
59236124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    int state = PRAGMA_NAME;
59336124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org
59404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
5957c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    while ((token->type != '\n') && (token->type != Token::LAST))
59636124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    {
59736124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        switch(state++)
59836124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        {
59936124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org          case PRAGMA_NAME:
6005b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org            name = token->text;
6017c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            valid = valid && (token->type == Token::IDENTIFIER);
60236124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            break;
60336124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org          case LEFT_PAREN:
60436124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            valid = valid && (token->type == '(');
60536124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            break;
60636124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org          case PRAGMA_VALUE:
6075b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org            value = token->text;
6087c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            valid = valid && (token->type == Token::IDENTIFIER);
60936124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            break;
61036124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org          case RIGHT_PAREN:
61136124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            valid = valid && (token->type == ')');
61236124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            break;
61336124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org          default:
61436124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            valid = false;
61536124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org            break;
61636124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        }
61736124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        mTokenizer->lex(token);
61836124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    }
61936124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org
62036124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    valid = valid && ((state == PRAGMA_NAME) ||     // Empty pragma.
62136124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org                      (state == LEFT_PAREN) ||      // Without value.
62236124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org                      (state == RIGHT_PAREN + 1));  // With value.
62336124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    if (!valid)
62436124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    {
6257f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA,
62636124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org                             token->location, name);
62736124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    }
62836124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.
62936124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    {
63036124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org        mDirectiveHandler->handlePragma(token->location, name, value);
63136124de8ce9855c1cfdfb6529b47822e12123274alokp@chromium.org    }
63204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
63304d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
634d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseExtension(Token *token)
63504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
636d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_EXTENSION);
6377c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org
6387c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    enum State
6397c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    {
6407c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        EXT_NAME,
6417c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        COLON,
6427c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        EXT_BEHAVIOR
6437c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    };
6447c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org
6457c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    bool valid = true;
6467c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    std::string name, behavior;
6477c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    int state = EXT_NAME;
6487c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org
64904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
6507c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    while ((token->type != '\n') && (token->type != Token::LAST))
6517c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    {
6527c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        switch (state++)
6537c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        {
6547c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org          case EXT_NAME:
6557c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            if (valid && (token->type != Token::IDENTIFIER))
6567c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            {
6577f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME,
6585b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
6597c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org                valid = false;
6607c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            }
6615b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org            if (valid) name = token->text;
6627c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            break;
6637c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org          case COLON:
6647c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            if (valid && (token->type != ':'))
6657c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            {
6667f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
6675b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
6687c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org                valid = false;
6697c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            }
6707c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            break;
6717c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org          case EXT_BEHAVIOR:
6727c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            if (valid && (token->type != Token::IDENTIFIER))
6737c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            {
6747f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
6755b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
6767c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org                valid = false;
6777c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            }
6785b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org            if (valid) behavior = token->text;
6797c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            break;
6807c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org          default:
6817c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            if (valid)
6827c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            {
6837f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
6845b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
6857c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org                valid = false;
6867c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            }
6877c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            break;
6887c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        }
6897c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        mTokenizer->lex(token);
6907c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    }
6917c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    if (valid && (state != EXT_BEHAVIOR + 1))
6927c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    {
6937f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE,
6945b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
6957c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        valid = false;
6967c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    }
6977c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    if (valid)
6987c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        mDirectiveHandler->handleExtension(token->location, name, behavior);
69904d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
70004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
701d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseVersion(Token *token)
70204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
703d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_VERSION);
7047c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org
705d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org    if (mPastFirstStatement)
706d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org    {
7077f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
708d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org                             token->location, token->text);
709d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org        skipUntilEOD(mTokenizer, token);
710d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org        return;
711d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org    }
712d0d9f87ac02955ae496b5cc51d5dffb693b31a87alokp@chromium.org
7137c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    enum State
7147c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    {
7150bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com        VERSION_NUMBER,
7160bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com        VERSION_PROFILE,
7170bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com        VERSION_ENDLINE
7187c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    };
7197c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org
7207c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    bool valid = true;
7217c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    int version = 0;
7227c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    int state = VERSION_NUMBER;
7237c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org
72404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    mTokenizer->lex(token);
7250bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com    while (valid && (token->type != '\n') && (token->type != Token::LAST))
7267c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    {
7270bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com        switch (state)
7287c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        {
7297c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org          case VERSION_NUMBER:
7300bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            if (token->type != Token::CONST_INT)
7317c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            {
7327f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER,
7335b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
7347c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org                valid = false;
7357c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            }
7362e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            if (valid && !token->iValue(&version))
7372e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            {
7387f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
7392e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org                                     token->location, token->text);
7402e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org                valid = false;
7412e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            }
7427c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            if (valid)
7437c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            {
7440bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com                state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
7450bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            }
7460bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            break;
7470bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com          case VERSION_PROFILE:
7480bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            if (token->type != Token::IDENTIFIER || token->text != "es")
7490bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            {
7507f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
7515b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
7527c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org                valid = false;
7537c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            }
7540bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            state = VERSION_ENDLINE;
7550bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            break;
7560bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com          default:
7577f2d7945ee702241829727751bd4c7424662b225Shannon Woods            mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
7580bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com                                 token->location, token->text);
7590bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com            valid = false;
7607c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org            break;
7617c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        }
7620bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com
7637c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        mTokenizer->lex(token);
7647c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    }
7650bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com
7660bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com    if (valid && (state != VERSION_ENDLINE))
7677c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    {
7687f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
7695b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
7707c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        valid = false;
7717c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    }
7720bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com
7737c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org    if (valid)
7740bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com    {
7757c884540ad7607a772b13b2ca7bc8f6b21574946alokp@chromium.org        mDirectiveHandler->handleVersion(token->location, version);
7760bbed38f417d490604909de5928d725fb39c5e3cshannon.woods%transgaming.com@gtempaccount.com    }
77704d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
77804d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
779d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseLine(Token *token)
78004d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org{
781d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert(getDirective(token) == DIRECTIVE_LINE);
78246aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org
78346aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    enum State
78446aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    {
78546aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        LINE_NUMBER,
78646aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        FILE_NUMBER
78746aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    };
78846aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org
78946aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    bool valid = true;
79046aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    int line = 0, file = 0;
79146aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    int state = LINE_NUMBER;
79246aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org
79398d04ec8e2db023e04818c4af97b5e613af3f55calokp@chromium.org    MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);
79404d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org    macroExpander.lex(token);
79546aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    while ((token->type != '\n') && (token->type != Token::LAST))
79646aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    {
79746aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        switch (state++)
79846aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        {
79946aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org          case LINE_NUMBER:
80046aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            if (valid && (token->type != Token::CONST_INT))
80146aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            {
8027f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INVALID_LINE_NUMBER,
8035b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
80446aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org                valid = false;
80546aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            }
8062e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            if (valid && !token->iValue(&line))
8072e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            {
8087f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
8092e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org                                     token->location, token->text);
8102e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org                valid = false;
8112e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            }
81246aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            break;
81346aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org          case FILE_NUMBER:
81446aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            if (valid && (token->type != Token::CONST_INT))
81546aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            {
8167f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INVALID_FILE_NUMBER,
8175b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
81846aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org                valid = false;
81946aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            }
8202e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            if (valid && !token->iValue(&file))
8212e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            {
8227f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
8232e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org                                     token->location, token->text);
8242e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org                valid = false;
8252e81891c21bfb199bb53f903bf0967f07efb65d8alokp@chromium.org            }
82646aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            break;
82746aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org          default:
82846aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            if (valid)
82946aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            {
8307f2d7945ee702241829727751bd4c7424662b225Shannon Woods                mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
8315b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                                     token->location, token->text);
83246aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org                valid = false;
83346aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            }
83446aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org            break;
83546aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        }
83646aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        macroExpander.lex(token);
83746aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    }
83846aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org
83946aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
84046aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    {
8417f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE,
8425b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
84346aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        valid = false;
84446aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    }
84546aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    if (valid)
84646aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    {
84746aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org        mTokenizer->setLineNumber(line);
848d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo        if (state == FILE_NUMBER + 1)
849d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo            mTokenizer->setFileNumber(file);
85046aa13d87fdc2da6d36fd14f678f204f8f98ae41alokp@chromium.org    }
85104d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}
85204d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org
853d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.orgbool DirectiveParser::skipping() const
854d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
855d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo    if (mConditionalStack.empty())
856d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Mo        return false;
857d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
858d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    const ConditionalBlock& block = mConditionalStack.back();
859d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    return block.skipBlock || block.skipGroup;
860d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
861d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
862d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Movoid DirectiveParser::parseConditionalIf(Token *token)
863d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
864d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    ConditionalBlock block;
8655b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org    block.type = token->text;
866d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    block.location = token->location;
867d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
868d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (skipping())
869d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
870d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // This conditional block is inside another conditional group
871d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // which is skipped. As a consequence this whole block is skipped.
872d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // Be careful not to parse the conditional expression that might
873d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        // emit a diagnostic.
874d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
875d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        block.skipBlock = true;
876d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
877d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    else
878d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
879d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        DirectiveType directive = getDirective(token);
880d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
881d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        int expression = 0;
882d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        switch (directive)
883d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        {
884d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org          case DIRECTIVE_IF:
885d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            expression = parseExpressionIf(token);
886d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            break;
887d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org          case DIRECTIVE_IFDEF:
888d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            expression = parseExpressionIfdef(token);
889d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            break;
890d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org          case DIRECTIVE_IFNDEF:
891d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
892d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            break;
893d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org          default:
894d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            assert(false);
895d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org            break;
896d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        }
897d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        block.skipGroup = expression == 0;
898d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        block.foundValidGroup = expression != 0;
899d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
900d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    mConditionalStack.push_back(block);
901d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
902d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
903d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Moint DirectiveParser::parseExpressionIf(Token *token)
904d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
905d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert((getDirective(token) == DIRECTIVE_IF) ||
906d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org           (getDirective(token) == DIRECTIVE_ELIF));
907d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
908d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
909d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);
910d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    ExpressionParser expressionParser(&macroExpander, mDiagnostics);
911d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
912d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    int expression = 0;
913d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    macroExpander.lex(token);
914d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    expressionParser.parse(token, &expression);
915d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
916d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    // Warn if there are tokens after #if expression.
917d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (!isEOD(token))
918d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
9197f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
9205b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
921d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
922d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
923d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
924d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    return expression;
925d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
926d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
927d526f9895c0aa867adb74a78e53832a9240c6ad6Zhenyao Moint DirectiveParser::parseExpressionIfdef(Token *token)
928d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org{
929d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    assert((getDirective(token) == DIRECTIVE_IFDEF) ||
930d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org           (getDirective(token) == DIRECTIVE_IFNDEF));
931d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
932d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    mTokenizer->lex(token);
933d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (token->type != Token::IDENTIFIER)
934d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
9357f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
9365b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
937d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
938d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        return 0;
939d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
940d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
9415b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org    MacroSet::const_iterator iter = mMacroSet->find(token->text);
942d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    int expression = iter != mMacroSet->end() ? 1 : 0;
943d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
944d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    // Warn if there are tokens after #ifdef expression.
945d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    mTokenizer->lex(token);
946d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    if (!isEOD(token))
947d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    {
9487f2d7945ee702241829727751bd4c7424662b225Shannon Woods        mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
9495b6a68e04a7d27dab71524fa481f42818f84a240alokp@chromium.org                             token->location, token->text);
950d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org        skipUntilEOD(mTokenizer, token);
951d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    }
952d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org    return expression;
953d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org}
954d39ec4c15d6e656e027d7ded7ffceaafa0608e89alokp@chromium.org
95504d7d22bb835408a82600244e09b9dcacbc0fa11alokp@chromium.org}  // namespace pp
956