1d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//
3d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
4d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// you may not use this file except in compliance with the License.
5d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// You may obtain a copy of the License at
6d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//
7d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
8d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//
9d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Unless required by applicable law or agreed to in writing, software
10d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
11d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// See the License for the specific language governing permissions and
13d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// limitations under the License.
14d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
15d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "DirectiveParser.h"
16d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
17d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include <cassert>
18d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include <cstdlib>
19d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include <sstream>
20d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
21d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Diagnostics.h"
22d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "DirectiveHandler.h"
23d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "ExpressionParser.h"
24d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "MacroExpander.h"
25d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Token.h"
26d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Tokenizer.h"
27d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
28d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensnamespace {
29d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensenum DirectiveType
30d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
31d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_NONE,
32d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_DEFINE,
33d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_UNDEF,
34d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_IF,
35d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_IFDEF,
36d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_IFNDEF,
37d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_ELSE,
38d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_ELIF,
39d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_ENDIF,
40d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_ERROR,
41d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_PRAGMA,
42d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_EXTENSION,
43d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_VERSION,
44d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DIRECTIVE_LINE
45d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens};
46d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}  // namespace
47d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
48d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensstatic DirectiveType getDirective(const pp::Token* token)
49d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
50d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveDefine("define");
51d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveUndef("undef");
52d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveIf("if");
53d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveIfdef("ifdef");
54d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveIfndef("ifndef");
55d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveElse("else");
56d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveElif("elif");
57d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveEndif("endif");
58d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveError("error");
59d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectivePragma("pragma");
60d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveExtension("extension");
61d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveVersion("version");
62d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	static const std::string kDirectiveLine("line");
63d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
64d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (token->type != pp::Token::IDENTIFIER)
65d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_NONE;
66d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
67d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (token->text == kDirectiveDefine)
68d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_DEFINE;
69d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveUndef)
70d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_UNDEF;
71d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveIf)
72d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_IF;
73d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveIfdef)
74d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_IFDEF;
75d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveIfndef)
76d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_IFNDEF;
77d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveElse)
78d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_ELSE;
79d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveElif)
80d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_ELIF;
81d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveEndif)
82d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_ENDIF;
83d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveError)
84d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_ERROR;
85d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectivePragma)
86d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_PRAGMA;
87d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveExtension)
88d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_EXTENSION;
89d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveVersion)
90d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_VERSION;
91d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (token->text == kDirectiveLine)
92d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return DIRECTIVE_LINE;
93d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
94d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	return DIRECTIVE_NONE;
95d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
96d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
97d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensstatic bool isConditionalDirective(DirectiveType directive)
98d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
99d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	switch (directive)
100d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
101d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_IF:
102d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_IFDEF:
103d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_IFNDEF:
104d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_ELSE:
105d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_ELIF:
106d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_ENDIF:
107d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return true;
108d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	default:
109d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return false;
110d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
111d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
112d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
113d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Returns true if the token represents End Of Directive.
114d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensstatic bool isEOD(const pp::Token* token)
115d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
116d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	return (token->type == '\n') || (token->type == pp::Token::LAST);
117d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
118d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
119d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensstatic void skipUntilEOD(pp::Lexer* lexer, pp::Token* token)
120d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
121d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	while(!isEOD(token))
122d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
123d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		lexer->lex(token);
124d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
125d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
126d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
127d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensstatic bool isMacroNameReserved(const std::string& name)
128d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
129d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// Names prefixed with "GL_" are reserved.
130d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (name.substr(0, 3) == "GL_")
131d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return true;
132d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
133d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// Names containing two consecutive underscores are reserved.
134d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (name.find("__") != std::string::npos)
135d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return true;
136d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
137d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	return false;
138d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
139d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
140d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensstatic bool isMacroPredefined(const std::string& name,
141d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens                              const pp::MacroSet& macroSet)
142d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
143d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	pp::MacroSet::const_iterator iter = macroSet.find(name);
144d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	return iter != macroSet.end() ? iter->second.predefined : false;
145d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
146d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
147d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensnamespace pp
148d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
149d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
150d999309b36cb3dceadd38217b322f0e96a06b202Nicolas CapensDirectiveParser::DirectiveParser(Tokenizer* tokenizer,
151d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens                                 MacroSet* macroSet,
152d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens                                 Diagnostics* diagnostics,
153d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens                                 DirectiveHandler* directiveHandler) :
154d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mPastFirstStatement(false),
155d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer(tokenizer),
156d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mMacroSet(macroSet),
157d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mDiagnostics(diagnostics),
158d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mDirectiveHandler(directiveHandler)
159d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
160d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
161d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
162d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::lex(Token* token)
163d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
164d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	do
165d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
166d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->lex(token);
167d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
168d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if (token->type == Token::PP_HASH)
169d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
170d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			parseDirective(token);
171d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			mPastFirstStatement = true;
172d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
173d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
174d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if (token->type == Token::LAST)
175d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
176d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (!mConditionalStack.empty())
177d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
178d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				const ConditionalBlock& block = mConditionalStack.back();
179d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED,
180d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     block.location, block.type);
181d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
182d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
183d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
184d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
185d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	} while (skipping() || (token->type == '\n'));
186d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
187d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mPastFirstStatement = true;
188d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
189d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
190d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseDirective(Token* token)
191d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
192d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(token->type == Token::PP_HASH);
193d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
194d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
195d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (isEOD(token))
196d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
197d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// Empty Directive.
198d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
199d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
200d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
201d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	DirectiveType directive = getDirective(token);
202d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
203d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// While in an excluded conditional block/group,
204d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// we only parse conditional directives.
205d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (skipping() && !isConditionalDirective(directive))
206d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
207d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
208d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
209d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
210d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
211d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	switch(directive)
212d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
213d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_NONE:
214d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME,
215d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
216d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
217d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
218d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_DEFINE:
219d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseDefine(token);
220d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
221d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_UNDEF:
222d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseUndef(token);
223d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
224d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_IF:
225d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseIf(token);
226d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
227d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_IFDEF:
228d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseIfdef(token);
229d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
230d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_IFNDEF:
231d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseIfndef(token);
232d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
233d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_ELSE:
234d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseElse(token);
235d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
236d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_ELIF:
237d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseElif(token);
238d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
239d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_ENDIF:
240d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseEndif(token);
241d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
242d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_ERROR:
243d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseError(token);
244d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
245d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_PRAGMA:
246d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parsePragma(token);
247d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
248d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_EXTENSION:
249d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseExtension(token);
250d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
251d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_VERSION:
252d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseVersion(token);
253d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
254d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	case DIRECTIVE_LINE:
255d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		parseLine(token);
256d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
257d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	default:
258d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		assert(false);
259d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		break;
260d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
261d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
262d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	skipUntilEOD(mTokenizer, token);
263d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (token->type == Token::LAST)
264d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
265d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE,
266d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
267d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
268d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
269d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
270d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseDefine(Token* token)
271d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
272d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_DEFINE);
273d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
274d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
275d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (token->type != Token::IDENTIFIER)
276d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
277d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
278d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
279d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
280d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
281d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (isMacroPredefined(token->text, *mMacroSet))
282d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
283d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED,
284d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
285d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
286d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
287d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (isMacroNameReserved(token->text))
288d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
289d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED,
290d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
291d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
292d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
293d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
294d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	Macro macro;
295d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	macro.type = Macro::kTypeObj;
296d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	macro.name = token->text;
297d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
298d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
299d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (token->type == '(' && !token->hasLeadingSpace())
300d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
301d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// Function-like macro. Collect arguments.
302d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		macro.type = Macro::kTypeFunc;
303d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		do {
304d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			mTokenizer->lex(token);
305d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (token->type != Token::IDENTIFIER)
306d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				break;
307d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
308d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (std::find(macro.parameters.begin(), macro.parameters.end(), token->text) != macro.parameters.end())
309d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
310d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::MACRO_DUPLICATE_PARAMETER_NAMES,
311d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
312d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				return;
313d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
314d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
315d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			macro.parameters.push_back(token->text);
316d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
317d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			mTokenizer->lex(token);  // Get ','.
318d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		} while (token->type == ',');
319d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
320d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if (token->type != ')')
321d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
322d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
323d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			                     token->location,
324d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			                     token->text);
325d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
326d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
327d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->lex(token);  // Get ')'.
328d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
329d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
330d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	while ((token->type != '\n') && (token->type != Token::LAST))
331d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
332d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// Reset the token location because it is unnecessary in replacement
333d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// list. Resetting it also allows us to reuse Token::equals() to
334d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// compare macros.
335d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		token->location = SourceLocation();
336d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		macro.replacements.push_back(*token);
337d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->lex(token);
338d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
339d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (!macro.replacements.empty())
340d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
341d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// Whitespace preceding the replacement list is not considered part of
342d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// the replacement list for either form of macro.
343d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		macro.replacements.front().setHasLeadingSpace(false);
344d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
345d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
346d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// Check for macro redefinition.
347d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	MacroSet::const_iterator iter = mMacroSet->find(macro.name);
348d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (iter != mMacroSet->end() && !macro.equals(iter->second))
349d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
350d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::MACRO_REDEFINED,
351d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location,
352d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     macro.name);
353d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
354d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
355d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mMacroSet->insert(std::make_pair(macro.name, macro));
356d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
357d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
358d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseUndef(Token* token)
359d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
360d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_UNDEF);
361d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
362d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
363d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (token->type != Token::IDENTIFIER)
364d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
365d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
366d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
367d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
368d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
369d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
370d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	MacroSet::iterator iter = mMacroSet->find(token->text);
371d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (iter != mMacroSet->end())
372d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
373d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if (iter->second.predefined)
374d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
375d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED,
376d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			                     token->location, token->text);
377d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
378d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		else
379d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
380d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			mMacroSet->erase(iter);
381d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
382d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
383d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
384d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
385d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
386d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
387d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseIf(Token* token)
388d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
389d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_IF);
390d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	parseConditionalIf(token);
391d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
392d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
393d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseIfdef(Token* token)
394d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
395d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_IFDEF);
396d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	parseConditionalIf(token);
397d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
398d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
399d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseIfndef(Token* token)
400d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
401d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_IFNDEF);
402d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	parseConditionalIf(token);
403d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
404d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
405d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseElse(Token* token)
406d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
407d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_ELSE);
408d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
409d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (mConditionalStack.empty())
410d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
411d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF,
412d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
413d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
414d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
415d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
416d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
417d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	ConditionalBlock& block = mConditionalStack.back();
418d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (block.skipBlock)
419d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
420d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// No diagnostics. Just skip the whole line.
421d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
422d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
423d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
424d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (block.foundElseGroup)
425d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
426d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE,
427d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
428d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
429d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
430d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
431d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
432d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	block.foundElseGroup = true;
433d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	block.skipGroup = block.foundValidGroup;
434d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	block.foundValidGroup = true;
435d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
436d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// Check if there are extra tokens after #else.
437d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
438d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (!isEOD(token))
439d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
440d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
441d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
442d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
443d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
444d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
445d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
446d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseElif(Token* token)
447d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
448d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_ELIF);
449d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
450d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (mConditionalStack.empty())
451d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
452d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF,
453d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
454d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
455d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
456d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
457d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
458d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	ConditionalBlock& block = mConditionalStack.back();
459d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (block.skipBlock)
460d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
461d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// No diagnostics. Just skip the whole line.
462d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
463d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
464d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
465d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (block.foundElseGroup)
466d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
467d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE,
468d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
469d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
470d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
471d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
472d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (block.foundValidGroup)
473d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
474d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// Do not parse the expression.
475d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// Also be careful not to emit a diagnostic.
476d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		block.skipGroup = true;
477d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
478d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
479d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
480d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
481d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int expression = parseExpressionIf(token);
482d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	block.skipGroup = expression == 0;
483d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	block.foundValidGroup = expression != 0;
484d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
485d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
486d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseEndif(Token* token)
487d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
488d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_ENDIF);
489d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
490d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (mConditionalStack.empty())
491d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
492d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF,
493d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
494d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
495d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
496d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
497d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
498d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mConditionalStack.pop_back();
499d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
500d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// Check if there are tokens after #endif.
501d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
502d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (!isEOD(token))
503d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
504d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
505d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
506d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
507d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
508d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
509d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
510d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseError(Token* token)
511d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
512d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_ERROR);
513d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
514d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	std::ostringstream stream;
515d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
516d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	while ((token->type != '\n') && (token->type != Token::LAST))
517d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
518d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		stream << *token;
519d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->lex(token);
520d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
521d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mDirectiveHandler->handleError(token->location, stream.str());
522d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
523d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
524d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Parses pragma of form: #pragma name[(value)].
525d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parsePragma(Token* token)
526d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
527d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_PRAGMA);
528d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
529d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	enum State
530d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
531d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		PRAGMA_NAME,
532d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		LEFT_PAREN,
533d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		PRAGMA_VALUE,
534d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		RIGHT_PAREN
535d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	};
536d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
537d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool valid = true;
538d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	std::string name, value;
539d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int state = PRAGMA_NAME;
540d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
541d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
542d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	while ((token->type != '\n') && (token->type != Token::LAST))
543d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
544d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		switch(state++)
545d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
546d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case PRAGMA_NAME:
547d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			name = token->text;
548d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			valid = valid && (token->type == Token::IDENTIFIER);
549d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
550d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case LEFT_PAREN:
551d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			valid = valid && (token->type == '(');
552d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
553d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case PRAGMA_VALUE:
554d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			value = token->text;
555d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			valid = valid && (token->type == Token::IDENTIFIER);
556d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
557d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case RIGHT_PAREN:
558d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			valid = valid && (token->type == ')');
559d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
560d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		default:
561d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			valid = false;
562d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
563d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
564d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->lex(token);
565d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
566d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
567d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	valid = valid && ((state == PRAGMA_NAME) ||     // Empty pragma.
568d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	                  (state == LEFT_PAREN) ||      // Without value.
569d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	                  (state == RIGHT_PAREN + 1));  // With value.
570d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (!valid)
571d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
572d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA,
573d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, name);
574d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
575d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.
576d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
577d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDirectiveHandler->handlePragma(token->location, name, value);
578d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
579d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
580d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
581d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseExtension(Token* token)
582d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
583d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_EXTENSION);
584d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
585d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	enum State
586d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
587d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		EXT_NAME,
588d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		COLON,
589d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		EXT_BEHAVIOR
590d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	};
591d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
592d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool valid = true;
593d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	std::string name, behavior;
594d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int state = EXT_NAME;
595d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
596d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
597d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	while ((token->type != '\n') && (token->type != Token::LAST))
598d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
599d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		switch (state++)
600d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
601d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case EXT_NAME:
602d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && (token->type != Token::IDENTIFIER))
603d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
604d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME,
605d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
606d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
607d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
608d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid) name = token->text;
609d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
610d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case COLON:
611d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && (token->type != ':'))
612d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
613d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
614d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
615d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
616d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
617d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
618d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case EXT_BEHAVIOR:
619d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && (token->type != Token::IDENTIFIER))
620d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
621d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR,
622d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
623d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
624d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
625d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid) behavior = token->text;
626d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
627d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		default:
628d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid)
629d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
630d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
631d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
632d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
633d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
634d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
635d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
636d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->lex(token);
637d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
638d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (valid && (state != EXT_BEHAVIOR + 1))
639d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
640d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE,
641d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
642d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		valid = false;
643d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
644d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (valid)
645d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDirectiveHandler->handleExtension(token->location, name, behavior);
646d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
647d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
648d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseVersion(Token* token)
649d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
650d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_VERSION);
651d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
652d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (mPastFirstStatement)
653d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
654d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT,
655d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
656d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
657d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return;
658d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
659d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
660d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	enum State
661d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
662d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		VERSION_NUMBER,
663d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		VERSION_PROFILE,
664d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		VERSION_ENDLINE
665d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	};
666d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
667d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool valid = true;
668d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int version = 0;
669d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int state = VERSION_NUMBER;
670d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
671d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
672d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	while (valid && (token->type != '\n') && (token->type != Token::LAST))
673d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
674d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		switch (state)
675d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
676d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case VERSION_NUMBER:
677d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (token->type != Token::CONST_INT)
678d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
679d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER,
680d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
681d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
682d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
683d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && !token->iValue(&version))
684d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
685d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
686d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
687d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
688d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
689d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid)
690d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
691d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
692d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
693d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
694d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case VERSION_PROFILE:
695d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (token->type != Token::IDENTIFIER || token->text != "es")
696d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
697d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
698d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
699d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
700d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
701d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			state = VERSION_ENDLINE;
702d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
703d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		default:
704d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
705d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			                     token->location, token->text);
706d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			valid = false;
707d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
708d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
709d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
710d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->lex(token);
711d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
712d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
713d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (valid && (state != VERSION_ENDLINE))
714d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
715d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
716d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
717d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		valid = false;
718d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
719d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
720d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (valid)
721d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
722d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDirectiveHandler->handleVersion(token->location, version);
723d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
724d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
725d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
726d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseLine(Token* token)
727d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
728d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert(getDirective(token) == DIRECTIVE_LINE);
729d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
730d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	enum State
731d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
732d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		LINE_NUMBER,
733d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		FILE_NUMBER
734d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	};
735d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
736d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool valid = true;
737d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int line = 0, file = 0;
738d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int state = LINE_NUMBER;
739d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
740d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
741d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	macroExpander.lex(token);
742d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	while ((token->type != '\n') && (token->type != Token::LAST))
743d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
744d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		switch (state++)
745d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
746d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case LINE_NUMBER:
747d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && (token->type != Token::CONST_INT))
748d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
749d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER,
750d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
751d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
752d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
753d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && !token->iValue(&line))
754d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
755d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
756d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
757d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
758d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
759d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
760d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FILE_NUMBER:
761d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && (token->type != Token::CONST_INT))
762d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
763d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER,
764d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
765d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
766d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
767d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid && !token->iValue(&file))
768d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
769d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
770d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
771d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
772d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
773d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
774d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		default:
775d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if (valid)
776d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
777d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
778d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				                     token->location, token->text);
779d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				valid = false;
780d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
781d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
782d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
783d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		macroExpander.lex(token);
784d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
785d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
786d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
787d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
788d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE,
789d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
790d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		valid = false;
791d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
792d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (valid)
793d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
794d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mTokenizer->setLineNumber(line);
795d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file);
796d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
797d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
798d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
799d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensbool DirectiveParser::skipping() const
800d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
801d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (mConditionalStack.empty()) return false;
802d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
803d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	const ConditionalBlock& block = mConditionalStack.back();
804d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	return block.skipBlock || block.skipGroup;
805d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
806d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
807d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid DirectiveParser::parseConditionalIf(Token* token)
808d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
809d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	ConditionalBlock block;
810d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	block.type = token->text;
811d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	block.location = token->location;
812d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
813d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (skipping())
814d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
815d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// This conditional block is inside another conditional group
816d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// which is skipped. As a consequence this whole block is skipped.
817d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// Be careful not to parse the conditional expression that might
818d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		// emit a diagnostic.
819d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
820d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		block.skipBlock = true;
821d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
822d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	else
823d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
824d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		DirectiveType directive = getDirective(token);
825d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
826d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		int expression = 0;
827d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		switch (directive)
828d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
829d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case DIRECTIVE_IF:
830d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			expression = parseExpressionIf(token);
831d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
832d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case DIRECTIVE_IFDEF:
833d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			expression = parseExpressionIfdef(token);
834d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
835d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case DIRECTIVE_IFNDEF:
836d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
837d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
838d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		default:
839d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			assert(false);
840d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
841d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
842d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		block.skipGroup = expression == 0;
843d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		block.foundValidGroup = expression != 0;
844d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
845d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mConditionalStack.push_back(block);
846d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
847d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
848d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensint DirectiveParser::parseExpressionIf(Token* token)
849d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
850d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert((getDirective(token) == DIRECTIVE_IF) ||
851d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	       (getDirective(token) == DIRECTIVE_ELIF));
852d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
853d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true);
854d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	ExpressionParser expressionParser(&macroExpander, mDiagnostics);
855d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
856d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int expression = 0;
857d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	macroExpander.lex(token);
858d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	expressionParser.parse(token, &expression);
859d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
860d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// Check if there are tokens after #if expression.
861d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (!isEOD(token))
862d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
863d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
864d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
865d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
866d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
867d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
868d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	return expression;
869d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
870d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
871d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensint DirectiveParser::parseExpressionIfdef(Token* token)
872d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
873d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	assert((getDirective(token) == DIRECTIVE_IFDEF) ||
874d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		   (getDirective(token) == DIRECTIVE_IFNDEF));
875d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
876d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
877d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (token->type != Token::IDENTIFIER)
878d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
879d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
880d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
881d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
882d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return 0;
883d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
884d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
885d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	MacroSet::const_iterator iter = mMacroSet->find(token->text);
886d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	int expression = iter != mMacroSet->end() ? 1 : 0;
887d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
888d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	// Check if there are tokens after #ifdef expression.
889d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	mTokenizer->lex(token);
890d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	if (!isEOD(token))
891d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
892d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
893d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		                     token->location, token->text);
894d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		skipUntilEOD(mTokenizer, token);
895d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
896d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	return expression;
897d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
898d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
899d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}  // namespace pp
900