18 class TokenLexer :
public Lexer
21 typedef std::vector<Token> TokenVector;
23 TokenLexer(TokenVector* tokens)
25 tokens->swap(mTokens);
26 mIter = mTokens.begin();
29 virtual void lex(Token* token)
31 if (mIter == mTokens.end())
46 TokenVector::const_iterator mIter;
54 mDiagnostics(diagnostics)
62 delete mContextStack[
i];
78 MacroSet::const_iterator iter = mMacroSet->find(token->
text);
79 if (iter == mMacroSet->end())
82 const Macro& macro = iter->second;
96 pushMacro(macro, *token);
100 void MacroExpander::getToken(
Token* token)
102 if (mReserveToken.get())
104 *token = *mReserveToken;
105 mReserveToken.reset();
110 while (!mContextStack.empty() && mContextStack.back()->empty())
115 if (!mContextStack.empty())
117 *token = mContextStack.back()->get();
125 void MacroExpander::ungetToken(
const Token& token)
127 if (!mContextStack.empty())
129 MacroContext*
context = mContextStack.back();
131 assert(context->replacements[context->index] == token);
135 assert(!mReserveToken.get());
136 mReserveToken.reset(
new Token(token));
140 bool MacroExpander::isNextTokenLeftParen()
145 bool lparen = token.type ==
'(';
151 bool MacroExpander::pushMacro(
const Macro& macro,
const Token& identifier)
154 assert(!identifier.expansionDisabled());
156 assert(identifier.text == macro.name);
158 std::vector<Token> replacements;
159 if (!expandMacro(macro, identifier, &replacements))
163 macro.disabled =
true;
165 MacroContext* context =
new MacroContext;
166 context->macro = ¯o;
167 context->replacements.swap(replacements);
168 mContextStack.push_back(context);
172 void MacroExpander::popMacro()
174 assert(!mContextStack.empty());
176 MacroContext* context = mContextStack.back();
177 mContextStack.pop_back();
180 assert(context->macro->disabled);
181 context->macro->disabled =
false;
185 bool MacroExpander::expandMacro(
const Macro& macro,
186 const Token& identifier,
187 std::vector<Token>* replacements)
189 replacements->clear();
192 replacements->assign(macro.replacements.begin(),
193 macro.replacements.end());
195 if (macro.predefined)
200 assert(replacements->size() == 1);
201 Token& repl = replacements->front();
202 if (macro.name == kLine)
204 std::ostringstream
stream;
205 stream << identifier.location.line;
206 repl.text = stream.str();
208 else if (macro.name == kFile)
210 std::ostringstream
stream;
211 stream << identifier.location.file;
212 repl.text = stream.str();
219 std::vector<MacroArg> args;
220 args.reserve(macro.parameters.size());
221 if (!collectMacroArgs(macro, identifier, &args))
224 replaceMacroParams(macro, args, replacements);
229 Token& repl = replacements->at(
i);
234 repl.setAtStartOfLine(identifier.atStartOfLine());
235 repl.setHasLeadingSpace(identifier.hasLeadingSpace());
237 repl.location = identifier.location;
242 bool MacroExpander::collectMacroArgs(
const Macro& macro,
243 const Token& identifier,
244 std::vector<MacroArg>* args)
248 assert(token.type ==
'(');
250 args->push_back(MacroArg());
251 for (
int openParens = 1; openParens != 0; )
258 identifier.location, identifier.text);
273 isArg = openParens != 0;
279 if (openParens == 1) args->push_back(MacroArg());
280 isArg = openParens != 1;
288 MacroArg& arg = args->back();
290 if (arg.empty()) token.setHasLeadingSpace(
false);
291 arg.push_back(token);
297 if (params.empty() && (args->size() == 1) && args->front().empty())
302 if (args->size() != params.size())
307 mDiagnostics->
report(
id, identifier.location, identifier.text);
316 MacroArg& arg = args->at(
i);
317 TokenLexer lexer(&arg);
321 expander.lex(&token);
324 arg.push_back(token);
325 expander.lex(&token);
331 void MacroExpander::replaceMacroParams(
const Macro& macro,
332 const std::vector<MacroArg>& args,
333 std::vector<Token>* replacements)
337 const Token& repl = macro.replacements[
i];
340 replacements->push_back(repl);
347 Macro::Parameters::const_iterator iter = std::find(
348 macro.parameters.begin(), macro.parameters.end(), repl.text);
349 if (iter == macro.parameters.end())
351 replacements->push_back(repl);
356 const MacroArg& arg = args[iArg];
362 replacements->insert(replacements->end(), arg.begin(), arg.end());
365 replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace());
std::vector< std::string > Parameters
bool expansionDisabled() const
GLsizei GLsizei GLfloat distance
void setExpansionDisabled(bool disable)
void report(ID id, const SourceLocation &loc, const std::string &text)
virtual void lex(Token *token)
std::map< std::string, Macro > MacroSet
MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics)
GLsizei const GLcharARB ** string
virtual void lex(Token *token)=0
#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName)