-
Notifications
You must be signed in to change notification settings - Fork 4
/
backtrack.c
117 lines (110 loc) · 2.36 KB
/
backtrack.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
// Copyright 2007-2009 Russ Cox. All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "re1.5.h"
typedef struct Thread Thread;
struct Thread
{
char *pc;
const char *sp;
Sub *sub;
};
static Thread
thread(char *pc, const char *sp, Sub *sub)
{
Thread t = {pc, sp, sub};
return t;
}
int
re1_5_backtrack(ByteProg *prog, Subject *input, const char **subp, int nsubp, int is_anchored)
{
enum { MAX = 1000 };
Thread ready[MAX];
int i, nready;
char *pc;
const char *sp;
Sub *sub;
int off;
/* queue initial thread */
sub = newsub(nsubp);
for(i=0; i<nsubp; i++)
sub->sub[i] = nil;
ready[0] = thread(HANDLE_ANCHORED(prog->insts, is_anchored), input->begin, sub);
nready = 1;
/* run threads in stack order */
while(nready > 0) {
--nready; /* pop state for next thread to run */
pc = ready[nready].pc;
sp = ready[nready].sp;
sub = ready[nready].sub;
assert(sub->ref > 0);
for(;;) {
if(inst_is_consumer(*pc)) {
// If we need to match a character, but there's none left, it's fail
if(sp >= input->end)
goto Dead;
}
switch(*pc++) {
case Char:
if(*sp != *pc++)
goto Dead;
case Any:
sp++;
continue;
case Class:
case ClassNot:
if (!_re1_5_classmatch(pc, sp))
goto Dead;
pc += *(unsigned char*)pc * 2 + 1;
sp++;
continue;
case NamedClass:
if (!_re1_5_namedclassmatch(pc, sp))
goto Dead;
pc++;
sp++;
continue;
case Match:
for(i=0; i<nsubp; i++)
subp[i] = sub->sub[i];
decref(sub);
return 1;
case Jmp:
off = (signed char)*pc++;
pc = pc + off;
continue;
case Split:
if(nready >= MAX)
re1_5_fatal("backtrack overflow");
off = (signed char)*pc++;
ready[nready++] = thread(pc + off, sp, incref(sub));
// pc = pc->x; /* continue current thread */
continue;
case RSplit:
if(nready >= MAX)
re1_5_fatal("backtrack overflow");
off = (signed char)*pc++;
ready[nready++] = thread(pc, sp, incref(sub));
pc = pc + off;
continue;
case Save:
off = (unsigned char)*pc++;
sub = update(sub, off, sp);
continue;
case Bol:
if(sp != input->begin)
goto Dead;
continue;
case Eol:
if(sp != input->end)
goto Dead;
continue;
default:
re1_5_fatal("backtrack");
}
}
Dead:
decref(sub);
}
return 0;
}