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::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