bool cGraphMaster::isMatchWildcard(const InputIterator& input, const InputIterator& pattern, const unsigned long& rec) { if (input.isDone()) { if (pattern.isDone()) return true; else return false; } else { if (pattern.isDone()) return true; else { InputIterator input_copy(input); do { if (isMatch(input_copy, pattern, rec+1)) return true; input_copy++; } while(!input_copy.isDone()); return false; } } return false; }
bool cGraphMaster::getMatch(InputIterator input, NodeType curr_type, const NodeVec& tree, MatcherStruct& ms, unsigned long rec) { // save head of input and advance iterator string input_front = *input; input++; //cout<<"tree.front().key="<<tree.front().key<<endl; _DBG_CODE(msg_dbg() << "[" << rec << "]getMatch(" << curr_type << ") HEAD: [" << input_front << "] last input?:" << boolalpha << input.isDone() << endl); /** FIRST WILDCARD: try to match the '_' wildcard **/ if (tree.front().key == "_") { _DBG_CODE(msg_dbg() << "[" << rec << "]" << "Looking in '_'" << endl); if (getMatchWildcard(input, curr_type, tree.front(), ms, rec, input_front)) { if (ms.log) ms.logMatch("_", curr_type); return true; } } /** KEYS: if wildcard didn't matched, look for specific matching keys against current input_front **/ _DBG_CODE(msg_dbg() << "[" << rec << "]" << "KEYS" << endl); Node tmp_node; tmp_node.key = input_front; NodeVec::const_iterator it = lower_bound(tree.begin(), tree.end(), tmp_node); // if there was a match if (it != tree.end() && it->key == input_front) { // if there are more tokens on input if (!input.isDone()) { // if I have something to match with, then look for a match if (!it->same_childs.empty()) { if (getMatch(input, curr_type, it->same_childs, ms, rec+1)) { if (ms.log) ms.logMatch(it->key, curr_type); return true; } } } // else, this is the last token else { // get the the next type of nodes to match if necessary list<string> match_list; if (curr_type != NODE_TOPIC && !it->diff_childs.empty()) ms.user.getMatchList(NodeType(curr_type+1), match_list); // if in previous situation check if there's a match deeper if (curr_type != NODE_TOPIC && !it->diff_childs.empty() && getMatch(match_list, nextNodeType(curr_type), it->diff_childs, ms, rec+1)) { if (ms.log) ms.logMatch(it->key, curr_type); return true; } // if I'm in the final type of nodes, it needs to be a leaf to have a match else if (curr_type == NODE_TOPIC && !it->templ.empty()) { ms.templ = it->templ; if (ms.log) ms.logMatch(it->key, curr_type); return true; } } } /** LAST WILDCARD: if above didn't matched repeat procedure for '_' **/ if (tree.back().key == "*") { _DBG_CODE(msg_dbg() << "[" << rec << "]" << "Looking in '*'" << endl); if (getMatchWildcard(input, curr_type, tree.back(), ms, rec, input_front)) { if (ms.log) ms.logMatch("*", curr_type); return true; } } return false; }
// Reduced version of the matching algorithm found on graphmaster.cpp, look there for a thorough explanation of the code // This version doesn't have to handle with different node types. The pattern is just a list, not a tree, so it is much easier bool cGraphMaster::isMatch(InputIterator input, InputIterator pattern, unsigned long rec) { string input_head(*input); string patt_head(*pattern); input++; pattern++; if (patt_head == "_" && isMatchWildcard(input, pattern, rec)) return true; if (patt_head == input_head) { if (input.isDone()) { if (pattern.isDone()) return true; else return false; } else { if (pattern.isDone()) return false; else { if (isMatch(input, pattern, rec+1)) return true; else return false; } } } if (patt_head == "*" && isMatchWildcard(input, pattern, rec)) return true; return false; }
bool cGraphMaster::getMatchWildcard(const InputIterator& input, const NodeType& curr_type, const Node& tree_frontback, MatcherStruct& ms, const unsigned long& rec, const string& input_front) { // add the head token to the <*star/>, will remove it if it didn't matched later StarIt it = ms.sh.AddStar(input_front, curr_type); // if this is not the last token of input if (!input.isDone()) { // if this is the last node of the path, then it is a match (save the star and then proceed to match the next node type) if (tree_frontback.same_childs.empty()) { for (InputIterator input_copy(input); !input_copy.isDone(); input_copy++) *it += string(" ") + *input_copy; } // it isn't, so try matching this token with the wildcard and match the rest in a deeper recursion, // after that start making a bigger match for current wildcard, until all trailing input is matched against this wildcard else { InputIterator input_copy(input); do { if (getMatch(input_copy, curr_type, tree_frontback.same_childs, ms, rec+1)) return true; *it += string(" ") + *input_copy; input_copy++; } while(!input_copy.isDone()); } } // this is reached if the match is in this recursion level (the deepest level will set the template and return true, // so I don't have to do anything but pass the 'true' if getMatch() returns true) // This situation is because either: // a) one token of input (sure match, I have to continue the matching job deeper) // b) more than one token of input and: // b.1) trailing wildcard (sure match, eats all available input) // b.2) the wildcard couldn't be used to match just a part of the trailing input, so it matches ALL the trailing input // if i'm not in the final type (ie: not matching the topic) of node and there are other type of nodes I // should get the next type of nodes to match list<string> match_list; if (curr_type != NODE_TOPIC && !tree_frontback.diff_childs.empty()) ms.user.getMatchList(NodeType(curr_type+1), match_list); // so, If I'm in the previous situation AND there's a match with the current match list I should return 'there is a match' if (curr_type != NODE_TOPIC && !tree_frontback.diff_childs.empty() && getMatch(match_list, nextNodeType(curr_type), tree_frontback.diff_childs, ms, rec+1)) return true; // if not, I need to see if I'm matching the topic AND I reached a possible leaf, if so I'm all done, set the template else if (curr_type == NODE_TOPIC && !tree_frontback.templ.empty()) { ms.templ = tree_frontback.templ; return true; } // If I reach here, then there was no match anywere, so I remove the previously added token from <*star> ms.sh.DelStar(it, curr_type); return false; }