1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | "use strict";
|
18 |
|
19 |
|
20 |
|
21 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
|
22 |
|
23 |
|
24 |
|
25 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
26 |
|
27 | var PatternAcceptor = (function () {
|
28 | function PatternAcceptor(pattern, u) {
|
29 | _classCallCheck(this, PatternAcceptor);
|
30 |
|
31 | this.index = 0;
|
32 | this.nCapturingParens = 0;
|
33 |
|
34 | this.length = pattern.length;
|
35 | this.pattern = pattern;
|
36 | this.u = u;
|
37 | }
|
38 |
|
39 | _createClass(PatternAcceptor, [{
|
40 | key: "eat",
|
41 | value: function eat(ch) {
|
42 | if (this.index >= this.length || this.pattern[this.index] !== ch) return false;
|
43 | ++this.index;
|
44 | return true;
|
45 | }
|
46 | }, {
|
47 | key: "eatRegExp",
|
48 | value: function eatRegExp(r) {
|
49 | if (this.index >= this.length || !r.test(this.pattern[this.index])) return false;
|
50 | ++this.index;
|
51 | return true;
|
52 | }
|
53 | }, {
|
54 | key: "eatN",
|
55 | value: function eatN(n, r) {
|
56 | if (this.index + n <= this.length && r.test(this.pattern.slice(this.index, this.index + n))) {
|
57 | this.index += n;
|
58 | return true;
|
59 | }
|
60 | return false;
|
61 | }
|
62 | }, {
|
63 | key: "match",
|
64 | value: function match(ch) {
|
65 | return this.index < this.length && this.pattern[this.index] === ch;
|
66 | }
|
67 | }, {
|
68 | key: "matchRegExp",
|
69 | value: function matchRegExp(r) {
|
70 | return this.index < this.length && r.test(this.pattern[this.index]);
|
71 | }
|
72 | }, {
|
73 | key: "trackback",
|
74 | value: function trackback(start, result) {
|
75 | if (result) return true;
|
76 | this.index = start;
|
77 | return false;
|
78 | }
|
79 | }, {
|
80 | key: "readDisjunction",
|
81 | value: function readDisjunction() {
|
82 | return this.readAlternative() && (this.eat("|") ? this.readDisjunction() : true);
|
83 | }
|
84 | }, {
|
85 | key: "readAlternative",
|
86 | value: function readAlternative() {
|
87 | var savedIndex = this.index;
|
88 | while (this.readTerm()) {
|
89 | savedIndex = this.index;
|
90 | }
|
91 | this.index = savedIndex;
|
92 | return true;
|
93 | }
|
94 | }, {
|
95 | key: "readTerm",
|
96 | value: function readTerm() {
|
97 | if (!this.u) return this.readExtendedTerm();
|
98 | return this.readAssertion() || this.readQuantifiableAssertion() || this.readAtom() && (this.readQuantifier(), true);
|
99 | }
|
100 | }, {
|
101 | key: "readExtendedTerm",
|
102 | value: function readExtendedTerm() {
|
103 | return this.readQuantifiableAssertion() && (this.readQuantifier(), true) || this.readAssertion() || this.readAtomNoBrace() && (this.readQuantifier(), true) || this.readAtom();
|
104 | }
|
105 | }, {
|
106 | key: "readAssertion",
|
107 | value: function readAssertion() {
|
108 | return this.eat("^") || this.eat("$") || this.eatN(2, /^\\[bB]$/);
|
109 | }
|
110 | }, {
|
111 | key: "readQuantifiableAssertion",
|
112 | value: function readQuantifiableAssertion() {
|
113 | var start = this.index;
|
114 | return this.eatN(3, /^\(\?[=!]$/) && this.trackback(start, this.readDisjunction() && this.eat(")"));
|
115 | }
|
116 | }, {
|
117 | key: "readQuantifier",
|
118 | value: function readQuantifier() {
|
119 | return this.readQuantifierPrefix() && (this.eat("?"), true);
|
120 | }
|
121 | }, {
|
122 | key: "readQuantifierPrefix",
|
123 | value: function readQuantifierPrefix() {
|
124 | if (this.eat("*") || this.eat("+") || this.eat("?")) return true;
|
125 | if (this.eat("{") && this.readDecimalDigits()) {
|
126 | if (this.eat(",")) this.readDecimalDigits();
|
127 | return this.eat("}");
|
128 | }
|
129 | return false;
|
130 | }
|
131 | }, {
|
132 | key: "readDecimalDigits",
|
133 | value: function readDecimalDigits() {
|
134 | var start = this.index;
|
135 | while (this.eatRegExp(/^\d$/));
|
136 | return this.index > start;
|
137 | }
|
138 | }, {
|
139 | key: "readAtomNoBrace",
|
140 | value: function readAtomNoBrace() {
|
141 | var start = this.index;
|
142 | var startingParens = this.nCapturingParens;
|
143 | if (this.readPatternCharacterNoBrace() || this.eat(".")) return true;
|
144 | if (this.eat("\\")) return this.trackback(start, this.readAtomEscape());
|
145 | if (this.readCharacterClass()) return true;
|
146 | if (this.eat("(")) {
|
147 | if (!this.eatN(2, /^\?:$/)) ++this.nCapturingParens;
|
148 | if (this.readDisjunction() && this.eat(")")) return true;
|
149 | this.nCapturingParens = startingParens;
|
150 | this.index = start;
|
151 | return false;
|
152 | }
|
153 | return false;
|
154 | }
|
155 | }, {
|
156 | key: "readAtom",
|
157 | value: function readAtom() {
|
158 | return this.readAtomNoBrace() || this.eat("{") || this.eat("}");
|
159 | }
|
160 | }, {
|
161 | key: "readSyntaxCharacter",
|
162 | value: function readSyntaxCharacter() {
|
163 | return this.eatRegExp(/^[\^$\\.*+?()[\]{}|]$/);
|
164 | }
|
165 | }, {
|
166 | key: "readPatternCharacterNoBrace",
|
167 | value: function readPatternCharacterNoBrace() {
|
168 | return this.eatRegExp(/^[^\^$\\.*+?()[\]{}|]$/);
|
169 | }
|
170 | }, {
|
171 | key: "readAtomEscape",
|
172 | value: function readAtomEscape() {
|
173 | return this.readDecimalEscape() || this.readCharacterEscape() || this.readCharacterClassEscape();
|
174 | }
|
175 | }, {
|
176 | key: "readCharacterEscape",
|
177 | value: function readCharacterEscape() {
|
178 | return this.readControlEscape() || this.eat("c") && this.readControlLetter() || this.readHexEscapeSequence() || this.readRegExpUnicodeEscapeSequence() || this.readIdentityEscape();
|
179 | }
|
180 | }, {
|
181 | key: "readControlEscape",
|
182 | value: function readControlEscape() {
|
183 | return this.eatRegExp(/^[fnrtv]$/);
|
184 | }
|
185 | }, {
|
186 | key: "readControlLetter",
|
187 | value: function readControlLetter() {
|
188 | return this.eatRegExp(/^[a-zA-Z]$/);
|
189 | }
|
190 | }, {
|
191 | key: "readHexEscapeSequence",
|
192 | value: function readHexEscapeSequence() {
|
193 | return this.eat("x") && this.readHexDigit() && this.readHexDigit();
|
194 | }
|
195 | }, {
|
196 | key: "readHexDigit",
|
197 | value: function readHexDigit() {
|
198 | return this.eatRegExp(/^[a-fA-F0-9]$/);
|
199 | }
|
200 | }, {
|
201 | key: "readRegExpUnicodeEscapeSequence",
|
202 | value: function readRegExpUnicodeEscapeSequence() {
|
203 | if (!this.eat("u")) return false;
|
204 | if (this.u) {
|
205 | if (this.eatN(4, /^D[abAB89][a-fA-F0-9]{2}$/)) {
|
206 | this.eatN(6, /^\\u[dD][c-fC-F0-9][a-fA-F0-9]{2}$/);
|
207 | return true;
|
208 | }
|
209 | return this.readHex4Digits() || this.eat("{") && this.readHexDigits() && this.eat("}");
|
210 | } else {
|
211 | return this.readHex4Digits();
|
212 | }
|
213 | }
|
214 | }, {
|
215 | key: "readHex4Digits",
|
216 | value: function readHex4Digits() {
|
217 | var k = 4;
|
218 | while (k > 0) {
|
219 | --k;
|
220 | if (!this.readHexDigit()) return false;
|
221 | }
|
222 | return true;
|
223 | }
|
224 | }, {
|
225 | key: "readHexDigits",
|
226 | value: function readHexDigits() {
|
227 | var start = this.index;
|
228 | while (this.readHexDigit());
|
229 | return this.index > start;
|
230 | }
|
231 | }, {
|
232 | key: "readIdentityEscape",
|
233 | value: function readIdentityEscape() {
|
234 | if (this.u) {
|
235 | return this.readSyntaxCharacter() || this.eat("/");
|
236 | } else {
|
237 | return this.eatRegExp(/^[^a-zA-Z0-9_]$/);
|
238 | }
|
239 | }
|
240 | }, {
|
241 | key: "readDecimalEscape",
|
242 | value: function readDecimalEscape() {
|
243 | if (this.eat("0")) {
|
244 | if (!this.matchRegExp(/^\d$/)) return true;
|
245 | --this.index;
|
246 | return false;
|
247 | }
|
248 | var start = this.index;
|
249 | while (this.eatRegExp(/^\d$/));
|
250 | return this.trackback(start, this.index > start && (this.u || +this.pattern.slice(start, this.index) <= this.nCapturingParens));
|
251 | }
|
252 | }, {
|
253 | key: "readCharacterClassEscape",
|
254 | value: function readCharacterClassEscape() {
|
255 | return this.eatRegExp(/^[dDsSwW]$/);
|
256 | }
|
257 | }, {
|
258 | key: "readCharacterClass",
|
259 | value: function readCharacterClass() {
|
260 | var start = this.index;
|
261 | return this.eat("[") && this.trackback(start, (this.eat("^"), true) && this.readClassRanges() && this.eat("]"));
|
262 | }
|
263 | }, {
|
264 | key: "readClassRanges",
|
265 | value: function readClassRanges() {
|
266 | var start = this.index;
|
267 | if (!this.readNonemptyClassRanges()) {
|
268 | this.index = start;
|
269 | }
|
270 | return true;
|
271 | }
|
272 | }, {
|
273 | key: "readNonemptyClassRanges",
|
274 | value: function readNonemptyClassRanges() {
|
275 | if (!this.readClassAtom()) return false;
|
276 | if (this.match("]")) return true;
|
277 | if (this.eat("-")) {
|
278 | if (this.match("]")) return true;
|
279 | return this.readClassAtom() && this.readClassRanges();
|
280 | }
|
281 | return this.readNonemptyClassRangesNoDash();
|
282 | }
|
283 | }, {
|
284 | key: "readNonemptyClassRangesNoDash",
|
285 | value: function readNonemptyClassRangesNoDash() {
|
286 |
|
287 |
|
288 |
|
289 | if (!this.readClassAtomNoDash()) return false;
|
290 | if (this.match("]")) return true;
|
291 | if (this.eat("-")) {
|
292 | if (this.match("]")) return true;
|
293 | return this.readClassAtom() && this.readClassRanges();
|
294 | }
|
295 | return this.readNonemptyClassRangesNoDash();
|
296 | }
|
297 | }, {
|
298 | key: "readClassAtom",
|
299 | value: function readClassAtom() {
|
300 | return this.eat("-") || this.readClassAtomNoDash();
|
301 | }
|
302 | }, {
|
303 | key: "readClassAtomNoDash",
|
304 | value: function readClassAtomNoDash() {
|
305 | return this.eatRegExp(/^[^\\\]-]$/) || this.eat("\\") && this.readClassEscape();
|
306 | }
|
307 | }, {
|
308 | key: "readClassEscape",
|
309 | value: function readClassEscape() {
|
310 | return this.readDecimalEscape() || this.eat("b") || this.u && this.eat("-") || this.readCharacterEscape() || this.readCharacterClassEscape();
|
311 | }
|
312 | }], [{
|
313 | key: "test",
|
314 | value: function test(pattern, u) {
|
315 | var acceptor = new PatternAcceptor(pattern, u);
|
316 | return acceptor.readDisjunction() && acceptor.index === acceptor.length;
|
317 | }
|
318 | }]);
|
319 |
|
320 | return PatternAcceptor;
|
321 | })();
|
322 |
|
323 | exports.PatternAcceptor = PatternAcceptor; |
\ | No newline at end of file |