@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.
Files changed (153) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +108 -0
  3. package/dist/@jorgsowa/php-parser.js +11239 -0
  4. package/dist/@jorgsowa/php-parser.min.js +2 -0
  5. package/dist/@jorgsowa/php-parser.min.js.LICENSE.txt +10 -0
  6. package/package.json +86 -0
  7. package/src/ast/array.js +44 -0
  8. package/src/ast/arrowfunc.js +43 -0
  9. package/src/ast/assign.js +28 -0
  10. package/src/ast/assignref.js +27 -0
  11. package/src/ast/attrgroup.js +21 -0
  12. package/src/ast/attribute.js +26 -0
  13. package/src/ast/bin.js +27 -0
  14. package/src/ast/block.js +24 -0
  15. package/src/ast/boolean.js +23 -0
  16. package/src/ast/break.js +21 -0
  17. package/src/ast/byref.js +21 -0
  18. package/src/ast/call.js +26 -0
  19. package/src/ast/case.js +26 -0
  20. package/src/ast/cast.js +28 -0
  21. package/src/ast/catch.js +29 -0
  22. package/src/ast/class.js +36 -0
  23. package/src/ast/classconstant.js +71 -0
  24. package/src/ast/clone.js +21 -0
  25. package/src/ast/closure.js +47 -0
  26. package/src/ast/comment.js +23 -0
  27. package/src/ast/commentblock.js +22 -0
  28. package/src/ast/commentline.js +22 -0
  29. package/src/ast/constant.js +26 -0
  30. package/src/ast/constantstatement.js +24 -0
  31. package/src/ast/continue.js +24 -0
  32. package/src/ast/declaration.js +60 -0
  33. package/src/ast/declare.js +71 -0
  34. package/src/ast/declaredirective.js +26 -0
  35. package/src/ast/do.js +26 -0
  36. package/src/ast/echo.js +26 -0
  37. package/src/ast/empty.js +23 -0
  38. package/src/ast/encapsed.js +75 -0
  39. package/src/ast/encapsedpart.js +28 -0
  40. package/src/ast/entry.js +30 -0
  41. package/src/ast/enum.js +30 -0
  42. package/src/ast/enumcase.js +26 -0
  43. package/src/ast/error.js +30 -0
  44. package/src/ast/eval.js +24 -0
  45. package/src/ast/exit.js +26 -0
  46. package/src/ast/expression.js +20 -0
  47. package/src/ast/expressionstatement.js +24 -0
  48. package/src/ast/for.js +33 -0
  49. package/src/ast/foreach.js +33 -0
  50. package/src/ast/function.js +34 -0
  51. package/src/ast/global.js +24 -0
  52. package/src/ast/goto.js +22 -0
  53. package/src/ast/halt.js +22 -0
  54. package/src/ast/identifier.js +26 -0
  55. package/src/ast/if.js +30 -0
  56. package/src/ast/include.js +28 -0
  57. package/src/ast/inline.js +23 -0
  58. package/src/ast/interface.js +28 -0
  59. package/src/ast/intersectiontype.js +24 -0
  60. package/src/ast/isset.js +23 -0
  61. package/src/ast/label.js +21 -0
  62. package/src/ast/list.js +26 -0
  63. package/src/ast/literal.js +28 -0
  64. package/src/ast/location.js +22 -0
  65. package/src/ast/lookup.js +26 -0
  66. package/src/ast/magic.js +22 -0
  67. package/src/ast/match.js +26 -0
  68. package/src/ast/matcharm.js +26 -0
  69. package/src/ast/method.js +24 -0
  70. package/src/ast/name.js +55 -0
  71. package/src/ast/namedargument.js +27 -0
  72. package/src/ast/namespace.js +26 -0
  73. package/src/ast/new.js +26 -0
  74. package/src/ast/node.js +111 -0
  75. package/src/ast/noop.js +20 -0
  76. package/src/ast/nowdoc.js +26 -0
  77. package/src/ast/nullkeyword.js +20 -0
  78. package/src/ast/nullsafepropertylookup.js +22 -0
  79. package/src/ast/number.js +23 -0
  80. package/src/ast/offsetlookup.js +22 -0
  81. package/src/ast/operation.js +19 -0
  82. package/src/ast/parameter.js +61 -0
  83. package/src/ast/parentreference.js +24 -0
  84. package/src/ast/position.js +22 -0
  85. package/src/ast/post.js +26 -0
  86. package/src/ast/pre.js +26 -0
  87. package/src/ast/print.js +23 -0
  88. package/src/ast/program.js +32 -0
  89. package/src/ast/property.js +46 -0
  90. package/src/ast/propertyhook.js +33 -0
  91. package/src/ast/propertylookup.js +22 -0
  92. package/src/ast/propertystatement.js +59 -0
  93. package/src/ast/reference.js +21 -0
  94. package/src/ast/retif.js +28 -0
  95. package/src/ast/return.js +21 -0
  96. package/src/ast/selfreference.js +24 -0
  97. package/src/ast/silent.js +24 -0
  98. package/src/ast/statement.js +19 -0
  99. package/src/ast/static.js +24 -0
  100. package/src/ast/staticlookup.js +22 -0
  101. package/src/ast/staticreference.js +24 -0
  102. package/src/ast/staticvariable.js +26 -0
  103. package/src/ast/string.js +28 -0
  104. package/src/ast/switch.js +28 -0
  105. package/src/ast/throw.js +21 -0
  106. package/src/ast/trait.js +24 -0
  107. package/src/ast/traitalias.js +44 -0
  108. package/src/ast/traitprecedence.js +28 -0
  109. package/src/ast/traituse.js +26 -0
  110. package/src/ast/try.js +28 -0
  111. package/src/ast/typereference.js +40 -0
  112. package/src/ast/unary.js +26 -0
  113. package/src/ast/uniontype.js +24 -0
  114. package/src/ast/unset.js +23 -0
  115. package/src/ast/usegroup.js +30 -0
  116. package/src/ast/useitem.js +45 -0
  117. package/src/ast/variable.js +36 -0
  118. package/src/ast/variadic.js +25 -0
  119. package/src/ast/variadicplaceholder.js +24 -0
  120. package/src/ast/while.js +28 -0
  121. package/src/ast/yield.js +27 -0
  122. package/src/ast/yieldfrom.js +25 -0
  123. package/src/ast.js +593 -0
  124. package/src/index.js +239 -0
  125. package/src/lexer/attribute.js +85 -0
  126. package/src/lexer/comments.js +63 -0
  127. package/src/lexer/initial.js +64 -0
  128. package/src/lexer/numbers.js +171 -0
  129. package/src/lexer/property.js +96 -0
  130. package/src/lexer/scripting.js +114 -0
  131. package/src/lexer/strings.js +524 -0
  132. package/src/lexer/tokens.js +356 -0
  133. package/src/lexer/utils.js +112 -0
  134. package/src/lexer.js +561 -0
  135. package/src/parser/array.js +113 -0
  136. package/src/parser/class.js +718 -0
  137. package/src/parser/comment.js +52 -0
  138. package/src/parser/enum.js +56 -0
  139. package/src/parser/expr.js +848 -0
  140. package/src/parser/function.js +507 -0
  141. package/src/parser/if.js +94 -0
  142. package/src/parser/loops.js +168 -0
  143. package/src/parser/main.js +21 -0
  144. package/src/parser/namespace.js +231 -0
  145. package/src/parser/scalar.js +492 -0
  146. package/src/parser/statement.js +444 -0
  147. package/src/parser/switch.js +99 -0
  148. package/src/parser/try.js +43 -0
  149. package/src/parser/utils.js +203 -0
  150. package/src/parser/variable.js +363 -0
  151. package/src/parser.js +748 -0
  152. package/src/tokens.js +177 -0
  153. package/types.d.ts +1457 -0
