#include "common/LGraph-cdt.h"
#include "common/StrAttr.h"
#include <vector>
#include <queue>
#if defined(__GNUC__) && __GNUC__>=3
#include <ext/hash_set>
#define HASH_NAMESPACE __gnu_cxx
#else
#include <hash_set>
#define HASH_NAMESPACE std
#endif
namespace GSearch {
struct PatternState {
};
enum PatternDirection {matchDown=1,matchUp=2,matchBoth=3};
struct Test {
DString attr,value; bool matches(StrGraph::Edge *e) {
StrAttrs::iterator i = gd<StrAttrs>(e).find(attr);
if(i==gd<StrAttrs>(e).end())
return false;
return i->second==value;
}
};
struct Path {
std::vector<Test> tests;
int direction;
Path() : direction(matchBoth) {}
bool matches(StrGraph::Edge *e) {
for(std::vector<Test>::iterator ci = tests.begin(); ci!=tests.end(); ++ci)
if(!ci->matches(e))
return false;
return true;
}
};
struct NamedState : PatternState,Name {};
struct NamedTransition : Path,Name {};
struct Pattern : LGraph<Nothing,NamedState,NamedTransition> {
std::map<DString,Node*> dict;
Pattern(const Pattern ©) : Graph(copy) {
for(node_iter ni = nodes().begin(); ni!=nodes().end(); ++ni)
dict[gd<Name>(*ni)] = *ni;
}
Pattern() {}
void readStrGraph(StrGraph &desc);
Node *create_node(DString name) {
Node *ret = Graph::create_node();
gd<Name>(ret) = name;
dict[name] = ret;
return ret;
}
};
struct BadArgument { DString attr,val; BadArgument(DString attr,DString val) : attr(attr),val(val) {} };
struct Match {
Pattern::Node *pattern;
StrGraph::Node *match;
Match(Pattern::Node *pattern,StrGraph::Node *match) : pattern(pattern),match(match) {}
};
struct FollowedPath {
Pattern::Edge *transition;
StrGraph::Edge *edge;
FollowedPath(Pattern::Edge *transition,StrGraph::Edge *edge) : transition(transition),edge(edge) {}
};
#if defined(_MSC_VER) && _MSC_VER>=1300
using GSearch::FollowedPath;
struct hash_fp {
static const size_t bucket_size = 4,
min_buckets = 8;
hash_fp() {}
size_t operator()(FollowedPath fp) const {
return reinterpret_cast<size_t>(fp.transition)^reinterpret_cast<size_t>(fp.edge);
}
bool operator ()(FollowedPath fp1,FollowedPath fp2) const {
return fp1.transition<fp2.transition || (fp1.transition==fp2.transition && fp1.edge<fp2.edge);
}
};
typedef HASH_NAMESPACE::hash_set<FollowedPath,hash_fp> PathsFollowed;
#else
struct hashFollowedPath {
size_t operator ()(FollowedPath fp) const {
return reinterpret_cast<size_t>(fp.transition)^reinterpret_cast<size_t>(fp.edge);
}
};
struct equal_toFollowedPath {
bool operator ()(FollowedPath fp1,FollowedPath fp2) const {
return fp1.transition==fp2.transition && fp1.edge==fp2.edge;
}
};
typedef HASH_NAMESPACE::hash_set<GSearch::FollowedPath,hashFollowedPath,equal_toFollowedPath>
PathsFollowed;
#endif
void runPattern(std::queue<GSearch::Match> &Q,PathsFollowed &followed,
StrGraph *dest);
void matchPattern(Pattern::Node *start,StrGraph::Node *source,StrGraph *dest);
typedef std::map<DString,Pattern> Patterns;
}