diff --git a/wu_dfa/Makefile b/wu_dfa/Makefile new file mode 100644 index 00000000..dcd7ecd --- /dev/null +++ b/wu_dfa/Makefile @@ -0,0 +1,4 @@ +all: + g++ wu_dfa.cpp -o wu_dfa +clean: + rm -f wu_dfa \ No newline at end of file diff --git a/wu_dfa/wu_dfa b/wu_dfa/wu_dfa new file mode 100755 index 00000000..dd5bac2 Binary files /dev/null and b/wu_dfa/wu_dfa differ diff --git a/wu_dfa/wu_dfa.cpp b/wu_dfa/wu_dfa.cpp new file mode 100644 index 00000000..7c41a26 --- /dev/null +++ b/wu_dfa/wu_dfa.cpp @@ -0,0 +1,612 @@ +#include +using namespace std; +#include +#include +#include +#include +#include "wu_dfa.h" + +#define LStack LinkedStack + +class DFA +{ +public: + DFA(); + ~DFA(); + void GetRegExp(); + void InsertCatNode(); + void RegExpToPost(); + void GetEdgeNumber(); + void ThompsonConstruction(); + void SubsetConstruction(); +private: + char *exp; + char *post; + char *edge; + int edgeNumber; + int **DStates; + int **Dtran; + int *AcceptStates; + int DStatesNumber; + int DtranNumber; + int NFAStatesNumber; + int DFAStatesNumber; + AdjacentTable *NFATable; + TransitionTable *DFATable; + int Precedence(char symbol); + int CompArray(int *t1, int *t2); + int MinimizeDFAStates(int **Dtran, int *AcceptStates, int DtranNumber, int edgeNumber); + }; + +DFA::DFA() +{ + exp = new char[128]; + post = new char[128]; + edge = new char[128]; + edgeNumber = 0; + NFAStatesNumber = 0; + DFAStatesNumber = 0; + DStatesNumber = 0; + DtranNumber = 0; + NFATable = new AdjacentTable(); +} + +DFA::~DFA() +{ + delete [] exp; + delete [] post; + delete [] edge; + delete [] AcceptStates; + NFATable->Clear(); + DFATable->Clear(); +} + +void DFA::GetRegExp() +{ + cout << "\ninput regular expression: " << endl; + cin >> exp; + for (int i=0; exp[i]!='\0'; i++) + { + if (exp[i] == '~') + { + cout << "\n'~'is forbidden!" << endl; + getchar(); + exit(1); + } + } + cout << "------------------------" << endl; +} + +void DFA::InsertCatNode() +{ + int i = 0, j, len = strlen(exp); + while (exp[i+1] != '\0') + { + if (((exp[i] != '(' && exp[i] != '.' && exp[i] != '|'&& exp[i+1] != '/') + || exp[i] == ')' || exp[i] == '*' || exp[i] == '+' || exp[i] == '?') + && (exp[i+1] != ')' && exp[i+1] != '.' && exp[i+1] != '|' + && exp[i+1] != '*' && exp[i+1] != '+' && exp[i+1] != '?' && exp[i+1] != '/')) + { + for (j=len; j>i+1; j--) + { + exp[j] = exp[j-1]; + } + exp[i+1] = '.'; + len++; + exp[len] = '\0'; + i++; + } + i++; + } + cout << "1.Insert cat-node\n" + << exp << "\n------------------------" << endl; +} +int DFA::Precedence(char symbol) +{ + int priority; + switch (symbol) + { + case '|': priority = 1; break; + case '.': priority = 2; break; + case '*': priority = 3; break; + case '+': priority = 4; break; + case '?': priority = 5; break; + case '/': priority = 6; break; + default: priority = 0; break; + } + return priority; +} +void DFA::RegExpToPost() +{ + int i = 0, j = 0; + char ch, cl; + strcpy(post, "\0"); + LStack *ls = new LStack(); + ls->Clear(); + ls->Push('#'); + ch = exp[i]; + while (ch != '\0') + { + if (ch == '(') + { + ls->Push(ch); + ch = exp[++i]; + } + else if (ch == ')') + { + while (ls->GetTop() != '(') + { + post[j++] = ls->Pop(); + } + ls->Pop(); + ch = exp[++i]; + } + else if ((ch == '|') || (ch == '*') || (ch == '.') || (ch == '+') || (ch == '?') || (ch == '/') ) + { + cl = ls->GetTop(); + while (Precedence(cl) >= Precedence(ch)) + { + post[j++] = cl; + ls->Pop(); + cl = ls->GetTop(); + } + ls->Push(ch); + ch = exp[++i]; + } + else + { + post[j++] = ch; + ch = exp[++i]; + } + } + ch = ls->Pop(); + while ((ch == '|') || (ch == '*') || (ch == '.') || (ch == '+') || (ch == '?') || (ch == '/') ) + { + post[j++] = ch; + ch = ls->Pop(); + } + post[j] = '\0'; + ls->Clear(); + cout << "2.regexp to post\n" + << post << "\n------------------------" << endl; +} + +void DFA::GetEdgeNumber() +{ + int i = 0, j; + edgeNumber = 0; + while (post[i] != '\0') + { + if (post[i] == '.' || post[i] == '|' || post[i] == '*' || post[i] == '+' || post[i] == '?' || post[i] == '/') + { + i++; + continue; + } + for (j=0; j *states = new LStack(); + states->Clear(); + if (strlen(post) < 1) + { + cout << "No Valid Regular Expression Found!" << endl; + getchar(); + exit(1); + } + NFATable->SetValue(0, 0); + i = 1; + j = 0; + ch = post[j]; + while (ch != '\0') + { + if (ch == '.') + { + s2 = states->Pop(); + int temp1 = states->Pop(); + int temp2 = states->Pop(); + s1 = states->Pop(); + NFATable->InsertEdgeByValue(temp2, temp1, '~'); + states->Push(s1); + states->Push(s2); + } + else if (ch == '|') + { + s2 = states->Pop(); + int temp1 = states->Pop(); + int temp2 = states->Pop(); + s1 = states->Pop(); + NFATable->InsertVertex(i); + NFATable->InsertVertex(i+1); + NFATable->InsertEdgeByValue(i, s1, '~'); + NFATable->InsertEdgeByValue(i, temp1, '~'); + NFATable->InsertEdgeByValue(temp2, i+1, '~'); + NFATable->InsertEdgeByValue(s2, i+1, '~'); + s1 = i; + s2 = i+1; + states->Push(s1); + states->Push(s2); + i += 2; + } + else if (ch == '*') + { + s2 = states->Pop(); + s1 = states->Pop(); + NFATable->InsertVertex(i); + NFATable->InsertVertex(i+1); + NFATable->InsertEdgeByValue(i, i+1, '~'); + NFATable->InsertEdgeByValue(s2, s1, '~'); + NFATable->InsertEdgeByValue(i, s1, '~'); + NFATable->InsertEdgeByValue(s2, i+1, '~'); + s1 = i; + s2 = i+1; + states->Push(s1); + states->Push(s2); + i += 2; + } + else if (ch == '+') + { + s2 = states->Pop(); + s1 = states->Pop(); + NFATable->InsertVertex(i); + NFATable->InsertVertex(i+1); + NFATable->InsertEdgeByValue(s2, s1, '~'); + NFATable->InsertEdgeByValue(i, s1, '~'); + NFATable->InsertEdgeByValue(s2, i+1, '~'); + s1 = i; + s2 = i+1; + states->Push(s1); + states->Push(s2); + i += 2; + } + else if (ch == '?') + { + s2 = states->Pop(); + s1 = states->Pop(); + NFATable->InsertVertex(i); + NFATable->InsertVertex(i+1); + NFATable->InsertEdgeByValue(i, i+1, '~'); + NFATable->InsertEdgeByValue(i, s1, '~'); + NFATable->InsertEdgeByValue(s2, i+1, '~'); + s1 = i; + s2 = i+1; + states->Push(s1); + states->Push(s2); + i += 2; + } + else if (ch == '/') + { + s2 = states->Pop(); + s1 = states->Pop(); + NFATable->InsertVertex(i); + NFATable->InsertVertex(i+1); + NFATable->InsertEdgeByValue(i, i+1, '~'); + s1 = i; + s2 = i+1; + states->Push(s1); + states->Push(s2); + i += 2; + } + else + { + NFATable->InsertVertex(i); + NFATable->InsertVertex(i+1); + NFATable->InsertEdgeByValue(i, i+1, ch); + s1 = i; + s2 = i+1; + states->Push(s1); + states->Push(s2); + i += 2; + } + j++; + ch = post[j]; + } + s2 = states->Pop(); + s1 = states->Pop(); + NFATable->InsertEdgeByValue(0, s1, '~'); + if (! states->IsEmpty()) + { + cout << "Some error in your input string!" << endl; + getchar(); + exit(1); + } + NFAStatesNumber = s2 + 1; +} + +int DFA::CompArray(int *t1, int *t2) +{ + int i = 0, j = 0, len1, len2; + while (t1[i] != -1) + { + i++; + } + len1 = i; + while (t2[j] != -1) + { + j++; + } + len2 = j; + if (len1 != len2) + { + return 0; + } + for (i=0; iOutputNFA(); + cout << "------------------------" << endl; + DStates = (int**)(new int*[NFAStatesNumber+1]); + for (i=0; iClosure(T); + DStates[DStatesNumber] = T; + DStatesNumber++; + k = 0; + while (k < DStatesNumber) + { + for (i=0; edge[i]!='\0'; i++) + { + temp = NFATable->Closure(NFATable->Move(T, edge[i])); + if (temp[0] != -1) + { + for (j=0; jSetValue(i, j, Dtran[i][j]); + } + } + + cout << "7.DFA\nstate"; + for (j=0; jGetValue(i, j) < 0) cout << " "; + else if (DFATable->GetValue(i, j) < 10) cout << " " << DFATable->GetValue(i, j); + else if (DFATable->GetValue(i, j) < 100) cout << " " << DFATable->GetValue(i, j); + else if (DFATable->GetValue(i, j) < 1000) cout << " " << DFATable->GetValue(i, j); + else cout << " " << DFATable->GetValue(i, j); + } + if (AcceptStates[i] == 1) + { + cout << " Acc"; + } + cout << endl; + } + cout << "------------------------" << endl; + for (i=0; i +using namespace std; +#include +#include +#include +#include + + +template +class LinkedStack; + + +template +class StackNode +{ + friend class LinkedStack; +private: + T data; + StackNode *next; + StackNode(T item = 0, StackNode *p = NULL) + { + data = item; + next = p; + } +}; + + +template +class LinkedStack +{ +private: + StackNode *top; +public: + LinkedStack(); + ~LinkedStack(); + bool IsEmpty(void) const; + int Length(void) const; + void Push(const T &item); + T Pop(void); + T GetTop(void); + void Clear(void); +}; + +template +LinkedStack::LinkedStack() +{ + top = NULL; +} + +template +LinkedStack::~LinkedStack() +{ + Clear(); +} + +template +bool LinkedStack::IsEmpty(void) const +{ + return (! top); +} + +template +int LinkedStack::Length(void) const +{ + StackNode *temp = new StackNode(); + temp = top; + int length = 0; + while (temp) + { + temp = temp->next; + length++; + } + return length; +} + +template +void LinkedStack::Push(const T &item) +{ + top = new StackNode(item, top); +} + +template +T LinkedStack::Pop(void) +{ + if (! IsEmpty()) + { + StackNode *temp = top; + top = top->next; + T value = temp->data; + delete temp; + return value; + } + else + { + cout << "Stack Already Empty!" << endl; + getchar(); + exit(1); + } +} + +template +T LinkedStack::GetTop(void) +{ + if (! IsEmpty()) + { + return top->data; + } + else + { + cout << "Stack Already Empty!" << endl; + getchar(); + exit(1); + } +} + +template +void LinkedStack::Clear(void) +{ + StackNode *temp = new StackNode(); + while (top) + { + temp = top; + top = top->next; + delete temp; + } +} + + +class Edge +{ +public: + int number; + int position; + char weight; + Edge *link; + Edge(); + Edge(int num, int pos, char ch); +}; +Edge::Edge() +{ + number = -1; + position = -1; + link = NULL; +} +Edge::Edge(int num, int pos, char ch) +{ + number = num; + position = pos; + weight = ch; + link = NULL; +} + + +class Vertex +{ +public: + int number; + Vertex *next; + Edge *out; + Vertex(); + Vertex(int num); +}; +Vertex::Vertex() +{ + number = -1; + next = NULL; + out = NULL; +} +Vertex::Vertex(int num) +{ + number = num; + next = NULL; + out = NULL; +} + + +class AdjacentTable +{ +private: + Vertex *startVertex; + int numOfVertices; + int numOfEdges; +public: + AdjacentTable(); + ~AdjacentTable(); + int GetValueByPos(int pos) const; + int GetPosByValue(int value) const; + char GetWeightByPos(int v1, int v2) const; + char GetWeightByValue(int value1, int value2) const; + void SetValue(int value, int pos); + void InsertVertex(int value); + void InsertEdgeByPos(int v1, int v2, char weight); + void InsertEdgeByValue(int value1, int value2, char weight); + void RemoveAllEdges(void); + void Clear(void); + int* Closure(int *T); + int* Move(int *T, char ch); + void OutputNFA(void); +}; + +AdjacentTable::AdjacentTable() +{ + numOfVertices = 1; + numOfEdges = 0; + startVertex = new Vertex(); +} + +AdjacentTable::~AdjacentTable() +{ + Vertex *p; + Edge *q; + p = startVertex; + for (int i=0; iout; + while (q) + { + p->out = q->link; + delete q; + q = p->out; + } + p = p->next; + } +} + +int AdjacentTable::GetValueByPos(int pos) const +{ + if ((pos >= 0) && (pos < numOfVertices)) + { + Vertex *p = startVertex; + for (int i=0; inext; + } + return p->number; + } + return -1; +} + +int AdjacentTable::GetPosByValue(int value) const +{ + Vertex *p = startVertex; + for (int i=0; inumber == value) + { + return i; + } + p = p->next; + } + return -1; +} + +char AdjacentTable::GetWeightByPos(int v1, int v2) const +{ + if ((v1 >= 0) && (v2 >= 0) && (v1 < numOfVertices) && (v2 < numOfVertices)) + { + Vertex *p = startVertex; + for (int i=0; inext; + } + Edge *q = p->out; + while (q) + { + if (q->position == v2) + { + return (q->weight); + } + else + { + q = q->link; + } + } + } + return '#'; +} + +char AdjacentTable::GetWeightByValue(int value1, int value2) const +{ + return GetWeightByPos(GetPosByValue(value1), GetPosByValue(value2)); +} + +void AdjacentTable::SetValue(int value, int pos) +{ + if ((pos < 0) || (pos >= numOfVertices)) + { + cout << "Illegal setting: The vertex doesn't exist!" << endl; + getchar(); + exit(1); + } + Vertex *p = startVertex; + for (int i=0; inext; + } + p->number = value; +} + +void AdjacentTable::InsertVertex(int value) +{ + int pos = GetPosByValue(value); + if ((pos >= 0) && (pos < numOfVertices)) + { + cout << "Illegal insertion: The same vertex has existed!" << endl; + getchar(); + exit(1); + } + Vertex *p = startVertex; + while (p->next) + { + p = p->next; + } + Vertex *newVertex = new Vertex(value); + p->next = newVertex; + numOfVertices++; +} + +void AdjacentTable::InsertEdgeByPos(int v1, int v2, char weight) +{ + if ((v1 < 0) || (v1 >= numOfVertices) || (v2 < 0) || (v2 >= numOfVertices)) + { + cout << "Illegal insertion: The vertex doesn't exist!" << endl; + getchar(); + exit(1); + } + Vertex *p = startVertex; + for (int i=0; inext; + } + Edge *q = p->out; + Edge *newEdge = new Edge(GetValueByPos(v2), v2, weight); + if (! q) + { + p->out = newEdge; + numOfEdges++; + return; + } + while ((q->position != v2) && (q->link)) + { + q = q->link; + } + if (q->position == v2) + { + cout << "Illegal insertion: The Edge has existed!" << endl; + getchar(); + exit(1); + } + if (! q->link) + { + q->link = newEdge; + numOfEdges++; + } +} + +void AdjacentTable::InsertEdgeByValue(int value1, int value2, char weight) +{ + int v1 = GetPosByValue(value1), v2 = GetPosByValue(value2); + InsertEdgeByPos(v1, v2, weight); +} + +void AdjacentTable::RemoveAllEdges(void) +{ + Vertex *p = startVertex; + for (int i=0; iout; + while (q) + { + p->out = q->link; + delete q; + q = p->out; + } + p = p->next; + } + numOfEdges = 0; +} + +void AdjacentTable::Clear(void) +{ + RemoveAllEdges(); + Vertex *p = startVertex->next; + while (p) + { + startVertex->next = p->next; + delete p; + p = startVertex->next; + } + numOfVertices = 1; +} + +int* AdjacentTable::Closure(int *T) +{ + int i = 0, j, k = 0, l, len = 0; + int *temp = new int[128]; + Vertex *p; + Edge *q; + while (T[len] != -1) + { + len++; + } + while (T[i] != -1) + { + for (l=0; lnext; + } + q = p->out; + while (q) + { + if (q->weight == '~') + { + for (l=0; lnumber == temp[l]) + { + break; + } + } + if (l == k) + { + temp[k] = q->number; + k++; + T[len++] = q->number; + T[len] = -1; + } + } + q = q->link; + } + i++; + } + temp[k] = -1; + return temp; +} + +int* AdjacentTable::Move(int *T, char ch) +{ + int i = 0, j, k = 0, l; + int *temp = new int[128]; + Vertex *p; + Edge *q; + while (T[i] != -1) + { + int pos = GetPosByValue(T[i]); + p = startVertex; + for (j=0; jnext; + } + q = p->out; + while (q) + { + if (q->weight == ch) + { + for (l=0; lnumber == temp[l]) + { + break; + } + } + if (l == k) + { + temp[k] = q->number; + k++; + } + } + q = q->link; + } + i++; + } + temp[k] = -1; + return temp; +} + +void AdjacentTable::OutputNFA(void) +{ + Vertex *p = startVertex; + Edge *q = new Edge(); + cout << "state edge(weight)" << endl; + for (int i=0; inumber; + if (p->number < 10) cout << " "; + else if (p->number < 100) cout << " "; + else if (p->number < 1000) cout << " "; + else cout << " "; + q = p->out; + if (q) + { + while (q) + { + cout << q->number << "(" << q->weight << ") "; + q = q->link; + } + } + else + { + cout << "END"; + } + cout << endl; + p = p->next; + } +} + + +class TransitionTable +{ +public: + TransitionTable(int rowNum, int colNum); + ~TransitionTable(); + void SetValue(int i, int j, int value); + int GetValue(int i, int j); + void Clear(void); +private: + int **matrix; + int rowNumber; + int colNumber; +}; + +TransitionTable::TransitionTable(int rowNum, int colNum) +{ + rowNumber = rowNum; + colNumber = colNum; + matrix = (int**)(new int*[rowNumber]); + for (int i=0; i