Commit 16efbbae by alokp@chromium.org

Complete implementation for handling #define directive.

Review URL: http://codereview.appspot.com/4963062 git-svn-id: https://angleproject.googlecode.com/svn/trunk@752 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 8a4dad60
...@@ -13,6 +13,21 @@ ...@@ -13,6 +13,21 @@
#include "stl_utils.h" #include "stl_utils.h"
#include "token_type.h" #include "token_type.h"
static bool isMacroNameReserved(const std::string* name)
{
ASSERT(name);
// Names prefixed with "GL_" are reserved.
if (name->substr(0, 3) == "GL_")
return true;
// Names containing two consecutive underscores are reserved.
if (name->find("__") != std::string::npos)
return true;
return false;
}
namespace pp namespace pp
{ {
...@@ -58,18 +73,29 @@ bool Context::process(int count, ...@@ -58,18 +73,29 @@ bool Context::process(int count,
bool Context::defineMacro(pp::Token::Location location, bool Context::defineMacro(pp::Token::Location location,
pp::Macro::Type type, pp::Macro::Type type,
std::string* identifier, std::string* name,
pp::Macro::ParameterVector* parameters, pp::TokenVector* parameters,
pp::TokenVector* replacements) pp::TokenVector* replacements)
{ {
// TODO(alokp): Check for reserved macro names and duplicate macros. std::auto_ptr<Macro> macro(new Macro(type, name, parameters, replacements));
mMacros[*identifier] = new Macro(type, identifier, parameters, replacements); if (isMacroNameReserved(name))
{
// TODO(alokp): Report error.
return false;
}
if (isMacroDefined(name))
{
// TODO(alokp): Report error.
return false;
}
mMacros[*name] = macro.release();
return true; return true;
} }
bool Context::undefineMacro(const std::string* identifier) bool Context::undefineMacro(const std::string* name)
{ {
MacroSet::iterator iter = mMacros.find(*identifier); MacroSet::iterator iter = mMacros.find(*name);
if (iter == mMacros.end()) if (iter == mMacros.end())
{ {
// TODO(alokp): Report error. // TODO(alokp): Report error.
...@@ -79,9 +105,9 @@ bool Context::undefineMacro(const std::string* identifier) ...@@ -79,9 +105,9 @@ bool Context::undefineMacro(const std::string* identifier)
return true; return true;
} }
bool Context::isMacroDefined(const std::string* identifier) bool Context::isMacroDefined(const std::string* name)
{ {
return mMacros.find(*identifier) != mMacros.end(); return mMacros.find(*name) != mMacros.end();
} }
// Reset to initialized state. // Reset to initialized state.
...@@ -96,17 +122,17 @@ void Context::reset() ...@@ -96,17 +122,17 @@ void Context::reset()
mOutput = NULL; mOutput = NULL;
} }
void Context::defineBuiltInMacro(const std::string& identifier, int value) void Context::defineBuiltInMacro(const std::string& name, int value)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << value; stream << value;
Token* token = new Token(0, INT_CONSTANT, new std::string(stream.str())); Token* token = new Token(0, INT_CONSTANT, new std::string(stream.str()));
TokenVector* replacements = new pp::TokenVector(1, token); TokenVector* replacements = new pp::TokenVector(1, token);
mMacros[identifier] = new Macro(Macro::kTypeObj, mMacros[name] = new Macro(Macro::kTypeObj,
new std::string(identifier), new std::string(name),
NULL, NULL,
replacements); replacements);
} }
} // namespace pp } // namespace pp
......
...@@ -33,11 +33,11 @@ class Context ...@@ -33,11 +33,11 @@ class Context
bool defineMacro(pp::Token::Location location, bool defineMacro(pp::Token::Location location,
pp::Macro::Type type, pp::Macro::Type type,
std::string* identifier, std::string* name,
pp::Macro::ParameterVector* parameters, pp::TokenVector* parameters,
pp::TokenVector* replacements); pp::TokenVector* replacements);
bool undefineMacro(const std::string* identifier); bool undefineMacro(const std::string* name);
bool isMacroDefined(const std::string* identifier); bool isMacroDefined(const std::string* name);
private: private:
DISALLOW_COPY_AND_ASSIGN(Context); DISALLOW_COPY_AND_ASSIGN(Context);
...@@ -46,7 +46,7 @@ class Context ...@@ -46,7 +46,7 @@ class Context
void reset(); void reset();
bool initLexer(); bool initLexer();
void destroyLexer(); void destroyLexer();
void defineBuiltInMacro(const std::string& identifier, int value); void defineBuiltInMacro(const std::string& name, int value);
bool parse(); bool parse();
void* mLexer; // Lexer handle. void* mLexer; // Lexer handle.
......
...@@ -14,11 +14,11 @@ namespace pp ...@@ -14,11 +14,11 @@ namespace pp
{ {
Macro::Macro(Type type, Macro::Macro(Type type,
std::string* identifier, std::string* name,
ParameterVector* parameters, TokenVector* parameters,
TokenVector* replacements) TokenVector* replacements)
: mType(type), : mType(type),
mIdentifier(identifier), mName(name),
mParameters(parameters), mParameters(parameters),
mReplacements(replacements) mReplacements(replacements)
{ {
...@@ -26,7 +26,7 @@ Macro::Macro(Type type, ...@@ -26,7 +26,7 @@ Macro::Macro(Type type,
Macro::~Macro() Macro::~Macro()
{ {
delete mIdentifier; delete mName;
if (mParameters) if (mParameters)
{ {
......
...@@ -24,26 +24,25 @@ class Macro ...@@ -24,26 +24,25 @@ class Macro
kTypeObj, kTypeObj,
kTypeFunc kTypeFunc
}; };
typedef std::vector<std::string*> ParameterVector;
// Takes ownership of pointer parameters. // Takes ownership of pointer parameters.
Macro(Type type, Macro(Type type,
std::string* identifier, std::string* name,
ParameterVector* parameters, TokenVector* parameters,
TokenVector* replacements); TokenVector* replacements);
~Macro(); ~Macro();
Type type() const { return mType; } Type type() const { return mType; }
const std::string* identifier() const { return mIdentifier; } const std::string* identifier() const { return mName; }
const ParameterVector* parameters() const { return mParameters; } const TokenVector* parameters() const { return mParameters; }
const TokenVector* replacements() const { return mReplacements; } const TokenVector* replacements() const { return mReplacements; }
private: private:
DISALLOW_COPY_AND_ASSIGN(Macro); DISALLOW_COPY_AND_ASSIGN(Macro);
Type mType; Type mType;
std::string* mIdentifier; std::string* mName;
ParameterVector* mParameters; TokenVector* mParameters;
TokenVector* mReplacements; TokenVector* mReplacements;
}; };
......
...@@ -40,9 +40,6 @@ std::ostream& operator<<(std::ostream& out, const Token& token) ...@@ -40,9 +40,6 @@ std::ostream& operator<<(std::ostream& out, const Token& token)
{ {
switch (token.type()) switch (token.type())
{ {
case SPACE:
out << " ";
break;
case INT_CONSTANT: case INT_CONSTANT:
case FLOAT_CONSTANT: case FLOAT_CONSTANT:
case IDENTIFIER: case IDENTIFIER:
......
...@@ -36,6 +36,8 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh. ...@@ -36,6 +36,8 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
#define YY_INPUT(buf, result, maxSize) \ #define YY_INPUT(buf, result, maxSize) \
result = yyextra->readInput(buf, maxSize); result = yyextra->readInput(buf, maxSize);
static std::string* extractMacroName(const char* str, int len);
%} %}
%option noyywrap nounput never-interactive %option noyywrap nounput never-interactive
...@@ -61,9 +63,15 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") ...@@ -61,9 +63,15 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
{HASH} { return HASH; } {HASH} { return HASH; }
{HASH}define { return HASH_DEFINE_OBJ; } {HASH}define{HSPACE}+{IDENTIFIER}/[ \t\n] {
{HASH}define{HSPACE}+/{IDENTIFIER}"(" { return HASH_DEFINE_FUNC; } yylval->sval = extractMacroName(yytext, yyleng);
{HASH}undef { return HASH_UNDEF; } return HASH_DEFINE_OBJ;
}
{HASH}define{HSPACE}+{IDENTIFIER}/"(" {
yylval->sval = extractMacroName(yytext, yyleng);
return HASH_DEFINE_FUNC;
}
{HASH}undef{HSPACE}+ { return HASH_UNDEF; }
{HASH}if { return HASH_IF; } {HASH}if { return HASH_IF; }
{HASH}ifdef { return HASH_IFDEF; } {HASH}ifdef { return HASH_IFDEF; }
...@@ -96,7 +104,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") ...@@ -96,7 +104,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
{PUNCTUATOR} { return yytext[0]; } {PUNCTUATOR} { return yytext[0]; }
{HSPACE}+ { return SPACE; } [ \t\v\f]+ { /* Ignore whitespace */ }
\n { \n {
++yylineno; yycolumn = 0; ++yylineno; yycolumn = 0;
...@@ -107,6 +115,25 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") ...@@ -107,6 +115,25 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
%% %%
std::string* extractMacroName(const char* str, int len)
{
// The input string is of the form {HASH}define{HSPACE}+{IDENTIFIER}
// We just need to find the last HSPACE.
ASSERT(str && (len > 8)); // strlen("#define ") == 8;
std::string* name = NULL;
for (int i = len - 1; i >= 0; --i)
{
if ((str[i] == ' ') || (str[i] == '\t'))
{
name = new std::string(str + i + 1, len - i - 1);
break;
}
}
ASSERT(name);
return name;
}
namespace pp { namespace pp {
int Context::readInput(char* buf, int maxSize) int Context::readInput(char* buf, int maxSize)
......
...@@ -36,7 +36,6 @@ WHICH GENERATES THE GLSL ES PARSER. ...@@ -36,7 +36,6 @@ WHICH GENERATES THE GLSL ES PARSER.
%union { %union {
int ival; int ival;
std::string* sval; std::string* sval;
std::vector<std::string*>* slist;
pp::Token* tval; pp::Token* tval;
pp::TokenVector* tlist; pp::TokenVector* tlist;
} }
...@@ -51,15 +50,14 @@ static void pushConditionalBlock(pp::Context* context, bool condition); ...@@ -51,15 +50,14 @@ static void pushConditionalBlock(pp::Context* context, bool condition);
static void popConditionalBlock(pp::Context* context); static void popConditionalBlock(pp::Context* context);
%} %}
%token HASH HASH_DEFINE_OBJ HASH_DEFINE_FUNC HASH_UNDEF %token HASH HASH_UNDEF
%token HASH_IF HASH_IFDEF HASH_IFNDEF HASH_ELSE HASH_ELIF HASH_ENDIF DEFINED %token HASH_IF HASH_IFDEF HASH_IFNDEF HASH_ELSE HASH_ELIF HASH_ENDIF DEFINED
%token HASH_ERROR HASH_PRAGMA HASH_EXTENSION HASH_VERSION HASH_LINE %token HASH_ERROR HASH_PRAGMA HASH_EXTENSION HASH_VERSION HASH_LINE
%token SPACE %token <sval> HASH_DEFINE_OBJ HASH_DEFINE_FUNC
%token <sval> INT_CONSTANT FLOAT_CONSTANT IDENTIFIER %token <sval> INT_CONSTANT FLOAT_CONSTANT IDENTIFIER
%type <ival> operator %type <ival> operator
%type <slist> parameter_list
%type <tval> conditional_token token %type <tval> conditional_token token
%type <tlist> text_line replacement_token_list conditional_token_list token_list %type <tlist> parameter_list replacement_list conditional_list token_list
%% %%
input input
...@@ -68,32 +66,32 @@ input ...@@ -68,32 +66,32 @@ input
; ;
line line
: text_line { : text_line
| control_line
;
text_line
: '\n'
| token_list '\n' {
// TODO(alokp): Expand macros. // TODO(alokp): Expand macros.
pp::TokenVector* out = context->output(); pp::TokenVector* out = context->output();
out->insert(out->end(), $1->begin(), $1->end()); out->insert(out->end(), $1->begin(), $1->end());
delete $1; delete $1;
} }
| control_line
;
text_line
: '\n' { $$ = NULL; }
| token_list '\n' { $$ = $1; }
; ;
control_line control_line
: HASH '\n' : HASH '\n'
| HASH_DEFINE_OBJ IDENTIFIER replacement_token_list '\n' { | HASH_DEFINE_OBJ replacement_list '\n' {
context->defineMacro(@2.first_line, pp::Macro::kTypeObj, $2, NULL, $3); context->defineMacro(@1.first_line, pp::Macro::kTypeObj, $1, NULL, $2);
} }
| HASH_DEFINE_FUNC IDENTIFIER '(' parameter_list ')' replacement_token_list '\n' { | HASH_DEFINE_FUNC '(' parameter_list ')' replacement_list '\n' {
context->defineMacro(@2.first_line, pp::Macro::kTypeFunc, $2, $4, $6); context->defineMacro(@1.first_line, pp::Macro::kTypeFunc, $1, $3, $5);
} }
| HASH_UNDEF IDENTIFIER '\n' { | HASH_UNDEF IDENTIFIER '\n' {
context->undefineMacro($2); context->undefineMacro($2);
} }
| HASH_IF conditional_token_list '\n' { | HASH_IF conditional_list '\n' {
pushConditionalBlock(context, $2 ? true : false); pushConditionalBlock(context, $2 ? true : false);
} }
| HASH_IFDEF IDENTIFIER '\n' { | HASH_IFDEF IDENTIFIER '\n' {
...@@ -102,7 +100,7 @@ control_line ...@@ -102,7 +100,7 @@ control_line
| HASH_IFNDEF IDENTIFIER '\n' { | HASH_IFNDEF IDENTIFIER '\n' {
pushConditionalBlock(context, !context->isMacroDefined($2)); pushConditionalBlock(context, !context->isMacroDefined($2));
} }
| HASH_ELIF conditional_token_list '\n' { | HASH_ELIF conditional_list '\n' {
} }
| HASH_ELSE '\n' { | HASH_ELSE '\n' {
} }
...@@ -116,39 +114,29 @@ control_line ...@@ -116,39 +114,29 @@ control_line
| HASH_LINE '\n' | HASH_LINE '\n'
; ;
replacement_token_list replacement_list
: /* empty */ { $$ = NULL } : /* empty */ { $$ = NULL; }
| token_list | token_list
;
conditional_token_list parameter_list
: conditional_token { : /* empty */ { $$ = NULL; }
| IDENTIFIER {
$$ = new pp::TokenVector; $$ = new pp::TokenVector;
$$->push_back($1); $$->push_back(new pp::Token(@1.first_line, IDENTIFIER, $1));
} }
| conditional_token_list conditional_token { | parameter_list ',' IDENTIFIER {
$$ = $1; $$ = $1;
$$->push_back($2); $$->push_back(new pp::Token(@3.first_line, IDENTIFIER, $3));
}
;
conditional_token
: DEFINED IDENTIFIER {
}
| DEFINED '(' IDENTIFIER ')' {
} }
| token
;
parameter_list conditional_list
: /* empty */ { $$ = NULL; } : conditional_token {
| IDENTIFIER { $$ = new pp::TokenVector;
$$ = new std::vector<std::string*>();
$$->push_back($1); $$->push_back($1);
} }
| parameter_list ',' IDENTIFIER { | conditional_list conditional_token {
$$ = $1; $$ = $1;
$$->push_back($3); $$->push_back($2);
} }
; ;
...@@ -163,13 +151,18 @@ token_list ...@@ -163,13 +151,18 @@ token_list
} }
; ;
conditional_token
: DEFINED IDENTIFIER {
}
| DEFINED '(' IDENTIFIER ')' {
}
| token
;
token token
: operator { : operator {
$$ = new pp::Token(@1.first_line, $1, NULL); $$ = new pp::Token(@1.first_line, $1, NULL);
} }
| SPACE {
$$ = new pp::Token(@1.first_line, SPACE, NULL);
}
| INT_CONSTANT { | INT_CONSTANT {
$$ = new pp::Token(@1.first_line, INT_CONSTANT, $1); $$ = new pp::Token(@1.first_line, INT_CONSTANT, $1);
} }
......
...@@ -40,48 +40,46 @@ ...@@ -40,48 +40,46 @@
know about them. */ know about them. */
enum yytokentype { enum yytokentype {
HASH = 258, HASH = 258,
HASH_DEFINE_OBJ = 259, HASH_UNDEF = 259,
HASH_DEFINE_FUNC = 260, HASH_IF = 260,
HASH_UNDEF = 261, HASH_IFDEF = 261,
HASH_IF = 262, HASH_IFNDEF = 262,
HASH_IFDEF = 263, HASH_ELSE = 263,
HASH_IFNDEF = 264, HASH_ELIF = 264,
HASH_ELSE = 265, HASH_ENDIF = 265,
HASH_ELIF = 266, DEFINED = 266,
HASH_ENDIF = 267, HASH_ERROR = 267,
DEFINED = 268, HASH_PRAGMA = 268,
HASH_ERROR = 269, HASH_EXTENSION = 269,
HASH_PRAGMA = 270, HASH_VERSION = 270,
HASH_EXTENSION = 271, HASH_LINE = 271,
HASH_VERSION = 272, HASH_DEFINE_OBJ = 272,
HASH_LINE = 273, HASH_DEFINE_FUNC = 273,
SPACE = 274, INT_CONSTANT = 274,
INT_CONSTANT = 275, FLOAT_CONSTANT = 275,
FLOAT_CONSTANT = 276, IDENTIFIER = 276
IDENTIFIER = 277
}; };
#endif #endif
/* Tokens. */ /* Tokens. */
#define HASH 258 #define HASH 258
#define HASH_DEFINE_OBJ 259 #define HASH_UNDEF 259
#define HASH_DEFINE_FUNC 260 #define HASH_IF 260
#define HASH_UNDEF 261 #define HASH_IFDEF 261
#define HASH_IF 262 #define HASH_IFNDEF 262
#define HASH_IFDEF 263 #define HASH_ELSE 263
#define HASH_IFNDEF 264 #define HASH_ELIF 264
#define HASH_ELSE 265 #define HASH_ENDIF 265
#define HASH_ELIF 266 #define DEFINED 266
#define HASH_ENDIF 267 #define HASH_ERROR 267
#define DEFINED 268 #define HASH_PRAGMA 268
#define HASH_ERROR 269 #define HASH_EXTENSION 269
#define HASH_PRAGMA 270 #define HASH_VERSION 270
#define HASH_EXTENSION 271 #define HASH_LINE 271
#define HASH_VERSION 272 #define HASH_DEFINE_OBJ 272
#define HASH_LINE 273 #define HASH_DEFINE_FUNC 273
#define SPACE 274 #define INT_CONSTANT 274
#define INT_CONSTANT 275 #define FLOAT_CONSTANT 275
#define FLOAT_CONSTANT 276 #define IDENTIFIER 276
#define IDENTIFIER 277
...@@ -92,7 +90,6 @@ typedef union YYSTYPE ...@@ -92,7 +90,6 @@ typedef union YYSTYPE
{ {
int ival; int ival;
std::string* sval; std::string* sval;
std::vector<std::string*>* slist;
pp::Token* tval; pp::Token* tval;
pp::TokenVector* tlist; pp::TokenVector* tlist;
} }
......
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