void CxxPreProcessor::Parse(const wxFileName& filename, size_t options) { CxxPreProcessorScanner* scanner = NULL; try { CL_DEBUG("Calling CxxPreProcessor::Parse for file '%s'\n", filename.GetFullPath()); m_options = options; scanner = new CxxPreProcessorScanner(filename, m_options); // Remove the option so recursive scanner won't get it m_options &= ~kLexerOpt_DontCollectMacrosDefinedInThisFile; if(scanner && !scanner->IsNull()) { scanner->Parse(this); } } catch(CxxLexerException& e) { wxUnusedVar(e); } // Delete all the 'deleteOnExit' tokens CxxPreProcessorToken::Map_t filteredMap; CxxPreProcessorToken::Map_t::iterator iter = m_tokens.begin(); for(; iter != m_tokens.end(); ++iter) { if(!iter->second.deleteOnExit) { filteredMap.insert(std::make_pair(iter->first, iter->second)); } } m_tokens.swap(filteredMap); // Make sure that the scanner is deleted wxDELETE(scanner); }
void CxxPreProcessorScanner::Parse(CxxPreProcessor* pp) throw(CxxLexerException) { CxxLexerToken token; bool searchingForBranch = false; CxxPreProcessorToken::Map_t& ppTable = pp->GetTokens(); while(::LexerNext(m_scanner, token)) { // Pre Processor state switch(token.type) { case T_PP_INCLUDE_FILENAME: { // we found an include statement, recurse into it wxFileName include; if(pp->ExpandInclude(m_filename, token.text, include)) { CxxPreProcessorScanner* scanner = new CxxPreProcessorScanner(include, pp->GetOptions()); try { scanner->Parse(pp); } catch(CxxLexerException& e) { // catch the exception CL_DEBUG("Exception caught: %s\n", e.message); } // make sure we always delete the scanner wxDELETE(scanner); DEBUGMSG("<== Resuming parser on file: %s\n", m_filename.GetFullPath()); } break; } case T_PP_IFDEF: { searchingForBranch = true; // read the identifier ReadUntilMatch(T_PP_IDENTIFIER, token); if(IsTokenExists(ppTable, token)) { DEBUGMSG("=> ifdef condition is TRUE (line: %d)\n", token.lineNumber); searchingForBranch = false; // condition is true Parse(pp); } else { DEBUGMSG("=> ifdef condition is FALSE (line: %d)\n", token.lineNumber); // skip until we find the next: // else, elif, endif (but do not consume these tokens) if(!ConsumeCurrentBranch()) return; } break; } case T_PP_IFNDEF: { searchingForBranch = true; // read the identifier ReadUntilMatch(T_PP_IDENTIFIER, token); if(!IsTokenExists(ppTable, token)) { DEBUGMSG("=> ifndef condition is TRUE (line: %d)\n", token.lineNumber); searchingForBranch = false; // condition is true Parse(pp); } else { DEBUGMSG("=> ifndef condition is FALSE (line: %d)\n", token.lineNumber); // skip until we find the next: // else, elif, endif (but do not consume these tokens) if(!ConsumeCurrentBranch()) return; } break; } case T_PP_IF: searchingForBranch = true; case T_PP_ELIF: { if(searchingForBranch) { // We expect a condition if(!CheckIf(ppTable)) { DEBUGMSG("=> if condition is FALSE (line: %d)\n", token.lineNumber); // skip until we find the next: // else, elif, endif (but do not consume these tokens) if(!ConsumeCurrentBranch()) return; } else { DEBUGMSG("=> if condition is TRUE (line: %d)\n", token.lineNumber); searchingForBranch = false; // condition is true Parse(pp); } } else { ConsumeBlock(); return; } break; } case T_PP_ELSE: { if(searchingForBranch) { // if we reached an else, it means that we could not match // a if/elif/ifdef condition until now - enter it Parse(pp); searchingForBranch = false; } else { // we already found the branch for the current block // this means that the 'else' is a stop sign for us ConsumeBlock(); return; } break; } case T_PP_ENDIF: { return; } case T_PP_DEFINE: { if(!::LexerNext(m_scanner, token) || token.type != T_PP_IDENTIFIER) { // Recover wxString dummy; GetRestOfPPLine(dummy); break; } wxString macroName = token.text; wxString macroValue; // Optionally get the value GetRestOfPPLine(macroValue, m_options & kLexerOpt_CollectMacroValueNumbers); CxxPreProcessorToken pp; pp.name = macroName; pp.value = macroValue; // mark this token for deletion when the entire TU parsing is done pp.deleteOnExit = (m_options & kLexerOpt_DontCollectMacrosDefinedInThisFile); DEBUGMSG("=> Adding macro: %s=%s (line %d)\n", pp.name, pp.value, token.lineNumber); ppTable.insert(std::make_pair(pp.name, pp)); break; } } } }