package/src/index.js ADDED
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Copyright (C) 2020 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 lexer = require("./lexer");
9
+ const parser = require("./parser");
10
+ const tokens = require("./tokens");
11
+ const AST = require("./ast");
12
+
13
+ /**
14
+ * @private
15
+ */
16
+ function combine(src, to) {
17
+ const keys = Object.keys(src);
18
+ let i = keys.length;
19
+ while (i--) {
20
+ const k = keys[i];
21
+ const val = src[k];
22
+ if (val === null) {
23
+ delete to[k];
24
+ } else if (typeof val === "function") {
25
+ to[k] = val.bind(to);
26
+ } else if (Array.isArray(val)) {
27
+ to[k] = Array.isArray(to[k]) ? to[k].concat(val) : val;
28
+ } else if (typeof val === "object") {
29
+ to[k] = typeof to[k] === "object" ? combine(val, to[k]) : val;
30
+ } else {
31
+ to[k] = val;
32
+ }
33
+ }
34
+ return to;
35
+ }
36
+
37
+ /**
38
+ * Initialise a new parser instance with the specified options
39
+ *
40
+ * @class
41
+ * @memberOf module:php-parser
42
+ * @tutorial Engine
43
+ * @example
44
+ * var parser = require('php-parser');
45
+ * var instance = new parser({
46
+ * parser: {
47
+ * extractDoc: true,
48
+ * suppressErrors: true,
49
+ * version: 704 // or '7.4'
50
+ * },
51
+ * ast: {
52
+ * withPositions: true
53
+ * },
54
+ * lexer: {
55
+ * short_tags: true,
56
+ * asp_tags: true
57
+ * }
58
+ * });
59
+ *
60
+ * var evalAST = instance.parseEval('some php code');
61
+ * var codeAST = instance.parseCode('<?php some php code', 'foo.php');
62
+ * var tokens = instance.tokenGetAll('<?php some php code');
63
+ *
64
+ * @param {Object} options - List of options
65
+ * @property {Lexer} lexer
66
+ * @property {Parser} parser
67
+ * @property {AST} ast
68
+ * @property {Object} tokens
69
+ */
70
+ const Engine = function (options) {
71
+ if (typeof this === "function") {
72
+ return new this(options);
73
+ }
74
+ this.tokens = tokens;
75
+ this.lexer = new lexer(this);
76
+ this.ast = new AST();
77
+ this.parser = new parser(this.lexer, this.ast);
78
+ if (options && typeof options === "object") {
79
+ // disable php7 from lexer if already disabled from parser
80
+ if (options.parser) {
81
+ if (!options.lexer) {
82
+ options.lexer = {};
83
+ }
84
+ if (options.parser.version) {
85
+ if (typeof options.parser.version === "string") {
86
+ let version = options.parser.version.split(".");
87
+ version = parseInt(version[0]) * 100 + parseInt(version[1]);
88
+ if (isNaN(version)) {
89
+ throw new Error("Bad version number : " + options.parser.version);
90
+ } else {
91
+ options.parser.version = version;
92
+ }
93
+ } else if (typeof options.parser.version !== "number") {
94
+ throw new Error("Expecting a number for version");
95
+ }
96
+ if (options.parser.version < 500 || options.parser.version > 900) {
97
+ throw new Error("Can only handle versions between 5.x to 8.x");
98
+ }
99
+ }
100
+ }
101
+ combine(options, this);
102
+
103
+ // same version flags based on parser options
104
+ this.lexer.version = this.parser.version;
105
+ }
106
+ };
107
+
108
+ /**
109
+ * Check if the inpyt is a buffer or a string
110
+ * @private
111
+ * @param {Buffer|String} buffer Input value that can be either a buffer or a string
112
+ * @return {String} Returns the string from input
113
+ */
114
+ const getStringBuffer = function (buffer) {
115
+ return typeof buffer.write === "function" ? buffer.toString() : buffer;
116
+ };
117
+
118
+ /**
119
+ * Creates a new instance (Helper)
120
+ * @param {Object} options
121
+ * @return {Engine}
122
+ * @private
123
+ */
124
+ Engine.create = function (options) {
125
+ return new Engine(options);
126
+ };
127
+
128
+ /**
129
+ * Evaluate the buffer
130
+ * @private
131
+ */
132
+ Engine.parseEval = function (buffer, options) {
133
+ const self = new Engine(options);
134
+ return self.parseEval(buffer);
135
+ };
136
+
137
+ /**
138
+ * Parse an evaluating mode string (no need to open php tags)
139
+ * @param {String} buffer
140
+ * @return {Program}
141
+ */
142
+ Engine.prototype.parseEval = function (buffer) {
143
+ this.lexer.mode_eval = true;
144
+ this.lexer.all_tokens = false;
145
+ buffer = getStringBuffer(buffer);
146
+ return this.parser.parse(buffer, "eval");
147
+ };
148
+
149
+ /**
150
+ * Static function that parse a php code with open/close tags
151
+ * @private
152
+ */
153
+ Engine.parseCode = function (buffer, filename, options) {
154
+ if (typeof filename === "object" && !options) {
155
+ // retro-compatibility
156
+ options = filename;
157
+ filename = "unknown";
158
+ }
159
+ const self = new Engine(options);
160
+ return self.parseCode(buffer, filename);
161
+ };
162
+
163
+ /**
164
+ * Function that parse a php code with open/close tags
165
+ *
166
+ * Sample code :
167
+ * ```php
168
+ * <?php $x = 1;
169
+ * ```
170
+ *
171
+ * Usage :
172
+ * ```js
173
+ * var parser = require('php-parser');
174
+ * var phpParser = new parser({
175
+ * // some options
176
+ * });
177
+ * var ast = phpParser.parseCode('...php code...', 'foo.php');
178
+ * ```
179
+ * @param {String} buffer - The code to be parsed
180
+ * @param {String} filename - Filename
181
+ * @return {Program}
182
+ */
183
+ Engine.prototype.parseCode = function (buffer, filename) {
184
+ this.lexer.mode_eval = false;
185
+ this.lexer.all_tokens = false;
186
+ buffer = getStringBuffer(buffer);
187
+ return this.parser.parse(buffer, filename);
188
+ };
189
+
190
+ /**
191
+ * Split the buffer into tokens
192
+ * @private
193
+ */
194
+ Engine.tokenGetAll = function (buffer, options) {
195
+ const self = new Engine(options);
196
+ return self.tokenGetAll(buffer);
197
+ };
198
+
199
+ /**
200
+ * Extract tokens from the specified buffer.
201
+ * > Note that the output tokens are *STRICLY* similar to PHP function `token_get_all`
202
+ * @param {string} buffer
203
+ * @return {Array<string|string[]>} - Each item can be a string or an array with following informations [token_name, text, line_number]
204
+ */
205
+ Engine.prototype.tokenGetAll = function (buffer) {
206
+ this.lexer.mode_eval = false;
207
+ this.lexer.all_tokens = true;
208
+ buffer = getStringBuffer(buffer);
209
+ const EOF = this.lexer.EOF;
210
+ const names = this.tokens.values;
211
+ this.lexer.setInput(buffer);
212
+ let token = this.lexer.lex() || EOF;
213
+ const result = [];
214
+ while (token != EOF) {
215
+ let entry = this.lexer.yytext;
216
+ if (Object.prototype.hasOwnProperty.call(names, token)) {
217
+ entry = [names[token], entry, this.lexer.yylloc.first_line];
218
+ }
219
+ result.push(entry);
220
+ token = this.lexer.lex() || EOF;
221
+ }
222
+ return result;
223
+ };
224
+
225
+ /** @module php-parser */
226
+
227
+ // exports the function
228
+ module.exports = Engine;
229
+
230
+ // makes libraries public
231
+ module.exports.tokens = tokens;
232
+ module.exports.lexer = lexer;
233
+ module.exports.AST = AST;
234
+ module.exports.parser = parser;
235
+ module.exports.combine = combine;
236
+ module.exports.Engine = Engine;
237
+
238
+ // allow the default export in index.d.ts
239
+ module.exports.default = Engine;
@@ -0,0 +1,85 @@
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
+ module.exports = {
9
+ attributeIndex: 0,
10
+ attributeListDepth: {},
11
+ matchST_ATTRIBUTE() {
12
+ let ch = this.input();
13
+ if (this.is_WHITESPACE()) {
14
+ do {
15
+ ch = this.input();
16
+ } while (this.is_WHITESPACE());
17
+ this.unput(1);
18
+ return null;
19
+ }
20
+ switch (ch) {
21
+ case "]":
22
+ if (this.attributeListDepth[this.attributeIndex] === 0) {
23
+ delete this.attributeListDepth[this.attributeIndex];
24
+ this.attributeIndex--;
25
+ this.popState();
26
+ } else {
27
+ /* istanbul ignore next */
28
+ this.attributeListDepth[this.attributeIndex]--;
29
+ }
30
+ return "]";
31
+ case "(":
32
+ case ")":
33
+ case ":":
34
+ case "=":
35
+ case "|":
36
+ case "&":
37
+ case "^":
38
+ case "-":
39
+ case "+":
40
+ case "*":
41
+ case "%":
42
+ case "~":
43
+ case "<":
44
+ case ">":
45
+ case "!":
46
+ case ".":
47
+ return this.consume_TOKEN();
48
+ case "[":
49
+ this.attributeListDepth[this.attributeIndex]++;
50
+ return "[";
51
+ case ",":
52
+ return ",";
53
+ case '"':
54
+ return this.ST_DOUBLE_QUOTES();
55
+ case "'":
56
+ return this.T_CONSTANT_ENCAPSED_STRING();
57
+ case "/":
58
+ if (this._input[this.offset] === "/") {
59
+ return this.T_COMMENT();
60
+ } else if (this._input[this.offset] === "*") {
61
+ this.input();
62
+ return this.T_DOC_COMMENT();
63
+ } else {
64
+ return this.consume_TOKEN();
65
+ }
66
+ }
67
+ if (this.is_LABEL_START() || ch === "\\") {
68
+ while (this.offset < this.size) {
69
+ const ch = this.input();
70
+ if (!(this.is_LABEL() || ch === "\\")) {
71
+ if (ch) this.unput(1);
72
+ break;
73
+ }
74
+ }
75
+ return this.T_STRING();
76
+ } else if (this.is_NUM()) {
77
+ return this.consume_NUM();
78
+ }
79
+
80
+ /* istanbul ignore next */
81
+ throw new Error(
82
+ `Bad terminal sequence "${ch}" at line ${this.yylineno} (offset ${this.offset})`,
83
+ );
84
+ },
85
+ };
@@ -0,0 +1,63 @@
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
+ module.exports = {
9
+ /*
10
+ * Reads a single line comment
11
+ */
12
+ T_COMMENT() {
13
+ while (this.offset < this.size) {
14
+ const ch = this.input();
15
+ if (ch === "\n" || ch === "\r") {
16
+ return this.tok.T_COMMENT;
17
+ } else if (
18
+ ch === "?" &&
19
+ !this.aspTagMode &&
20
+ this._input[this.offset] === ">"
21
+ ) {
22
+ this.unput(1);
23
+ return this.tok.T_COMMENT;
24
+ } else if (
25
+ ch === "%" &&
26
+ this.aspTagMode &&
27
+ this._input[this.offset] === ">"
28
+ ) {
29
+ this.unput(1);
30
+ return this.tok.T_COMMENT;
31
+ }
32
+ }
33
+ return this.tok.T_COMMENT;
34
+ },
35
+ /*
36
+ * Behaviour : https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1927
37
+ */
38
+ T_DOC_COMMENT() {
39
+ let ch = this.input();
40
+ let token = this.tok.T_COMMENT;
41
+ if (ch === "*") {
42
+ // started with '/*' , check is next is '*'
43
+ ch = this.input();
44
+ if (this.is_WHITESPACE()) {
45
+ // check if next is WHITESPACE
46
+ token = this.tok.T_DOC_COMMENT;
47
+ }
48
+ if (ch === "/") {
49
+ return token;
50
+ } else {
51
+ this.unput(1); // reset
52
+ }
53
+ }
54
+ while (this.offset < this.size) {
55
+ ch = this.input();
56
+ if (ch === "*" && this._input[this.offset] === "/") {
57
+ this.input();
58
+ break;
59
+ }
60
+ }
61
+ return token;
62
+ },
63
+ };
@@ -0,0 +1,64 @@
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
+ module.exports = {
9
+ nextINITIAL() {
10
+ if (
11
+ this.conditionStack.length > 1 &&
12
+ this.conditionStack[this.conditionStack.length - 1] === "INITIAL"
13
+ ) {
14
+ // Return to HEREDOC/ST_DOUBLE_QUOTES mode
15
+ this.popState();
16
+ } else {
17
+ this.begin("ST_IN_SCRIPTING");
18
+ }
19
+ return this;
20
+ },
21
+ matchINITIAL() {
22
+ while (this.offset < this.size) {
23
+ let ch = this.input();
24
+ if (ch == "<") {
25
+ ch = this.ahead(1);
26
+ if (ch == "?") {
27
+ if (this.tryMatch("?=")) {
28
+ this.unput(1)
29
+ .appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3)
30
+ .nextINITIAL();
31
+ break;
32
+ } else if (this.tryMatchCaseless("?php")) {
33
+ ch = this._input[this.offset + 4];
34
+ if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
35
+ this.unput(1).appendToken(this.tok.T_OPEN_TAG, 6).nextINITIAL();
36
+ break;
37
+ }
38
+ }
39
+ if (this.short_tags) {
40
+ this.unput(1).appendToken(this.tok.T_OPEN_TAG, 2).nextINITIAL();
41
+ break;
42
+ }
43
+ } else if (this.asp_tags && ch == "%") {
44
+ if (this.tryMatch("%=")) {
45
+ this.aspTagMode = true;
46
+ this.unput(1)
47
+ .appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3)
48
+ .nextINITIAL();
49
+ break;
50
+ } else {
51
+ this.aspTagMode = true;
52
+ this.unput(1).appendToken(this.tok.T_OPEN_TAG, 2).nextINITIAL();
53
+ break;
54
+ }
55
+ }
56
+ }
57
+ }
58
+ if (this.yytext.length > 0) {
59
+ return this.tok.T_INLINE_HTML;
60
+ } else {
61
+ return false;
62
+ }
63
+ },
64
+ };
@@ -0,0 +1,171 @@
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
+ /* istanbul ignore else */
9
+ let MAX_LENGTH_OF_LONG = 10;
10
+ let long_min_digits = "2147483648";
11
+ if (process.arch == "x64") {
12
+ MAX_LENGTH_OF_LONG = 19;
13
+ long_min_digits = "9223372036854775808";
14
+ }
15
+
16
+ module.exports = {
17
+ consume_NUM() {
18
+ let ch = this.yytext[0];
19
+ let hasPoint = ch === ".";
20
+ if (ch === "0") {
21
+ ch = this.input();
22
+ // check if hexa
23
+ if (ch === "x" || ch === "X") {
24
+ ch = this.input();
25
+ if (ch !== "_" && this.is_HEX()) {
26
+ return this.consume_HNUM();
27
+ } else {
28
+ this.unput(ch ? 2 : 1);
29
+ }
30
+ // check binary notation
31
+ } else if (ch === "b" || ch === "B") {
32
+ ch = this.input();
33
+ if ((ch !== "_" && ch === "0") || ch === "1") {
34
+ return this.consume_BNUM();
35
+ } else {
36
+ this.unput(ch ? 2 : 1);
37
+ }
38
+ } else if (ch === "o" || ch === "O") {
39
+ ch = this.input();
40
+ if (ch !== "_" && this.is_OCTAL()) {
41
+ return this.consume_ONUM();
42
+ } else {
43
+ this.unput(ch ? 2 : 1);
44
+ }
45
+ } else if (!this.is_NUM()) {
46
+ if (ch) this.unput(1);
47
+ }
48
+ }
49
+
50
+ while (this.offset < this.size) {
51
+ const prev = ch;
52
+ ch = this.input();
53
+
54
+ if (ch === "_") {
55
+ if (prev === "_") {
56
+ // restriction : next to underscore / 1__1;
57
+ this.unput(2); // keep 1
58
+ break;
59
+ }
60
+ if (prev === ".") {
61
+ // next to decimal point "1._0"
62
+ this.unput(1); // keep 1.
63
+ break;
64
+ }
65
+ if (prev === "e" || prev === "E") {
66
+ // next to e "1e_10"
67
+ this.unput(2); // keep 1
68
+ break;
69
+ }
70
+ } else if (ch === ".") {
71
+ if (hasPoint) {
72
+ // no multiple points "1.0.5"
73
+ this.unput(1); // keep 1.0
74
+ break;
75
+ }
76
+ if (prev === "_") {
77
+ // next to decimal point "1_.0"
78
+ this.unput(2); // keep 1
79
+ break;
80
+ }
81
+ hasPoint = true;
82
+ continue;
83
+ } else if (ch === "e" || ch === "E") {
84
+ if (prev === "_") {
85
+ // next to e "1_e10"
86
+ this.unput(1);
87
+ break;
88
+ }
89
+ let undo = 2;
90
+ ch = this.input();
91
+ if (ch === "+" || ch === "-") {
92
+ // 1e-5
93
+ undo = 3;
94
+ ch = this.input();
95
+ }
96
+ if (this.is_NUM_START()) {
97
+ this.consume_LNUM();
98
+ return this.tok.T_DNUMBER;
99
+ }
100
+ this.unput(ch ? undo : undo - 1); // keep only 1
101
+ break;
102
+ }
103
+
104
+ if (!this.is_NUM()) {
105
+ // example : 10.0a
106
+ if (ch) this.unput(1); // keep 10.0
107
+ break;
108
+ }
109
+ }
110
+
111
+ if (hasPoint) {
112
+ return this.tok.T_DNUMBER;
113
+ } else if (this.yytext.length < MAX_LENGTH_OF_LONG - 1) {
114
+ return this.tok.T_LNUMBER;
115
+ } else {
116
+ if (
117
+ this.yytext.length < MAX_LENGTH_OF_LONG ||
118
+ (this.yytext.length == MAX_LENGTH_OF_LONG &&
119
+ this.yytext < long_min_digits)
120
+ ) {
121
+ return this.tok.T_LNUMBER;
122
+ }
123
+ return this.tok.T_DNUMBER;
124
+ }
125
+ },
126
+ // read hexa
127
+ consume_HNUM() {
128
+ while (this.offset < this.size) {
129
+ const ch = this.input();
130
+ if (!this.is_HEX()) {
131
+ if (ch) this.unput(1);
132
+ break;
133
+ }
134
+ }
135
+ return this.tok.T_LNUMBER;
136
+ },
137
+ // read a generic number
138
+ consume_LNUM() {
139
+ while (this.offset < this.size) {
140
+ const ch = this.input();
141
+ if (!this.is_NUM()) {
142
+ if (ch) this.unput(1);
143
+ break;
144
+ }
145
+ }
146
+ return this.tok.T_LNUMBER;
147
+ },
148
+ // read binary
149
+ consume_BNUM() {
150
+ let ch;
151
+ while (this.offset < this.size) {
152
+ ch = this.input();
153
+ if (ch !== "0" && ch !== "1" && ch !== "_") {
154
+ if (ch) this.unput(1);
155
+ break;
156
+ }
157
+ }
158
+ return this.tok.T_LNUMBER;
159
+ },
160
+ // read an octal number
161
+ consume_ONUM() {
162
+ while (this.offset < this.size) {
163
+ const ch = this.input();
164
+ if (!this.is_OCTAL()) {
165
+ if (ch) this.unput(1);
166
+ break;
167
+ }
168
+ }
169
+ return this.tok.T_LNUMBER;
170
+ },
171
+ };