Example #1
0
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;
        }
        }
    }
}