@jorgsowa/php-parser 3.2.5-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/README.md +108 -0
- package/dist/@jorgsowa/php-parser.js +11239 -0
- package/dist/@jorgsowa/php-parser.min.js +2 -0
- package/dist/@jorgsowa/php-parser.min.js.LICENSE.txt +10 -0
- package/package.json +86 -0
- package/src/ast/array.js +44 -0
- package/src/ast/arrowfunc.js +43 -0
- package/src/ast/assign.js +28 -0
- package/src/ast/assignref.js +27 -0
- package/src/ast/attrgroup.js +21 -0
- package/src/ast/attribute.js +26 -0
- package/src/ast/bin.js +27 -0
- package/src/ast/block.js +24 -0
- package/src/ast/boolean.js +23 -0
- package/src/ast/break.js +21 -0
- package/src/ast/byref.js +21 -0
- package/src/ast/call.js +26 -0
- package/src/ast/case.js +26 -0
- package/src/ast/cast.js +28 -0
- package/src/ast/catch.js +29 -0
- package/src/ast/class.js +36 -0
- package/src/ast/classconstant.js +71 -0
- package/src/ast/clone.js +21 -0
- package/src/ast/closure.js +47 -0
- package/src/ast/comment.js +23 -0
- package/src/ast/commentblock.js +22 -0
- package/src/ast/commentline.js +22 -0
- package/src/ast/constant.js +26 -0
- package/src/ast/constantstatement.js +24 -0
- package/src/ast/continue.js +24 -0
- package/src/ast/declaration.js +60 -0
- package/src/ast/declare.js +71 -0
- package/src/ast/declaredirective.js +26 -0
- package/src/ast/do.js +26 -0
- package/src/ast/echo.js +26 -0
- package/src/ast/empty.js +23 -0
- package/src/ast/encapsed.js +75 -0
- package/src/ast/encapsedpart.js +28 -0
- package/src/ast/entry.js +30 -0
- package/src/ast/enum.js +30 -0
- package/src/ast/enumcase.js +26 -0
- package/src/ast/error.js +30 -0
- package/src/ast/eval.js +24 -0
- package/src/ast/exit.js +26 -0
- package/src/ast/expression.js +20 -0
- package/src/ast/expressionstatement.js +24 -0
- package/src/ast/for.js +33 -0
- package/src/ast/foreach.js +33 -0
- package/src/ast/function.js +34 -0
- package/src/ast/global.js +24 -0
- package/src/ast/goto.js +22 -0
- package/src/ast/halt.js +22 -0
- package/src/ast/identifier.js +26 -0
- package/src/ast/if.js +30 -0
- package/src/ast/include.js +28 -0
- package/src/ast/inline.js +23 -0
- package/src/ast/interface.js +28 -0
- package/src/ast/intersectiontype.js +24 -0
- package/src/ast/isset.js +23 -0
- package/src/ast/label.js +21 -0
- package/src/ast/list.js +26 -0
- package/src/ast/literal.js +28 -0
- package/src/ast/location.js +22 -0
- package/src/ast/lookup.js +26 -0
- package/src/ast/magic.js +22 -0
- package/src/ast/match.js +26 -0
- package/src/ast/matcharm.js +26 -0
- package/src/ast/method.js +24 -0
- package/src/ast/name.js +55 -0
- package/src/ast/namedargument.js +27 -0
- package/src/ast/namespace.js +26 -0
- package/src/ast/new.js +26 -0
- package/src/ast/node.js +111 -0
- package/src/ast/noop.js +20 -0
- package/src/ast/nowdoc.js +26 -0
- package/src/ast/nullkeyword.js +20 -0
- package/src/ast/nullsafepropertylookup.js +22 -0
- package/src/ast/number.js +23 -0
- package/src/ast/offsetlookup.js +22 -0
- package/src/ast/operation.js +19 -0
- package/src/ast/parameter.js +61 -0
- package/src/ast/parentreference.js +24 -0
- package/src/ast/position.js +22 -0
- package/src/ast/post.js +26 -0
- package/src/ast/pre.js +26 -0
- package/src/ast/print.js +23 -0
- package/src/ast/program.js +32 -0
- package/src/ast/property.js +46 -0
- package/src/ast/propertyhook.js +33 -0
- package/src/ast/propertylookup.js +22 -0
- package/src/ast/propertystatement.js +59 -0
- package/src/ast/reference.js +21 -0
- package/src/ast/retif.js +28 -0
- package/src/ast/return.js +21 -0
- package/src/ast/selfreference.js +24 -0
- package/src/ast/silent.js +24 -0
- package/src/ast/statement.js +19 -0
- package/src/ast/static.js +24 -0
- package/src/ast/staticlookup.js +22 -0
- package/src/ast/staticreference.js +24 -0
- package/src/ast/staticvariable.js +26 -0
- package/src/ast/string.js +28 -0
- package/src/ast/switch.js +28 -0
- package/src/ast/throw.js +21 -0
- package/src/ast/trait.js +24 -0
- package/src/ast/traitalias.js +44 -0
- package/src/ast/traitprecedence.js +28 -0
- package/src/ast/traituse.js +26 -0
- package/src/ast/try.js +28 -0
- package/src/ast/typereference.js +40 -0
- package/src/ast/unary.js +26 -0
- package/src/ast/uniontype.js +24 -0
- package/src/ast/unset.js +23 -0
- package/src/ast/usegroup.js +30 -0
- package/src/ast/useitem.js +45 -0
- package/src/ast/variable.js +36 -0
- package/src/ast/variadic.js +25 -0
- package/src/ast/variadicplaceholder.js +24 -0
- package/src/ast/while.js +28 -0
- package/src/ast/yield.js +27 -0
- package/src/ast/yieldfrom.js +25 -0
- package/src/ast.js +593 -0
- package/src/index.js +239 -0
- package/src/lexer/attribute.js +85 -0
- package/src/lexer/comments.js +63 -0
- package/src/lexer/initial.js +64 -0
- package/src/lexer/numbers.js +171 -0
- package/src/lexer/property.js +96 -0
- package/src/lexer/scripting.js +114 -0
- package/src/lexer/strings.js +524 -0
- package/src/lexer/tokens.js +356 -0
- package/src/lexer/utils.js +112 -0
- package/src/lexer.js +561 -0
- package/src/parser/array.js +113 -0
- package/src/parser/class.js +718 -0
- package/src/parser/comment.js +52 -0
- package/src/parser/enum.js +56 -0
- package/src/parser/expr.js +848 -0
- package/src/parser/function.js +507 -0
- package/src/parser/if.js +94 -0
- package/src/parser/loops.js +168 -0
- package/src/parser/main.js +21 -0
- package/src/parser/namespace.js +231 -0
- package/src/parser/scalar.js +492 -0
- package/src/parser/statement.js +444 -0
- package/src/parser/switch.js +99 -0
- package/src/parser/try.js +43 -0
- package/src/parser/utils.js +203 -0
- package/src/parser/variable.js +363 -0
- package/src/parser.js +748 -0
- package/src/tokens.js +177 -0
- package/types.d.ts +1457 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2018 Glayzzle (BSD3 License)
|
|
3
|
+
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
|
|
4
|
+
* @url http://glayzzle.com
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const newline = ["\n", "\r"];
|
|
9
|
+
const valid_after_heredoc = ["\n", "\r", ";"];
|
|
10
|
+
const valid_after_heredoc_73 = valid_after_heredoc.concat([
|
|
11
|
+
"\t",
|
|
12
|
+
" ",
|
|
13
|
+
",",
|
|
14
|
+
"]",
|
|
15
|
+
")",
|
|
16
|
+
"/",
|
|
17
|
+
"=",
|
|
18
|
+
"!",
|
|
19
|
+
".",
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
T_CONSTANT_ENCAPSED_STRING() {
|
|
24
|
+
let ch;
|
|
25
|
+
while (this.offset < this.size) {
|
|
26
|
+
ch = this.input();
|
|
27
|
+
if (ch == "\\") {
|
|
28
|
+
this.input();
|
|
29
|
+
} else if (ch == "'") {
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return this.tok.T_CONSTANT_ENCAPSED_STRING;
|
|
34
|
+
},
|
|
35
|
+
// check if matching a HEREDOC state
|
|
36
|
+
is_HEREDOC() {
|
|
37
|
+
const revert = this.offset;
|
|
38
|
+
if (
|
|
39
|
+
this._input[this.offset - 1] === "<" &&
|
|
40
|
+
this._input[this.offset] === "<" &&
|
|
41
|
+
this._input[this.offset + 1] === "<"
|
|
42
|
+
) {
|
|
43
|
+
this.offset += 3;
|
|
44
|
+
|
|
45
|
+
// optional tabs / spaces
|
|
46
|
+
if (this.is_TABSPACE()) {
|
|
47
|
+
while (this.offset < this.size) {
|
|
48
|
+
this.offset++;
|
|
49
|
+
if (!this.is_TABSPACE()) {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// optional quotes
|
|
56
|
+
let tChar = this._input[this.offset - 1];
|
|
57
|
+
if (tChar === "'" || tChar === '"') {
|
|
58
|
+
this.offset++;
|
|
59
|
+
} else {
|
|
60
|
+
tChar = null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// required label
|
|
64
|
+
if (this.is_LABEL_START()) {
|
|
65
|
+
let yyoffset = this.offset - 1;
|
|
66
|
+
while (this.offset < this.size) {
|
|
67
|
+
this.offset++;
|
|
68
|
+
if (!this.is_LABEL()) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const yylabel = this._input.substring(yyoffset, this.offset - 1);
|
|
73
|
+
if (!tChar || tChar === this._input[this.offset - 1]) {
|
|
74
|
+
// required ending quote
|
|
75
|
+
if (tChar) this.offset++;
|
|
76
|
+
// require newline
|
|
77
|
+
if (newline.includes(this._input[this.offset - 1])) {
|
|
78
|
+
// go go go
|
|
79
|
+
this.heredoc_label.label = yylabel;
|
|
80
|
+
this.heredoc_label.length = yylabel.length;
|
|
81
|
+
this.heredoc_label.finished = false;
|
|
82
|
+
yyoffset = this.offset - revert;
|
|
83
|
+
this.offset = revert;
|
|
84
|
+
this.consume(yyoffset);
|
|
85
|
+
if (tChar === "'") {
|
|
86
|
+
this.begin("ST_NOWDOC");
|
|
87
|
+
} else {
|
|
88
|
+
this.begin("ST_HEREDOC");
|
|
89
|
+
}
|
|
90
|
+
// prematch to get the indentation information from end of doc
|
|
91
|
+
this.prematch_ENDOFDOC();
|
|
92
|
+
return this.tok.T_START_HEREDOC;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
this.offset = revert;
|
|
98
|
+
return false;
|
|
99
|
+
},
|
|
100
|
+
ST_DOUBLE_QUOTES() {
|
|
101
|
+
let ch;
|
|
102
|
+
while (this.offset < this.size) {
|
|
103
|
+
ch = this.input();
|
|
104
|
+
if (ch == "\\") {
|
|
105
|
+
this.input();
|
|
106
|
+
} else if (ch == '"') {
|
|
107
|
+
break;
|
|
108
|
+
} else if (ch == "$") {
|
|
109
|
+
ch = this.input();
|
|
110
|
+
if (ch == "{" || this.is_LABEL_START()) {
|
|
111
|
+
this.unput(2);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
if (ch) this.unput(1);
|
|
115
|
+
} else if (ch == "{") {
|
|
116
|
+
ch = this.input();
|
|
117
|
+
if (ch == "$") {
|
|
118
|
+
this.unput(2);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (ch) this.unput(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (ch == '"') {
|
|
125
|
+
return this.tok.T_CONSTANT_ENCAPSED_STRING;
|
|
126
|
+
} else {
|
|
127
|
+
let prefix = 1;
|
|
128
|
+
if (this.yytext[0] === "b" || this.yytext[0] === "B") {
|
|
129
|
+
prefix = 2;
|
|
130
|
+
}
|
|
131
|
+
if (this.yytext.length > 2) {
|
|
132
|
+
this.appendToken(
|
|
133
|
+
this.tok.T_ENCAPSED_AND_WHITESPACE,
|
|
134
|
+
this.yytext.length - prefix,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
this.unput(this.yytext.length - prefix);
|
|
138
|
+
this.begin("ST_DOUBLE_QUOTES");
|
|
139
|
+
return this.yytext;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// check if its a DOC end sequence
|
|
144
|
+
isDOC_MATCH(offset, consumeLeadingSpaces) {
|
|
145
|
+
// @fixme : check if out of text limits
|
|
146
|
+
|
|
147
|
+
// consumeLeadingSpaces is false happen DOC prematch END HEREDOC stage.
|
|
148
|
+
|
|
149
|
+
// Ensure current state is really after a new line break, not after a such as ${variables}
|
|
150
|
+
const prev_ch = this._input[offset - 2];
|
|
151
|
+
if (!newline.includes(prev_ch)) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// skip leading spaces or tabs
|
|
156
|
+
let indentation_uses_spaces = false;
|
|
157
|
+
let indentation_uses_tabs = false;
|
|
158
|
+
// reset heredoc_label structure
|
|
159
|
+
let indentation = 0;
|
|
160
|
+
let leading_ch = this._input[offset - 1];
|
|
161
|
+
|
|
162
|
+
if (this.version >= 703) {
|
|
163
|
+
while (leading_ch === "\t" || leading_ch === " ") {
|
|
164
|
+
if (leading_ch === " ") {
|
|
165
|
+
indentation_uses_spaces = true;
|
|
166
|
+
} else if (leading_ch === "\t") {
|
|
167
|
+
indentation_uses_tabs = true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
leading_ch = this._input[offset + indentation];
|
|
171
|
+
indentation++;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Move offset to skip leading whitespace
|
|
175
|
+
offset = offset + indentation;
|
|
176
|
+
|
|
177
|
+
// return out if there was only whitespace on this line
|
|
178
|
+
if (newline.includes(this._input[offset - 1])) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
this._input.substring(
|
|
185
|
+
offset - 1,
|
|
186
|
+
offset - 1 + this.heredoc_label.length,
|
|
187
|
+
) === this.heredoc_label.label
|
|
188
|
+
) {
|
|
189
|
+
const ch = this._input[offset - 1 + this.heredoc_label.length];
|
|
190
|
+
if (
|
|
191
|
+
(this.version >= 703
|
|
192
|
+
? valid_after_heredoc_73
|
|
193
|
+
: valid_after_heredoc
|
|
194
|
+
).includes(ch)
|
|
195
|
+
) {
|
|
196
|
+
if (consumeLeadingSpaces) {
|
|
197
|
+
this.consume(indentation);
|
|
198
|
+
// https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes
|
|
199
|
+
if (indentation_uses_spaces && indentation_uses_tabs) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
"Parse error: mixing spaces and tabs in ending marker at line " +
|
|
202
|
+
this.yylineno +
|
|
203
|
+
" (offset " +
|
|
204
|
+
this.offset +
|
|
205
|
+
")",
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
// Called in prematch_ENDOFDOC
|
|
210
|
+
this.heredoc_label.indentation = indentation;
|
|
211
|
+
this.heredoc_label.indentation_uses_spaces = indentation_uses_spaces;
|
|
212
|
+
this.heredoc_label.first_encaps_node = true;
|
|
213
|
+
}
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return false;
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
/*
|
|
222
|
+
* Prematch the end of HEREDOC/NOWDOC end tag to preset the
|
|
223
|
+
* context of this.heredoc_label
|
|
224
|
+
*/
|
|
225
|
+
prematch_ENDOFDOC() {
|
|
226
|
+
// reset heredoc
|
|
227
|
+
this.heredoc_label.indentation_uses_spaces = false;
|
|
228
|
+
this.heredoc_label.indentation = 0;
|
|
229
|
+
this.heredoc_label.first_encaps_node = true;
|
|
230
|
+
let offset = this.offset + 1;
|
|
231
|
+
|
|
232
|
+
while (offset < this._input.length) {
|
|
233
|
+
// if match heredoc_label structrue will be set
|
|
234
|
+
if (this.isDOC_MATCH(offset, false)) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!newline.includes(this._input[offset - 1])) {
|
|
239
|
+
// skip one line
|
|
240
|
+
while (
|
|
241
|
+
!newline.includes(this._input[offset++]) &&
|
|
242
|
+
offset < this._input.length
|
|
243
|
+
) {
|
|
244
|
+
// skip
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
offset++;
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
matchST_NOWDOC() {
|
|
253
|
+
// edge case : empty now doc
|
|
254
|
+
if (this.isDOC_MATCH(this.offset, true)) {
|
|
255
|
+
// @fixme : never reached (may be caused by quotes)
|
|
256
|
+
this.consume(this.heredoc_label.length);
|
|
257
|
+
this.popState();
|
|
258
|
+
return this.tok.T_END_HEREDOC;
|
|
259
|
+
}
|
|
260
|
+
// SCANNING CONTENTS
|
|
261
|
+
let ch = this._input[this.offset - 1];
|
|
262
|
+
while (this.offset < this.size) {
|
|
263
|
+
if (newline.includes(ch)) {
|
|
264
|
+
ch = this.input();
|
|
265
|
+
if (this.isDOC_MATCH(this.offset, true)) {
|
|
266
|
+
this.unput(1).popState();
|
|
267
|
+
this.appendToken(this.tok.T_END_HEREDOC, this.heredoc_label.length);
|
|
268
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
ch = this.input();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// too bad ! reached end of document (will get a parse error)
|
|
275
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
matchST_HEREDOC() {
|
|
279
|
+
// edge case : empty here doc
|
|
280
|
+
let ch = this.input();
|
|
281
|
+
if (this.isDOC_MATCH(this.offset, true)) {
|
|
282
|
+
this.consume(this.heredoc_label.length - 1);
|
|
283
|
+
this.popState();
|
|
284
|
+
return this.tok.T_END_HEREDOC;
|
|
285
|
+
}
|
|
286
|
+
// SCANNING CONTENTS
|
|
287
|
+
while (this.offset < this.size) {
|
|
288
|
+
if (ch === "\\") {
|
|
289
|
+
ch = this.input(); // ignore next
|
|
290
|
+
if (!newline.includes(ch)) {
|
|
291
|
+
ch = this.input();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (newline.includes(ch)) {
|
|
296
|
+
ch = this.input();
|
|
297
|
+
if (this.isDOC_MATCH(this.offset, true)) {
|
|
298
|
+
this.unput(1).popState();
|
|
299
|
+
this.appendToken(this.tok.T_END_HEREDOC, this.heredoc_label.length);
|
|
300
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
301
|
+
}
|
|
302
|
+
} else if (ch === "$") {
|
|
303
|
+
ch = this.input();
|
|
304
|
+
if (ch === "{") {
|
|
305
|
+
// start of ${
|
|
306
|
+
this.begin("ST_LOOKING_FOR_VARNAME");
|
|
307
|
+
if (this.yytext.length > 2) {
|
|
308
|
+
this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
|
|
309
|
+
this.unput(2);
|
|
310
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
311
|
+
} else {
|
|
312
|
+
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
|
|
313
|
+
}
|
|
314
|
+
} else if (this.is_LABEL_START()) {
|
|
315
|
+
// start of $var...
|
|
316
|
+
const yyoffset = this.offset;
|
|
317
|
+
const next = this.consume_VARIABLE();
|
|
318
|
+
if (this.yytext.length > this.offset - yyoffset + 2) {
|
|
319
|
+
this.appendToken(next, this.offset - yyoffset + 2);
|
|
320
|
+
this.unput(this.offset - yyoffset + 2);
|
|
321
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
322
|
+
} else {
|
|
323
|
+
return next;
|
|
324
|
+
}
|
|
325
|
+
//console.log(this.yytext);
|
|
326
|
+
}
|
|
327
|
+
} else if (ch === "{") {
|
|
328
|
+
ch = this.input();
|
|
329
|
+
if (ch === "$") {
|
|
330
|
+
// start of {$...
|
|
331
|
+
this.begin("ST_IN_SCRIPTING");
|
|
332
|
+
if (this.yytext.length > 2) {
|
|
333
|
+
this.appendToken(this.tok.T_CURLY_OPEN, 1);
|
|
334
|
+
this.unput(2);
|
|
335
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
336
|
+
} else {
|
|
337
|
+
this.unput(1);
|
|
338
|
+
return this.tok.T_CURLY_OPEN;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
ch = this.input();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// too bad ! reached end of document (will get a parse error)
|
|
347
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
consume_VARIABLE() {
|
|
351
|
+
this.consume_LABEL();
|
|
352
|
+
const ch = this.input();
|
|
353
|
+
if (ch == "[") {
|
|
354
|
+
this.unput(1);
|
|
355
|
+
this.begin("ST_VAR_OFFSET");
|
|
356
|
+
return this.tok.T_VARIABLE;
|
|
357
|
+
} else if (ch === "-") {
|
|
358
|
+
if (this.input() === ">") {
|
|
359
|
+
this.input();
|
|
360
|
+
if (this.is_LABEL_START()) {
|
|
361
|
+
this.begin("ST_LOOKING_FOR_PROPERTY");
|
|
362
|
+
}
|
|
363
|
+
this.unput(3);
|
|
364
|
+
return this.tok.T_VARIABLE;
|
|
365
|
+
} else {
|
|
366
|
+
this.unput(2);
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
if (ch) this.unput(1);
|
|
370
|
+
}
|
|
371
|
+
return this.tok.T_VARIABLE;
|
|
372
|
+
},
|
|
373
|
+
// HANDLES BACKQUOTES
|
|
374
|
+
matchST_BACKQUOTE() {
|
|
375
|
+
let ch = this.input();
|
|
376
|
+
if (ch === "$") {
|
|
377
|
+
ch = this.input();
|
|
378
|
+
if (ch === "{") {
|
|
379
|
+
this.begin("ST_LOOKING_FOR_VARNAME");
|
|
380
|
+
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
|
|
381
|
+
} else if (this.is_LABEL_START()) {
|
|
382
|
+
const tok = this.consume_VARIABLE();
|
|
383
|
+
return tok;
|
|
384
|
+
}
|
|
385
|
+
} else if (ch === "{") {
|
|
386
|
+
if (this._input[this.offset] === "$") {
|
|
387
|
+
this.begin("ST_IN_SCRIPTING");
|
|
388
|
+
return this.tok.T_CURLY_OPEN;
|
|
389
|
+
}
|
|
390
|
+
} else if (ch === "`") {
|
|
391
|
+
this.popState();
|
|
392
|
+
return "`";
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// any char
|
|
396
|
+
while (this.offset < this.size) {
|
|
397
|
+
if (ch === "\\") {
|
|
398
|
+
this.input();
|
|
399
|
+
} else if (ch === "`") {
|
|
400
|
+
this.unput(1);
|
|
401
|
+
this.popState();
|
|
402
|
+
this.appendToken("`", 1);
|
|
403
|
+
break;
|
|
404
|
+
} else if (ch === "$") {
|
|
405
|
+
ch = this.input();
|
|
406
|
+
if (ch === "{") {
|
|
407
|
+
this.begin("ST_LOOKING_FOR_VARNAME");
|
|
408
|
+
if (this.yytext.length > 2) {
|
|
409
|
+
this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
|
|
410
|
+
this.unput(2);
|
|
411
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
412
|
+
} else {
|
|
413
|
+
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
|
|
414
|
+
}
|
|
415
|
+
} else if (this.is_LABEL_START()) {
|
|
416
|
+
// start of $var...
|
|
417
|
+
const yyoffset = this.offset;
|
|
418
|
+
const next = this.consume_VARIABLE();
|
|
419
|
+
if (this.yytext.length > this.offset - yyoffset + 2) {
|
|
420
|
+
this.appendToken(next, this.offset - yyoffset + 2);
|
|
421
|
+
this.unput(this.offset - yyoffset + 2);
|
|
422
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
423
|
+
} else {
|
|
424
|
+
return next;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
continue;
|
|
428
|
+
} else if (ch === "{") {
|
|
429
|
+
ch = this.input();
|
|
430
|
+
if (ch === "$") {
|
|
431
|
+
// start of {$...
|
|
432
|
+
this.begin("ST_IN_SCRIPTING");
|
|
433
|
+
if (this.yytext.length > 2) {
|
|
434
|
+
this.appendToken(this.tok.T_CURLY_OPEN, 1);
|
|
435
|
+
this.unput(2);
|
|
436
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
437
|
+
} else {
|
|
438
|
+
this.unput(1);
|
|
439
|
+
return this.tok.T_CURLY_OPEN;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
ch = this.input();
|
|
445
|
+
}
|
|
446
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
matchST_DOUBLE_QUOTES() {
|
|
450
|
+
let ch = this.input();
|
|
451
|
+
if (ch === "$") {
|
|
452
|
+
ch = this.input();
|
|
453
|
+
if (ch === "{") {
|
|
454
|
+
this.begin("ST_LOOKING_FOR_VARNAME");
|
|
455
|
+
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
|
|
456
|
+
} else if (this.is_LABEL_START()) {
|
|
457
|
+
const tok = this.consume_VARIABLE();
|
|
458
|
+
return tok;
|
|
459
|
+
}
|
|
460
|
+
} else if (ch === "{") {
|
|
461
|
+
if (this._input[this.offset] === "$") {
|
|
462
|
+
this.begin("ST_IN_SCRIPTING");
|
|
463
|
+
return this.tok.T_CURLY_OPEN;
|
|
464
|
+
}
|
|
465
|
+
} else if (ch === '"') {
|
|
466
|
+
this.popState();
|
|
467
|
+
return '"';
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// any char
|
|
471
|
+
while (this.offset < this.size) {
|
|
472
|
+
if (ch === "\\") {
|
|
473
|
+
this.input();
|
|
474
|
+
} else if (ch === '"') {
|
|
475
|
+
this.unput(1);
|
|
476
|
+
this.popState();
|
|
477
|
+
this.appendToken('"', 1);
|
|
478
|
+
break;
|
|
479
|
+
} else if (ch === "$") {
|
|
480
|
+
ch = this.input();
|
|
481
|
+
if (ch === "{") {
|
|
482
|
+
this.begin("ST_LOOKING_FOR_VARNAME");
|
|
483
|
+
if (this.yytext.length > 2) {
|
|
484
|
+
this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
|
|
485
|
+
this.unput(2);
|
|
486
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
487
|
+
} else {
|
|
488
|
+
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
|
|
489
|
+
}
|
|
490
|
+
} else if (this.is_LABEL_START()) {
|
|
491
|
+
// start of $var...
|
|
492
|
+
const yyoffset = this.offset;
|
|
493
|
+
const next = this.consume_VARIABLE();
|
|
494
|
+
if (this.yytext.length > this.offset - yyoffset + 2) {
|
|
495
|
+
this.appendToken(next, this.offset - yyoffset + 2);
|
|
496
|
+
this.unput(this.offset - yyoffset + 2);
|
|
497
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
498
|
+
} else {
|
|
499
|
+
return next;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (ch) this.unput(1);
|
|
503
|
+
} else if (ch === "{") {
|
|
504
|
+
ch = this.input();
|
|
505
|
+
if (ch === "$") {
|
|
506
|
+
// start of {$...
|
|
507
|
+
this.begin("ST_IN_SCRIPTING");
|
|
508
|
+
if (this.yytext.length > 2) {
|
|
509
|
+
this.appendToken(this.tok.T_CURLY_OPEN, 1);
|
|
510
|
+
this.unput(2);
|
|
511
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
512
|
+
} else {
|
|
513
|
+
// @fixme : yytext = '"{$' (this.yytext.length > 3)
|
|
514
|
+
this.unput(1);
|
|
515
|
+
return this.tok.T_CURLY_OPEN;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (ch) this.unput(1);
|
|
519
|
+
}
|
|
520
|
+
ch = this.input();
|
|
521
|
+
}
|
|
522
|
+
return this.tok.T_ENCAPSED_AND_WHITESPACE;
|
|
523
|
+
},
|
|
524
|
+
};
|