ParseResults parser::SLR1::parse(const std::vector<Token>& tokens) { assert(canParse()); ParseResults results; std::stack<std::size_t> stateStack; stateStack.push(0); std::size_t inputPointer = 0; Symbol nonTerminalBuffer; while (true) { TokenType currToken; if (!nonTerminalBuffer.empty()) { currToken = nonTerminalBuffer; } else if (inputPointer < tokens.size()) { currToken = tokens[inputPointer].type; } else { currToken = "EOS"; } auto& currState = table[stateStack.top()]; if (currState.count(currToken) == 0) { return error(tokens, inputPointer, "Unexpected token '" + currToken + "'"); } AscendingAction& action = currState[currToken]; switch (action.action) { case Action::ACCEPT: results.accepted = true; return results; case Action::GOTO: stateStack.push(action.target); nonTerminalBuffer.clear(); break; case Action::REDUCE: { const Production& prod = getCFG()[action.target]; for (std::size_t i = 0; i < prod.size(); i++) { stateStack.pop(); } nonTerminalBuffer = prod.getName(); break; } case Action::SHIFT: stateStack.push(action.target); inputPointer++; break; default: assert(false); } } }
int ReferencesJob::execute() { const bool rename = queryFlags() & QueryMessage::Rename; std::shared_ptr<Project> proj = project(); if (!proj) return 1; Set<Symbol> refs; Map<Location, std::pair<bool, CXCursorKind> > references; if (!symbolName.isEmpty()) { const bool hasFilter = QueryJob::hasFilter(); auto inserter = [this, hasFilter](Project::SymbolMatchType type, const String &string, const Set<Location> &locs) { if (type == Project::StartsWith) { const size_t paren = string.indexOf('('); if (paren == String::npos || paren != symbolName.size() || RTags::isFunctionVariable(string)) return; } for (const auto &l : locs) { if (!hasFilter || filter(l.path())) { locations.insert(l); } } }; proj->findSymbols(symbolName, inserter, queryFlags()); } const bool declarationOnly = queryFlags() & QueryMessage::DeclarationOnly; const bool definitionOnly = queryFlags() & QueryMessage::DefinitionOnly; Location startLocation; bool first = true; for (auto it = locations.begin(); it != locations.end(); ++it) { const Location pos = *it; Symbol sym = proj->findSymbol(pos); if (sym.isNull()) continue; if (first && !(queryFlags() & QueryMessage::NoSortReferencesByInput)) { first = false; startLocation = sym.location; } if (sym.isReference()) { const Symbol target = proj->findTarget(sym); if (!target.isNull() && target.kind != CXCursor_MacroExpansion) sym = target; } if (sym.isNull()) continue; if (rename && sym.isConstructorOrDestructor()) { const Location loc = sym.location; sym.clear(); const Set<String> usrs = proj->findTargetUsrs(loc); for (const String &usr : usrs) { for (const Symbol &s : proj->findByUsr(usr, loc.fileId(), Project::ArgDependsOn, loc)) { if (s.isClass()) { sym = s; if (s.isDefinition()) break; } } } if (sym.isNull()) continue; } if (queryFlags() & QueryMessage::AllReferences) { const Set<Symbol> all = proj->findAllReferences(sym); for (const auto &symbol : all) { if (rename) { if (symbol.kind == CXCursor_MacroExpansion && sym.kind != CXCursor_MacroDefinition) continue; if (symbol.flags & Symbol::AutoRef) continue; } else if (sym.isClass() && symbol.isConstructorOrDestructor()) { continue; } const bool def = symbol.isDefinition(); if (def) { if (declarationOnly) continue; } else if (definitionOnly) { continue; } references[symbol.location] = std::make_pair(def, symbol.kind); } } else if (queryFlags() & QueryMessage::FindVirtuals) { const Set<Symbol> virtuals = proj->findVirtuals(sym); for (const auto &symbol : virtuals) { const bool def = symbol.isDefinition(); if (def) { if (declarationOnly) continue; } else if (definitionOnly) { continue; } references[symbol.location] = std::make_pair(def, symbol.kind); } } else { const Set<Symbol> symbols = proj->findCallers(sym); for (const auto &symbol : symbols) { const bool def = symbol.isDefinition(); if (def) { if (declarationOnly) continue; } else if (definitionOnly) { continue; } references[symbol.location] = std::make_pair(false, CXCursor_FirstInvalid); } } } Flags<QueryJob::WriteFlag> writeFlags; Flags<Location::ToStringFlag> kf = locationToStringFlags(); if (queryFlags() & QueryMessage::Elisp) { write("(list ", DontQuote); writeFlags |= QueryJob::NoContext; } else if (queryFlags() & QueryMessage::NoContext) { writeFlags |= QueryJob::NoContext; } auto writeCons = [this](const String &car, const String &cdr) { write("(cons ", DontQuote); write(car, DontQuote); write(cdr); write(")", DontQuote); }; auto writeLoc = [this, writeCons, writeFlags, kf](Location loc) { if (queryFlags() & QueryMessage::Elisp) { if (!filterLocation(loc)) return; write("(list ", DontQuote); locationToString(loc, [writeCons, this](LocationPiece piece, const String &string) { switch (piece) { case Piece_ContainingFunctionLocation: if (queryFlags() & QueryMessage::ContainingFunctionLocation) writeCons("'cfl", string); break; case Piece_ContainingFunctionName: if (queryFlags() & QueryMessage::ContainingFunction) writeCons("'cf", string); break; case Piece_Location: writeCons("'loc", string); break; case Piece_Context: if (!(queryFlags() & QueryMessage::NoContext)) writeCons("'ctx", string); break; case Piece_SymbolName: case Piece_Kind: break; } }); write(")", DontQuote); } else { write(loc, writeFlags); } }; if (rename) { if (!references.isEmpty()) { if (queryFlags() & QueryMessage::ReverseSort) { Map<Location, std::pair<bool, CXCursorKind> >::const_iterator it = references.end(); do { --it; writeLoc(it->first); } while (it != references.begin()); } else { for (const auto &it : references) { writeLoc(it.first); } } } } else { List<RTags::SortedSymbol> sorted; sorted.reserve(references.size()); for (Map<Location, std::pair<bool, CXCursorKind> >::const_iterator it = references.begin(); it != references.end(); ++it) { sorted.append(RTags::SortedSymbol(it->first, it->second.first, it->second.second)); } if (queryFlags() & QueryMessage::ReverseSort) { std::sort(sorted.begin(), sorted.end(), std::greater<RTags::SortedSymbol>()); } else { std::sort(sorted.begin(), sorted.end()); } int startIndex = 0; const int count = sorted.size(); if (!startLocation.isNull()) { for (int i=0; i<count; ++i) { if (sorted.at(i).location == startLocation) { startIndex = i + 1; break; } } } for (int i=0; i<count; ++i) { Location loc = sorted.at((startIndex + i) % count).location; writeLoc(loc); } } if (queryFlags() & QueryMessage::Elisp) write(")", DontQuote); return references.isEmpty() ? 1 : 0; }