Edit

kc3-lang/angle/src/compiler/preprocessor/Preprocessor.cpp

Branch :

  • Show log

    Commit

  • Author : daniel@transgaming.com
    Date : 2012-10-26 18:58:24
    Hash : b401a92b
    Message : Move the new preprocessor out of the 'new' directory. TRAC #21966 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@1326 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/preprocessor/Preprocessor.cpp
  • //
    // Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include "Preprocessor.h"
    
    #include <cassert>
    #include <sstream>
    
    #include "Diagnostics.h"
    #include "DirectiveParser.h"
    #include "Macro.h"
    #include "MacroExpander.h"
    #include "Token.h"
    #include "Tokenizer.h"
    
    namespace pp
    {
    
    struct PreprocessorImpl
    {
        Diagnostics* diagnostics;
        MacroSet macroSet;
        Tokenizer tokenizer;
        DirectiveParser directiveParser;
        MacroExpander macroExpander;
    
        PreprocessorImpl(Diagnostics* diag,
                         DirectiveHandler* directiveHandler) :
            diagnostics(diag),
            tokenizer(diag),
            directiveParser(&tokenizer, &macroSet, diag, directiveHandler),
            macroExpander(&directiveParser, &macroSet, diag)
        {
        }
    };
    
    Preprocessor::Preprocessor(Diagnostics* diagnostics,
                               DirectiveHandler* directiveHandler)
    {
        mImpl = new PreprocessorImpl(diagnostics, directiveHandler);
    }
    
    Preprocessor::~Preprocessor()
    {
        delete mImpl;
    }
    
    bool Preprocessor::init(int count,
                            const char* const string[],
                            const int length[])
    {
        static const int kGLSLVersion = 100;
    
        // Add standard pre-defined macros.
        predefineMacro("__LINE__", 0);
        predefineMacro("__FILE__", 0);
        predefineMacro("__VERSION__", kGLSLVersion);
        predefineMacro("GL_ES", 1);
    
        return mImpl->tokenizer.init(count, string, length);
    }
    
    void Preprocessor::predefineMacro(const char* name, int value)
    {
        std::ostringstream stream;
        stream << value;
    
        Token token;
        token.type = Token::CONST_INT;
        token.text = stream.str();
    
        Macro macro;
        macro.predefined = true;
        macro.type = Macro::kTypeObj;
        macro.name = name;
        macro.replacements.push_back(token);
    
        mImpl->macroSet[name] = macro;
    }
    
    void Preprocessor::lex(Token* token)
    {
        bool validToken = false;
        while (!validToken)
        {
            mImpl->macroExpander.lex(token);
            switch (token->type)
            {
              // We should not be returning internal preprocessing tokens.
              // Convert preprocessing tokens to compiler tokens or report
              // diagnostics.
              case Token::PP_HASH:
                assert(false);
                break;
              case Token::CONST_INT:
              {
                int val = 0;
                if (!token->iValue(&val))
                {
                    // Do not mark the token as invalid.
                    // Just emit the diagnostic and reset value to 0.
                    mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
                                               token->location, token->text);
                    token->text.assign("0");
                }
                validToken = true;
                break;
              }
              case Token::CONST_FLOAT:
              {
                float val = 0;
                if (!token->fValue(&val))
                {
                    // Do not mark the token as invalid.
                    // Just emit the diagnostic and reset value to 0.0.
                    mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
                                               token->location, token->text);
                    token->text.assign("0.0");
                }
                validToken = true;
                break;
              }
              case Token::PP_NUMBER:
                mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
                                           token->location, token->text);
                break;
              case Token::PP_OTHER:
                mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER,
                                           token->location, token->text);
                break;
              default:
                validToken = true;
                break;
            }
        }
    }
    
    }  // namespace pp