inline Try<Warnings> FlagsBase::load( const Option<std::string>& prefix, int argc, const char* const *argv, bool unknowns, bool duplicates) { Multimap<std::string, Option<std::string>> values; // Grab the program name from argv[0]. programName_ = argc > 0 ? Path(argv[0]).basename() : ""; // Read flags from the command line. for (int i = 1; i < argc; i++) { const std::string arg(strings::trim(argv[i])); // Stop parsing flags after '--' is encountered. if (arg == "--") { break; } // Skip anything that doesn't look like a flag. if (arg.find("--") != 0) { continue; } std::string name; Option<std::string> value = None(); size_t eq = arg.find_first_of("="); if (eq == std::string::npos && arg.find("--no-") == 0) { // --no-name name = arg.substr(2); } else if (eq == std::string::npos) { // --name name = arg.substr(2); } else { // --name=value name = arg.substr(2, eq - 2); value = arg.substr(eq + 1); } name = strings::lower(name); values.put(name, value); } if (prefix.isSome()) { // Merge in flags from the environment. Command-line // flags take precedence over environment flags. foreachpair (const std::string& name, const Option<std::string>& value, extract(prefix.get())) { if (!values.contains(name)) { values.put(name, value); } } }
inline Try<Warnings> FlagsBase::load( const Option<std::string>& prefix, int argc, const char* const *argv, bool unknowns, bool duplicates) { Multimap<std::string, Option<std::string>> values; // Grab the program name from argv[0]. programName_ = argc > 0 ? Path(argv[0]).basename() : ""; // Read flags from the command line. for (int i = 1; i < argc; i++) { const std::string arg(strings::trim(argv[i])); // Stop parsing flags after '--' is encountered. if (arg == "--") { break; } // Skip anything that doesn't look like a flag. if (arg.find("--") != 0) { continue; } std::string name; Option<std::string> value = None(); size_t eq = arg.find_first_of("="); if (eq == std::string::npos && arg.find("--no-") == 0) { // --no-name name = arg.substr(2); } else if (eq == std::string::npos) { // --name name = arg.substr(2); } else { // --name=value name = arg.substr(2, eq - 2); value = arg.substr(eq + 1); } name = strings::lower(name); values.put(name, value); } return load(values, unknowns, duplicates, prefix); }
inline void test_multimap_insert(std::multimap<int, int> c) { using phx::arg_names::arg1; using phx::arg_names::arg2; using phx::arg_names::arg3; typedef std::multimap<int, int> Multimap; Multimap::value_type const value = *c.begin(); Multimap::iterator c_begin = c.begin(); // wrapper for // iterator insert(iterator where, const value_type& val); Multimap::iterator it = phx::insert(arg1, arg2, arg3)(c, c_begin, value); if (test(it != c.begin() || *it != *(++it))) { cerr << "Failed " << typeid(Multimap).name() << " test_multimap_insert 1\n"; return; } // wrapper for // iterator insert(const value_type& val); Multimap::value_type const value2(1400, 2200); it = phx::insert(arg1, arg2)(c, value2); if (test(it == c.end())) { cerr << "Failed " << typeid(Multimap).name() << " test_multimap_insert 2\n"; return; } // wrapper for // template<class InIt> // void insert(InIt first, InIt last); Multimap const const_c = build_multimap(); Multimap::size_type size = c.size(); phx::insert(arg1, const_c.begin(), const_c.end())(c); if (test(c.size() != size + const_c.size())) { cerr << "Failed " << typeid(Multimap).name() << " test_multimap_insert 3\n"; return; } }
inline Try<Warnings> FlagsBase::load( const Option<std::string>& prefix, int* argc, char*** argv, bool unknowns, bool duplicates) { Multimap<std::string, Option<std::string>> values; // Grab the program name from argv, without removing it. programName_ = *argc > 0 ? Path(*(argv[0])).basename() : ""; // Keep the arguments that are not being processed as flags. std::vector<char*> args; // Read flags from the command line. for (int i = 1; i < *argc; i++) { const std::string arg(strings::trim((*argv)[i])); // Stop parsing flags after '--' is encountered. if (arg == "--") { // Save the rest of the arguments. for (int j = i + 1; j < *argc; j++) { args.push_back((*argv)[j]); } break; } // Skip anything that doesn't look like a flag. if (arg.find("--") != 0) { args.push_back((*argv)[i]); continue; } std::string name; Option<std::string> value = None(); size_t eq = arg.find_first_of("="); if (eq == std::string::npos && arg.find("--no-") == 0) { // --no-name name = arg.substr(2); } else if (eq == std::string::npos) { // --name name = arg.substr(2); } else { // --name=value name = arg.substr(2, eq - 2); value = arg.substr(eq + 1); } name = strings::lower(name); values.put(name, value); } Try<Warnings> result = load(values, unknowns, duplicates, prefix); // Update 'argc' and 'argv' if we successfully loaded the flags. if (!result.isError()) { CHECK_LE(args.size(), (size_t) *argc); int i = 1; // Start at '1' to skip argv[0]. foreach (char* arg, args) { (*argv)[i++] = arg; } *argc = i; // Now null terminate the array. Note that we'll "leak" the // arguments that were processed here but it's not like they would // have gotten deleted in normal operations anyway. (*argv)[i++] = nullptr; }
Automaton::Ref NfaToDfa(Automaton::Ref source, Multimap<State*, State*>& dfaStateMap) { Automaton::Ref target = shared_ptr<Automaton>(new Automaton); Multimap<Transition*, Transition*> nfaTransitions; vector<Transition*> transitionClasses;//保证转换先后顺序不被nfaTransitions.Keys破坏 State* startState = target->NewState(); target->startState = startState; dfaStateMap.insert(startState, source->startState); vector<State*> transitionTargets; vector<State*> relativeStates; for (int i = 0;i < target->states.size();i++) { // dfa中的待处理的结点 State* currentState = target->states[i].get(); nfaTransitions.clear(); transitionClasses.clear(); // 获得dfa结点对应的nfa的那个结点 // 对该DFA状态的所有等价NFA状态进行遍历 vector<State*> &nfaStates = dfaStateMap[currentState]; for (int j = 0;j < nfaStates.size();j++) { State* nfaState = nfaStates[j]; //对每一个NFA状态的所有转换进行遍历 for (int k = 0;k < nfaState->transitions.size();k++) { Transition* nfaTransition = nfaState->transitions[k]; //检查该NFA转换类型是否已经具有已经被记录 Transition* transitionClass = 0; for (auto it = nfaTransitions.begin();it != nfaTransitions.end();it++) { Transition* key = (*it).first; if (isTransitionEqual(key, nfaTransition)) { transitionClass = key; break; } } //不存在则创建一个转换类型 if (transitionClass == 0) { transitionClass = nfaTransition; transitionClasses.push_back(transitionClass); } //注册转换,一对多的结构 nfaTransitions.insert(transitionClass, nfaTransition); } } // 遍历上面获得的转换,transitionClasses就是将来可能会成为 // 某个dfa结点的边的结构,它的key是任意取的其中的一条边 for (int j = 0;j < transitionClasses.size();j++) { // 获得一条边对应的那些边 const vector<Transition*>& transitionSet = nfaTransitions[transitionClasses[j]]; // 获得那些边指向的结点集合 transitionTargets.clear(); for (int l = 0;l < transitionSet.size();l++) { State* nfaState = transitionSet[l]->target; if (!isElementExist(transitionTargets, nfaState)) { transitionTargets.push_back(nfaState); } } // 判断转换类的所有转换的NFA目标状态组成的集合是否已经有一个对应的DFA状态 State* dfaState = 0; for (auto it = dfaStateMap.begin();it != dfaStateMap.end();it++) { // 将DFA的等价NFA状态集合进行排序(不然不能compare对吧) // 话说我记得我当初也是这么写的 hh // dfaStateMap.CopyValuesToCollection(k, relativeStates); relativeStates.clear(); // 忘记清空了,debug了一年 for (auto i = 0;i < (*it).second.size();i++) { relativeStates.push_back((*it).second[i]); } // 先排下序,才能比较 sort(relativeStates.begin(),relativeStates.end()); sort(transitionTargets.begin(), transitionTargets.end()); // 比较两者是否相等 if (relativeStates.size() == transitionTargets.size()) { bool equal = true; for (int l = 0;l < relativeStates.size();l++) { if (relativeStates[l] != transitionTargets[l]) { equal = false; break; } } if (equal) { dfaState = (*it).first; break; } } } //不存在这个DFA状态则创建一个 if (!dfaState) { dfaState = target->NewState(); // 把刚刚得到的那些结点加进去 for (int k = 0;k < transitionTargets.size();k++) { dfaStateMap.insert(dfaState, transitionTargets[k]); if (transitionTargets[k]->finalState) { dfaState->finalState = true; } } } //将该转换复制到新状态机里 Transition* transitionClass = transitionClasses[j]; Transition* newTransition = target->NewTransition(currentState, dfaState); newTransition->range = transitionClass->range; newTransition->type = transitionClass->type; } } return target; }