This repository has been archived by the owner on Aug 16, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
match.c
246 lines (217 loc) · 5.12 KB
/
match.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*
* match函数运行自动机的代码实现
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <setjmp.h>
#include "dfa.h"
#include "match.h"
/*
* 使用delta函数生成DState时,
* 标记NState是否添加进DState的List列表。
*/
static int listid = 1;
static void handler(int id);
/**
* add_nstate 将NState添加进集合List
*
* @param l 集合List
* @param ns NState
*/
static void add_nstate(List *l, NState *ns)
{
/*
* 判断NState中的lid与当前循环中的listid是否
* 相等,相等的略过,不相等的添加进nlist。
*/
if (ns == NULL || ns->lid == listid) {
return;
}
/* 更新lid */
ns->lid = listid;
/*
* 同时递归添加通过epsilon边
* 能够达到的状态。
*/
if (ns->c == EPSILON) {
add_nstate(l, ns->out1);
add_nstate(l, ns->out2);
return;
}
/* 添加当前NState进入List集合 */
l->ns[l->n++] = ns;
}
/**
* delta 转移函数
*
* @param cl 当前NState集合(clist)
* @param c 字符c
* @param nl 接收字符c后可能转换到的NState集合
*
* @note
* 1. 计算由clist集合吃进字符c后,可以转换到的nlist集合
* 2. 避免每次进入函数都初始化nl,设置全局变量nlist,
* nlist在match函数中分配内存并初始化。
* 因此,这里的nl总是等于&nlist。
*/
List nlist;
void delta(List *cl, int c, List *nl)
{
int i;
NState *ns;
/*
* 标记当前List的状态,
* 是NState是否已经添加进nlist的依据。
*/
listid++;
/* 重置nlist */
nl->n = 0;
for (i = 0; i < cl->n; ++i) {
ns = cl->ns[i];
if (ns->c == c) { /* ns接收字符c,加入nlist */
add_nstate(nl, ns->out1);
}
}
}
static int ptrcmp(const void *a, const void *b)
{
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}
static int listcmp(List *l1, List *l2)
{
int i;
if(l1->n < l2->n)
return -1;
if(l1->n > l2->n)
return 1;
for(i=0; i<l1->n; i++)
if(l1->ns[i] < l2->ns[i])
return -1;
else if(l1->ns[i] > l2->ns[i])
return 1;
return 0;
}
/**
* 二叉树,用于存储已经计算出的DState
* 注意:List l能够唯一确定一个DState。
*/
DState *root;
DState *ds_tree(List *l)
{
int i;
DState *d, **dp;
qsort(l->ns, l->n, sizeof(l->ns[0]), ptrcmp);
dp = &root;
while ((d = *dp) != NULL) {
i = listcmp(l, &d->l);
if (i < 0) {
dp = &d->left;
} else if (i > 0) {
dp = &d->right;
} else {
return d;
}
}
/*
* 树中不存在当前List *l,新建DState并插入
*/
d = (DState *) malloc(sizeof(*d) + l->n * sizeof(l->ns[0]));
memset(d, 0, sizeof(*d));
d->l.ns = (NState **) (d + 1);
memmove(d->l.ns, l->ns, l->n * sizeof(l->ns[0]));
d->l.n = l->n;
*dp = d;
return d;
}
/**
* next_dstate 下一个DState
*
* @param d 当前DState
* @param c 输入字符c
*
* @return 返回当前DState接收字符c后能够达到的DState。
* //TODO 当不存在DState时,未处理,
* //TODO 包括delta函数和ds_tree都没有处理这个问题
*/
DState *next_dstate(DState *d, int c)
{
delta(&d->l, c, &nlist);
return d->next[c] = ds_tree(&nlist);
}
/**
* is_match 是否为接受状态
*
* @param l NState集合List
* @return 若l中含有ACCEPT的NState,则返回1,
* 否则,返回0。
*/
int is_match(List *l)
{
int i;
for (i = 0; i < l->n; ++i) {
if (l->ns[i]->c == ACCEPT) {
return 1;
}
}
return 0;
}
extern int NSTATE;
static jmp_buf env; /* 错误处理 */
int match(NFA *nfa, char *str)
{
int c;
int jmpret;
DState *d, *next;
if ((jmpret = setjmp(env)) != 0) {
handler(jmpret);
}
if (!nfa) {
longjmp(env, 1);
}
if (!str) {
longjmp(env, 2);
}
/* 初始化 */
nlist.ns = (NState **) malloc(NSTATE * sizeof(NState *));
nlist.n = 0;
add_nstate(&nlist, nfa->beg);
d = ds_tree(&nlist); /* 初始节点存进二叉树 */
/*
* 运行nfa,生成dfa,并同步匹配
*/
for (; *str; ++str) {
c = *str;
if ((next = d->next[c]) == NULL) {
next = next_dstate(d, c);
}
d = next;
}
return is_match(&d->l);
}
/**
* handler 异常处理函数
*
* @param id 异常号
*/
void handler(int id)
{
switch (id) {
case 1:
printf("NFA was not established.\n");
break;
case 2:
printf("No valid string to be parsed.\n");
break;
default:
printf("Unknown error.\n");
break;
}
exit(id);
}