Home | History | Annotate | Download | only in preprocessor
      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, &macroSet, diag, directiveHandler),
     35         macroExpander(&directiveParser, &macroSet, 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