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::setMaxTokenLength(size_t maxLength) 85 { 86 mImpl->tokenizer.setMaxTokenLength(maxLength); 87 } 88 89 void Preprocessor::lex(Token* token) 90 { 91 bool validToken = false; 92 while (!validToken) 93 { 94 mImpl->macroExpander.lex(token); 95 switch (token->type) 96 { 97 // We should not be returning internal preprocessing tokens. 98 // Convert preprocessing tokens to compiler tokens or report 99 // diagnostics. 100 case Token::PP_HASH: 101 assert(false); 102 break; 103 case Token::PP_NUMBER: 104 mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER, 105 token->location, token->text); 106 break; 107 case Token::PP_OTHER: 108 mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER, 109 token->location, token->text); 110 break; 111 default: 112 validToken = true; 113 break; 114 } 115 } 116 } 117 118 } // namespace pp 119 120