Commit 3a01d1bc by alokp@chromium.org

Preparation for macro expansion.

Review URL: http://codereview.appspot.com/4919045 git-svn-id: https://angleproject.googlecode.com/svn/trunk@741 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent e4eb9911
......@@ -6,15 +6,107 @@
#include "Context.h"
#include <algorithm>
#include <sstream>
#include "compiler/debug.h"
#include "stl_utils.h"
#include "token_type.h"
namespace pp
{
Context::Context(int count, const char* const string[], const int length[],
TokenVector* output)
: input(count, string, length),
output(output),
lexer(NULL)
Context::Context()
: mLexer(NULL),
mInput(NULL),
mOutput(NULL)
{
}
Context::~Context()
{
destroyLexer();
}
bool Context::init()
{
return initLexer();
// TODO(alokp): Define built-in macros here so that we do not need to
// define them everytime in process().
}
bool Context::process(int count,
const char* const string[],
const int length[],
TokenVector* output)
{
ASSERT((count >=0) && (string != NULL) && (output != NULL));
// Setup.
mInput = new Input(count, string, length);
mOutput = output;
defineBuiltInMacro("GL_ES", 1);
// Parse.
bool success = parse();
// Cleanup.
reset();
return success;
}
bool Context::defineMacro(pp::Token::Location location,
pp::Macro::Type type,
std::string* identifier,
pp::Macro::ParameterVector* parameters,
pp::TokenVector* replacements)
{
// TODO(alokp): Check for reserved macro names and duplicate macros.
mMacros[*identifier] = new Macro(type, identifier, parameters, replacements);
return true;
}
bool Context::undefineMacro(const std::string* identifier)
{
MacroSet::iterator iter = mMacros.find(*identifier);
if (iter == mMacros.end())
{
// TODO(alokp): Report error.
return false;
}
mMacros.erase(iter);
return true;
}
bool Context::isMacroDefined(const std::string* identifier)
{
return mMacros.find(*identifier) != mMacros.end();
}
// Reset to initialized state.
void Context::reset()
{
std::for_each(mMacros.begin(), mMacros.end(), DeleteSecond());
mMacros.clear();
delete mInput;
mInput = NULL;
mOutput = NULL;
}
void Context::defineBuiltInMacro(const std::string& identifier, int value)
{
std::ostringstream stream;
stream << value;
Token* token = new Token(0, INT_CONSTANT, new std::string(stream.str()));
TokenVector* replacements = new pp::TokenVector(1, token);
mMacros[identifier] = new Macro(Macro::kTypeObj,
new std::string(identifier),
NULL,
replacements);
}
} // namespace pp
......
......@@ -7,6 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_CONTEXT_H_
#define COMPILER_PREPROCESSOR_CONTEXT_H_
#include <map>
#include "common/angleutils.h"
#include "Input.h"
#include "Macro.h"
#include "Token.h"
......@@ -14,16 +17,42 @@
namespace pp
{
struct Context
class Context
{
Context(int count, const char* const string[], const int length[],
TokenVector* output);
Input input;
TokenVector* output;
void* lexer; // Lexer handle.
MacroSet macros; // Defined macros.
public:
Context();
~Context();
bool init();
bool process(int count, const char* const string[], const int length[],
TokenVector* output);
void* lexer() { return mLexer; }
int readInput(char* buf, int maxSize);
TokenVector* output() { return mOutput; }
bool defineMacro(pp::Token::Location location,
pp::Macro::Type type,
std::string* identifier,
pp::Macro::ParameterVector* parameters,
pp::TokenVector* replacements);
bool undefineMacro(const std::string* identifier);
bool isMacroDefined(const std::string* identifier);
private:
DISALLOW_COPY_AND_ASSIGN(Context);
typedef std::map<std::string, Macro*> MacroSet;
void reset();
bool initLexer();
void destroyLexer();
void defineBuiltInMacro(const std::string& identifier, int value);
bool parse();
void* mLexer; // Lexer handle.
Input* mInput;
TokenVector* mOutput;
MacroSet mMacros; // Defined macros.
};
} // namespace pp
......
//
// 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 "Macro.h"
#include <algorithm>
#include "stl_utils.h"
namespace pp
{
Macro::Macro(Type type,
std::string* identifier,
ParameterVector* parameters,
TokenVector* replacements)
: mType(type),
mIdentifier(identifier),
mParameters(parameters),
mReplacements(replacements)
{
}
Macro::~Macro()
{
delete mIdentifier;
if (mParameters)
{
std::for_each(mParameters->begin(), mParameters->end(), Delete());
delete mParameters;
}
if (mReplacements)
{
std::for_each(mReplacements->begin(), mReplacements->end(), Delete());
delete mReplacements;
}
}
} // namespace pp
......@@ -7,27 +7,45 @@
#ifndef COMPILER_PREPROCESSOR_MACRO_H_
#define COMPILER_PREPROCESSOR_MACRO_H_
#include <map>
#include <string>
#include <vector>
#include "common/angleutils.h"
#include "Token.h"
namespace pp
{
struct Macro
class Macro
{
public:
enum Type
{
kTypeObj,
kTypeFunc
};
Type type;
std::string identifier;
TokenVector parameters;
TokenVector replacements;
typedef std::vector<std::string*> ParameterVector;
// Takes ownership of pointer parameters.
Macro(Type type,
std::string* identifier,
ParameterVector* parameters,
TokenVector* replacements);
~Macro();
Type type() const { return mType; }
const std::string* identifier() const { return mIdentifier; }
const ParameterVector* parameters() const { return mParameters; }
const TokenVector* replacements() const { return mReplacements; }
private:
DISALLOW_COPY_AND_ASSIGN(Macro);
Type mType;
std::string* mIdentifier;
ParameterVector* mParameters;
TokenVector* mReplacements;
};
typedef std::map<std::string, Macro> MacroSet;
} // namespace pp
#endif COMPILER_PREPROCESSOR_MACRO_H_
......
......@@ -6,12 +6,30 @@
#include "Preprocessor.h"
#include <algorithm>
#include "compiler/debug.h"
#include "Context.h"
#include "stl_utils.h"
namespace pp
{
Preprocessor::Preprocessor() : mContext(NULL)
{
}
Preprocessor::~Preprocessor()
{
delete mContext;
}
bool Preprocessor::init()
{
mContext = new Context;
return mContext->init();
}
bool Preprocessor::process(int count,
const char* const string[],
const int length[])
......@@ -20,22 +38,14 @@ bool Preprocessor::process(int count,
if ((count < 0) || (string == NULL))
return false;
clearResults();
Context context(count, string, length, &mTokens);
if (!initLexer(&context))
return false;
bool success = parse(&context);
reset();
destroyLexer(&context);
return success;
return mContext->process(count, string, length, &mTokens);
}
void Preprocessor::clearResults()
void Preprocessor::reset()
{
for (TokenVector::iterator i = mTokens.begin(); i != mTokens.end(); ++i)
delete (*i);
std::for_each(mTokens.begin(), mTokens.end(), Delete());
mTokens.clear();
}
......
......@@ -13,27 +13,27 @@
namespace pp
{
struct Context;
class Context;
class Preprocessor
{
public:
Preprocessor() { }
Preprocessor();
~Preprocessor();
bool process(int count, const char* const string[], const int length[]);
bool init();
bool process(int count, const char* const string[], const int length[]);
TokenIterator begin() const { return mTokens.begin(); }
TokenIterator end() const { return mTokens.end(); }
private:
DISALLOW_COPY_AND_ASSIGN(Preprocessor);
static bool initLexer(Context* context);
static void destroyLexer(Context* context);
static bool parse(Context* context);
void clearResults();
// Reset to initialized state.
void reset();
Context* mContext;
TokenVector mTokens; // Output.
};
......
......@@ -10,6 +10,8 @@
#include <string>
#include <vector>
#include "common/angleutils.h"
namespace pp
{
......@@ -29,6 +31,8 @@ class Token
const std::string* value() const { return mValue; }
private:
DISALLOW_COPY_AND_ASSIGN(Token);
Location mLocation;
int mType;
std::string* mValue;
......
......@@ -26,7 +26,6 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
#include "compiler/debug.h"
#include "Context.h"
#include "pp_tab.h"
#include "Preprocessor.h"
#define YY_USER_ACTION \
do { \
......@@ -36,9 +35,7 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
} while(0);
#define YY_INPUT(buf, result, maxSize) \
result = readInput(yyextra, buf, maxSize);
static int readInput(pp::Context* context, char* buf, int maxSize);
result = yyextra->readInput(buf, maxSize);
%}
%option noyywrap nounput never-interactive
......@@ -110,24 +107,23 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
%%
int readInput(pp::Context* context, char* buf, int maxSize)
{
yyscan_t lexer = context->lexer;
ASSERT(lexer);
namespace pp {
int Context::readInput(char* buf, int maxSize)
{
int nread = YY_NULL;
while (!context->input.eof() &&
(context->input.error() == pp::Input::kErrorNone) &&
while (!mInput->eof() &&
(mInput->error() == pp::Input::kErrorNone) &&
(nread == YY_NULL))
{
int line = 0, file = 0;
pp::Token::decodeLocation(yyget_lineno(lexer), &line, &file);
file = context->input.stringIndex();
yyset_lineno(pp::Token::encodeLocation(line, file), lexer);
pp::Token::decodeLocation(yyget_lineno(mLexer), &line, &file);
file = mInput->stringIndex();
yyset_lineno(pp::Token::encodeLocation(line, file), mLexer);
nread = context->input.read(buf, maxSize);
nread = mInput->read(buf, maxSize);
if (context->input.error() == pp::Input::kErrorUnexpectedEOF)
if (mInput->error() == pp::Input::kErrorUnexpectedEOF)
{
// TODO(alokp): Report error.
}
......@@ -135,27 +131,23 @@ int readInput(pp::Context* context, char* buf, int maxSize)
return nread;
}
namespace pp {
bool Preprocessor::initLexer(Context* context)
bool Context::initLexer()
{
ASSERT(context->lexer == NULL);
ASSERT(mLexer == NULL);
yyscan_t lexer = 0;
if (yylex_init_extra(context, &lexer))
if (yylex_init_extra(this, &mLexer))
return false;
context->lexer = lexer;
yyrestart(0, lexer);
yyrestart(0, mLexer);
return true;
}
void Preprocessor::destroyLexer(Context* context)
void Context::destroyLexer()
{
ASSERT(context->lexer);
ASSERT(mLexer);
yylex_destroy(context->lexer);
context->lexer = 0;
yylex_destroy(mLexer);
mLexer = NULL;
}
} // namespace pp
......
......@@ -23,9 +23,8 @@ WHICH GENERATES THE GLSL ES PARSER.
// This file is auto-generated by generate_glslang_parser.sh. DO NOT EDIT!
#include "Context.h"
#include "Preprocessor.h"
#define YYLEX_PARAM context->lexer
#define YYLEX_PARAM context->lexer()
#define YYDEBUG 1
%}
......@@ -48,14 +47,6 @@ static void yyerror(YYLTYPE* llocp,
pp::Context* context,
const char* reason);
static void defineMacro(pp::Context* context,
YYLTYPE* llocp,
pp::Macro::Type type,
const std::string* identifier,
std::vector<std::string*>* parameters,
pp::TokenVector* replacements);
static void undefineMacro(pp::Context* context, const std::string* identifier);
static bool isMacroDefined(pp::Context* context, const std::string* identifier);
static void pushConditionalBlock(pp::Context* context, bool condition);
static void popConditionalBlock(pp::Context* context);
%}
......@@ -79,7 +70,7 @@ input
line
: text_line {
// TODO(alokp): Expand macros.
pp::TokenVector* out = context->output;
pp::TokenVector* out = context->output();
out->insert(out->end(), $1->begin(), $1->end());
delete $1;
}
......@@ -94,22 +85,22 @@ text_line
control_line
: HASH '\n'
| HASH_DEFINE_OBJ IDENTIFIER replacement_token_list '\n' {
defineMacro(context, & @2, pp::Macro::kTypeObj, $2, NULL, $3);
context->defineMacro(@2.first_line, pp::Macro::kTypeObj, $2, NULL, $3);
}
| HASH_DEFINE_FUNC IDENTIFIER '(' parameter_list ')' replacement_token_list '\n' {
defineMacro(context, & @2, pp::Macro::kTypeFunc, $2, $4, $6);
context->defineMacro(@2.first_line, pp::Macro::kTypeFunc, $2, $4, $6);
}
| HASH_UNDEF IDENTIFIER '\n' {
undefineMacro(context, $2);
context->undefineMacro($2);
}
| HASH_IF conditional_token_list '\n' {
pushConditionalBlock(context, $2 ? true : false);
}
| HASH_IFDEF IDENTIFIER '\n' {
pushConditionalBlock(context, isMacroDefined(context, $2));
pushConditionalBlock(context, context->isMacroDefined($2));
}
| HASH_IFNDEF IDENTIFIER '\n' {
pushConditionalBlock(context, !isMacroDefined(context, $2));
pushConditionalBlock(context, !context->isMacroDefined($2));
}
| HASH_ELIF conditional_token_list '\n' {
}
......@@ -223,24 +214,6 @@ void yyerror(YYLTYPE* llocp, pp::Context* context, const char* reason)
{
}
void defineMacro(pp::Context* context,
YYLTYPE* llocp,
pp::Macro::Type type,
const std::string* identifier,
std::vector<std::string*>* parameters,
pp::TokenVector* replacements)
{
}
void undefineMacro(pp::Context* context, const std::string* identifier)
{
}
bool isMacroDefined(pp::Context* context, const std::string* identifier)
{
return false;
}
void pushConditionalBlock(pp::Context* context, bool condition)
{
}
......@@ -250,10 +223,10 @@ void popConditionalBlock(pp::Context* context)
}
namespace pp {
bool Preprocessor::parse(Context* context)
bool Context::parse()
{
yydebug = 1;
return yyparse(context) == 0 ? true : false;
return yyparse(this) == 0 ? true : false;
}
} // namespace pp
......@@ -571,7 +571,6 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
#include "compiler/debug.h"
#include "Context.h"
#include "pp_tab.h"
#include "Preprocessor.h"
#define YY_USER_ACTION \
do { \
......@@ -581,9 +580,7 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
} while(0);
#define YY_INPUT(buf, result, maxSize) \
result = readInput(yyextra, buf, maxSize);
static int readInput(pp::Context* context, char* buf, int maxSize);
result = yyextra->readInput(buf, maxSize);
#define INITIAL 0
......@@ -2224,24 +2221,23 @@ void ppfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
int readInput(pp::Context* context, char* buf, int maxSize)
{
yyscan_t lexer = context->lexer;
ASSERT(lexer);
namespace pp {
int Context::readInput(char* buf, int maxSize)
{
int nread = YY_NULL;
while (!context->input.eof() &&
(context->input.error() == pp::Input::kErrorNone) &&
while (!mInput->eof() &&
(mInput->error() == pp::Input::kErrorNone) &&
(nread == YY_NULL))
{
int line = 0, file = 0;
pp::Token::decodeLocation(ppget_lineno(lexer), &line, &file);
file = context->input.stringIndex();
ppset_lineno(pp::Token::encodeLocation(line, file),lexer);
pp::Token::decodeLocation(ppget_lineno(mLexer), &line, &file);
file = mInput->stringIndex();
ppset_lineno(pp::Token::encodeLocation(line, file),mLexer);
nread = context->input.read(buf, maxSize);
nread = mInput->read(buf, maxSize);
if (context->input.error() == pp::Input::kErrorUnexpectedEOF)
if (mInput->error() == pp::Input::kErrorUnexpectedEOF)
{
// TODO(alokp): Report error.
}
......@@ -2249,27 +2245,23 @@ int readInput(pp::Context* context, char* buf, int maxSize)
return nread;
}
namespace pp {
bool Preprocessor::initLexer(Context* context)
bool Context::initLexer()
{
ASSERT(context->lexer == NULL);
ASSERT(mLexer == NULL);
yyscan_t lexer = 0;
if (pplex_init_extra(context,&lexer))
if (pplex_init_extra(this,&mLexer))
return false;
context->lexer = lexer;
pprestart(0,lexer);
pprestart(0,mLexer);
return true;
}
void Preprocessor::destroyLexer(Context* context)
void Context::destroyLexer()
{
ASSERT(context->lexer);
ASSERT(mLexer);
pplex_destroy(context->lexer);
context->lexer = 0;
pplex_destroy(mLexer);
mLexer = NULL;
}
} // namespace pp
......
......@@ -133,9 +133,8 @@
// This file is auto-generated by generate_glslang_parser.sh. DO NOT EDIT!
#include "Context.h"
#include "Preprocessor.h"
#define YYLEX_PARAM context->lexer
#define YYLEX_PARAM context->lexer()
#define YYDEBUG 1
......@@ -197,14 +196,6 @@ static void yyerror(YYLTYPE* llocp,
pp::Context* context,
const char* reason);
static void defineMacro(pp::Context* context,
YYLTYPE* llocp,
pp::Macro::Type type,
const std::string* identifier,
std::vector<std::string*>* parameters,
pp::TokenVector* replacements);
static void undefineMacro(pp::Context* context, const std::string* identifier);
static bool isMacroDefined(pp::Context* context, const std::string* identifier);
static void pushConditionalBlock(pp::Context* context, bool condition);
static void popConditionalBlock(pp::Context* context);
......@@ -517,13 +508,13 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
0, 74, 74, 76, 80, 86, 90, 91, 95, 96,
99, 102, 105, 108, 111, 114, 116, 118, 121, 122,
123, 124, 125, 129, 130, 134, 138, 145, 147, 149,
153, 154, 158, 165, 169, 176, 179, 182, 185, 188,
194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
214, 215, 216, 217
0, 65, 65, 67, 71, 77, 81, 82, 86, 87,
90, 93, 96, 99, 102, 105, 107, 109, 112, 113,
114, 115, 116, 120, 121, 125, 129, 136, 138, 140,
144, 145, 149, 156, 160, 167, 170, 173, 176, 179,
185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208
};
#endif
......@@ -1552,7 +1543,7 @@ yyreduce:
{
// TODO(alokp): Expand macros.
pp::TokenVector* out = context->output;
pp::TokenVector* out = context->output();
out->insert(out->end(), (yyvsp[(1) - (1)].tlist)->begin(), (yyvsp[(1) - (1)].tlist)->end());
delete (yyvsp[(1) - (1)].tlist);
;}
......@@ -1571,21 +1562,21 @@ yyreduce:
case 9:
{
defineMacro(context, & (yylsp[(2) - (4)]), pp::Macro::kTypeObj, (yyvsp[(2) - (4)].sval), NULL, (yyvsp[(3) - (4)].tlist));
context->defineMacro((yylsp[(2) - (4)]).first_line, pp::Macro::kTypeObj, (yyvsp[(2) - (4)].sval), NULL, (yyvsp[(3) - (4)].tlist));
;}
break;
case 10:
{
defineMacro(context, & (yylsp[(2) - (7)]), pp::Macro::kTypeFunc, (yyvsp[(2) - (7)].sval), (yyvsp[(4) - (7)].slist), (yyvsp[(6) - (7)].tlist));
context->defineMacro((yylsp[(2) - (7)]).first_line, pp::Macro::kTypeFunc, (yyvsp[(2) - (7)].sval), (yyvsp[(4) - (7)].slist), (yyvsp[(6) - (7)].tlist));
;}
break;
case 11:
{
undefineMacro(context, (yyvsp[(2) - (3)].sval));
context->undefineMacro((yyvsp[(2) - (3)].sval));
;}
break;
......@@ -1599,14 +1590,14 @@ yyreduce:
case 13:
{
pushConditionalBlock(context, isMacroDefined(context, (yyvsp[(2) - (3)].sval)));
pushConditionalBlock(context, context->isMacroDefined((yyvsp[(2) - (3)].sval)));
;}
break;
case 14:
{
pushConditionalBlock(context, !isMacroDefined(context, (yyvsp[(2) - (3)].sval)));
pushConditionalBlock(context, !context->isMacroDefined((yyvsp[(2) - (3)].sval)));
;}
break;
......@@ -2083,24 +2074,6 @@ void yyerror(YYLTYPE* llocp, pp::Context* context, const char* reason)
{
}
void defineMacro(pp::Context* context,
YYLTYPE* llocp,
pp::Macro::Type type,
const std::string* identifier,
std::vector<std::string*>* parameters,
pp::TokenVector* replacements)
{
}
void undefineMacro(pp::Context* context, const std::string* identifier)
{
}
bool isMacroDefined(pp::Context* context, const std::string* identifier)
{
return false;
}
void pushConditionalBlock(pp::Context* context, bool condition)
{
}
......@@ -2110,10 +2083,10 @@ void popConditionalBlock(pp::Context* context)
}
namespace pp {
bool Preprocessor::parse(Context* context)
bool Context::parse()
{
yydebug = 1;
return yyparse(context) == 0 ? true : false;
return yyparse(this) == 0 ? true : false;
}
} // namespace pp
......
//
// 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.
//
// stl_utils.h: Common STL utilities.
#ifndef COMMON_STLUTILS_H_
#define COMMON_STLUTILS_H_
namespace pp
{
struct Delete
{
template<class T>
void operator() (T x) { delete x; }
};
struct DeleteSecond
{
template<class A, class B>
void operator() (std::pair<A, B>& x) { delete x.second; }
};
} // namespace pp
#endif // COMMON_STLUTILS_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment