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 19 namespace pp 20 { 21 22 struct 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 40 Preprocessor::Preprocessor(Diagnostics *diagnostics, 41 DirectiveHandler *directiveHandler) 42 { 43 mImpl = new PreprocessorImpl(diagnostics, directiveHandler); 44 } 45 46 Preprocessor::~Preprocessor() 47 { 48 delete mImpl; 49 } 50 51 bool 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 66 void 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 84 void 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 113 void Preprocessor::setMaxTokenSize(size_t maxTokenSize) 114 { 115 mImpl->tokenizer.setMaxTokenSize(maxTokenSize); 116 } 117 118 } // namespace pp 119