1// 2// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6 7#include "Preprocessor.h" 8 9#include <cassert> 10#include <sstream> 11 12#include "DiagnosticsBase.h" 13#include "DirectiveParser.h" 14#include "Macro.h" 15#include "MacroExpander.h" 16#include "Token.h" 17#include "Tokenizer.h" 18 19namespace pp 20{ 21 22struct PreprocessorImpl 23{ 24 Diagnostics *diagnostics; 25 MacroSet macroSet; 26 Tokenizer tokenizer; 27 DirectiveParser directiveParser; 28 MacroExpander macroExpander; 29 30 PreprocessorImpl(Diagnostics *diag, 31 DirectiveHandler *directiveHandler) 32 : diagnostics(diag), 33 tokenizer(diag), 34 directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), 35 macroExpander(&directiveParser, ¯oSet, diag) 36 { 37 } 38}; 39 40Preprocessor::Preprocessor(Diagnostics *diagnostics, 41 DirectiveHandler *directiveHandler) 42{ 43 mImpl = new PreprocessorImpl(diagnostics, directiveHandler); 44} 45 46Preprocessor::~Preprocessor() 47{ 48 delete mImpl; 49} 50 51bool Preprocessor::init(size_t count, 52 const char * const string[], 53 const int length[]) 54{ 55 static const int kGLSLVersion = 100; 56 57 // Add standard pre-defined macros. 58 predefineMacro("__LINE__", 0); 59 predefineMacro("__FILE__", 0); 60 predefineMacro("__VERSION__", kGLSLVersion); 61 predefineMacro("GL_ES", 1); 62 63 return mImpl->tokenizer.init(count, string, length); 64} 65 66void Preprocessor::predefineMacro(const char *name, int value) 67{ 68 std::ostringstream stream; 69 stream << value; 70 71 Token token; 72 token.type = Token::CONST_INT; 73 token.text = stream.str(); 74 75 Macro macro; 76 macro.predefined = true; 77 macro.type = Macro::kTypeObj; 78 macro.name = name; 79 macro.replacements.push_back(token); 80 81 mImpl->macroSet[name] = macro; 82} 83 84void Preprocessor::lex(Token *token) 85{ 86 bool validToken = false; 87 while (!validToken) 88 { 89 mImpl->macroExpander.lex(token); 90 switch (token->type) 91 { 92 // We should not be returning internal preprocessing tokens. 93 // Convert preprocessing tokens to compiler tokens or report 94 // diagnostics. 95 case Token::PP_HASH: 96 assert(false); 97 break; 98 case Token::PP_NUMBER: 99 mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER, 100 token->location, token->text); 101 break; 102 case Token::PP_OTHER: 103 mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER, 104 token->location, token->text); 105 break; 106 default: 107 validToken = true; 108 break; 109 } 110 } 111} 112 113void Preprocessor::setMaxTokenSize(size_t maxTokenSize) 114{ 115 mImpl->tokenizer.setMaxTokenSize(maxTokenSize); 116} 117 118} // namespace pp 119