Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7641 views
1
#include "jsi.h"
2
#include "jsvalue.h"
3
#include "jsbuiltin.h"
4
#include "regex.h"
5
6
void js_newregexp(js_State *J, const char *pattern, int flags)
7
{
8
const char *error;
9
js_Object *obj;
10
Reprog *prog;
11
int opts;
12
13
obj = jsV_newobject(J, JS_CREGEXP, J->RegExp_prototype);
14
15
opts = 0;
16
if (flags & JS_REGEXP_I) opts |= REG_ICASE;
17
if (flags & JS_REGEXP_M) opts |= REG_NEWLINE;
18
19
prog = js_regcomp(pattern, opts, &error);
20
if (!prog)
21
js_syntaxerror(J, "regular expression: %s", error);
22
23
obj->u.r.prog = prog;
24
obj->u.r.source = pattern;
25
obj->u.r.flags = flags;
26
obj->u.r.last = 0;
27
js_pushobject(J, obj);
28
}
29
30
void js_RegExp_prototype_exec(js_State *J, js_Regexp *re, const char *text)
31
{
32
unsigned int i;
33
int opts;
34
Resub m;
35
36
opts = 0;
37
if (re->flags & JS_REGEXP_G) {
38
if (re->last > strlen(text)) {
39
re->last = 0;
40
js_pushnull(J);
41
return;
42
}
43
if (re->last > 0) {
44
text += re->last;
45
opts |= REG_NOTBOL;
46
}
47
}
48
49
if (!js_regexec(re->prog, text, &m, opts)) {
50
js_newarray(J);
51
js_pushstring(J, text);
52
js_setproperty(J, -2, "input");
53
js_pushnumber(J, js_utfptrtoidx(text, m.sub[0].sp));
54
js_setproperty(J, -2, "index");
55
for (i = 0; i < m.nsub; ++i) {
56
js_pushlstring(J, m.sub[i].sp, m.sub[i].ep - m.sub[i].sp);
57
js_setindex(J, -2, i);
58
}
59
if (re->flags & JS_REGEXP_G)
60
re->last = re->last + (m.sub[0].ep - text);
61
return;
62
}
63
64
if (re->flags & JS_REGEXP_G)
65
re->last = 0;
66
67
js_pushnull(J);
68
}
69
70
static void Rp_test(js_State *J)
71
{
72
js_Regexp *re;
73
const char *text;
74
int opts;
75
Resub m;
76
77
re = js_toregexp(J, 0);
78
text = js_tostring(J, 1);
79
80
opts = 0;
81
if (re->flags & JS_REGEXP_G) {
82
if (re->last > strlen(text)) {
83
re->last = 0;
84
js_pushboolean(J, 0);
85
return;
86
}
87
if (re->last > 0) {
88
text += re->last;
89
opts |= REG_NOTBOL;
90
}
91
}
92
93
if (!js_regexec(re->prog, text, &m, opts)) {
94
if (re->flags & JS_REGEXP_G)
95
re->last = re->last + (m.sub[0].ep - text);
96
js_pushboolean(J, 1);
97
return;
98
}
99
100
if (re->flags & JS_REGEXP_G)
101
re->last = 0;
102
103
js_pushboolean(J, 0);
104
}
105
106
static void jsB_new_RegExp(js_State *J)
107
{
108
js_Regexp *old;
109
const char *pattern;
110
int flags;
111
112
if (js_isregexp(J, 1)) {
113
if (js_isdefined(J, 2))
114
js_typeerror(J, "cannot supply flags when creating one RegExp from another");
115
old = js_toregexp(J, 1);
116
pattern = old->source;
117
flags = old->flags;
118
} else if (js_isundefined(J, 1)) {
119
pattern = "";
120
flags = 0;
121
} else {
122
pattern = js_tostring(J, 1);
123
flags = 0;
124
}
125
126
if (js_isdefined(J, 2)) {
127
const char *s = js_tostring(J, 2);
128
int g = 0, i = 0, m = 0;
129
while (*s) {
130
if (*s == 'g') ++g;
131
else if (*s == 'i') ++i;
132
else if (*s == 'm') ++m;
133
else js_syntaxerror(J, "invalid regular expression flag: '%c'", *s);
134
++s;
135
}
136
if (g > 1) js_syntaxerror(J, "invalid regular expression flag: 'g'");
137
if (i > 1) js_syntaxerror(J, "invalid regular expression flag: 'i'");
138
if (m > 1) js_syntaxerror(J, "invalid regular expression flag: 'm'");
139
if (g) flags |= JS_REGEXP_G;
140
if (i) flags |= JS_REGEXP_I;
141
if (m) flags |= JS_REGEXP_M;
142
}
143
144
js_newregexp(J, pattern, flags);
145
}
146
147
static void jsB_RegExp(js_State *J)
148
{
149
if (js_gettop(J) == 2 && js_isregexp(J, 1))
150
return;
151
jsB_new_RegExp(J);
152
}
153
154
static void Rp_toString(js_State *J)
155
{
156
js_Regexp *re;
157
char *out;
158
159
re = js_toregexp(J, 0);
160
161
out = js_malloc(J, strlen(re->source) + 6); /* extra space for //gim */
162
strcpy(out, "/");
163
strcat(out, re->source);
164
strcat(out, "/");
165
if (re->flags & JS_REGEXP_G) strcat(out, "g");
166
if (re->flags & JS_REGEXP_I) strcat(out, "i");
167
if (re->flags & JS_REGEXP_M) strcat(out, "m");
168
169
if (js_try(J)) {
170
js_free(J, out);
171
js_throw(J);
172
}
173
js_pop(J, 0);
174
js_pushstring(J, out);
175
js_endtry(J);
176
js_free(J, out);
177
}
178
179
static void Rp_exec(js_State *J)
180
{
181
js_RegExp_prototype_exec(J, js_toregexp(J, 0), js_tostring(J, 1));
182
}
183
184
void jsB_initregexp(js_State *J)
185
{
186
js_pushobject(J, J->RegExp_prototype);
187
{
188
jsB_propf(J, "toString", Rp_toString, 0);
189
jsB_propf(J, "test", Rp_test, 0);
190
jsB_propf(J, "exec", Rp_exec, 0);
191
}
192
js_newcconstructor(J, jsB_RegExp, jsB_new_RegExp, "RegExp", 1);
193
js_defglobal(J, "RegExp", JS_DONTENUM);
194
}
195
196