//
// 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::IDENTIFIER:
          {
            static const int kMaxIdentifierLength = 256;
            if (token->text.size() > kMaxIdentifierLength)
            {
                // Do not mark the token as invalid.
                // Just emit the diagnostic and clamp string length.
                mImpl->diagnostics->report(Diagnostics::IDENTIFIER_OVERFLOW,
                                           token->location, token->text);
                token->text.erase(kMaxIdentifierLength);
            }
            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

