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(¯oExpander, 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