php-parser
Version:
Parse PHP code from JS and returns its AST
172 lines (165 loc) • 4.24 kB
JavaScript
/**
* Copyright (C) 2018 Glayzzle (BSD3 License)
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
* @url http://glayzzle.com
*/
"use strict";
/* istanbul ignore else */
let MAX_LENGTH_OF_LONG = 10;
let long_min_digits = "2147483648";
if (process.arch == "x64") {
MAX_LENGTH_OF_LONG = 19;
long_min_digits = "9223372036854775808";
}
module.exports = {
consume_NUM: function () {
let ch = this.yytext[0];
let hasPoint = ch === ".";
if (ch === "0") {
ch = this.input();
// check if hexa
if (ch === "x" || ch === "X") {
ch = this.input();
if (ch !== "_" && this.is_HEX()) {
return this.consume_HNUM();
} else {
this.unput(ch ? 2 : 1);
}
// check binary notation
} else if (ch === "b" || ch === "B") {
ch = this.input();
if ((ch !== "_" && ch === "0") || ch === "1") {
return this.consume_BNUM();
} else {
this.unput(ch ? 2 : 1);
}
} else if (ch === "o" || ch === "O") {
ch = this.input();
if (ch !== "_" && this.is_OCTAL()) {
return this.consume_ONUM();
} else {
this.unput(ch ? 2 : 1);
}
} else if (!this.is_NUM()) {
if (ch) this.unput(1);
}
}
while (this.offset < this.size) {
const prev = ch;
ch = this.input();
if (ch === "_") {
if (prev === "_") {
// restriction : next to underscore / 1__1;
this.unput(2); // keep 1
break;
}
if (prev === ".") {
// next to decimal point "1._0"
this.unput(1); // keep 1.
break;
}
if (prev === "e" || prev === "E") {
// next to e "1e_10"
this.unput(2); // keep 1
break;
}
} else if (ch === ".") {
if (hasPoint) {
// no multiple points "1.0.5"
this.unput(1); // keep 1.0
break;
}
if (prev === "_") {
// next to decimal point "1_.0"
this.unput(2); // keep 1
break;
}
hasPoint = true;
continue;
} else if (ch === "e" || ch === "E") {
if (prev === "_") {
// next to e "1_e10"
this.unput(1);
break;
}
let undo = 2;
ch = this.input();
if (ch === "+" || ch === "-") {
// 1e-5
undo = 3;
ch = this.input();
}
if (this.is_NUM_START()) {
this.consume_LNUM();
return this.tok.T_DNUMBER;
}
this.unput(ch ? undo : undo - 1); // keep only 1
break;
}
if (!this.is_NUM()) {
// example : 10.0a
if (ch) this.unput(1); // keep 10.0
break;
}
}
if (hasPoint) {
return this.tok.T_DNUMBER;
} else if (this.yytext.length < MAX_LENGTH_OF_LONG - 1) {
return this.tok.T_LNUMBER;
} else {
if (
this.yytext.length < MAX_LENGTH_OF_LONG ||
(this.yytext.length == MAX_LENGTH_OF_LONG &&
this.yytext < long_min_digits)
) {
return this.tok.T_LNUMBER;
}
return this.tok.T_DNUMBER;
}
},
// read hexa
consume_HNUM: function () {
while (this.offset < this.size) {
const ch = this.input();
if (!this.is_HEX()) {
if (ch) this.unput(1);
break;
}
}
return this.tok.T_LNUMBER;
},
// read a generic number
consume_LNUM: function () {
while (this.offset < this.size) {
const ch = this.input();
if (!this.is_NUM()) {
if (ch) this.unput(1);
break;
}
}
return this.tok.T_LNUMBER;
},
// read binary
consume_BNUM: function () {
let ch;
while (this.offset < this.size) {
ch = this.input();
if (ch !== "0" && ch !== "1" && ch !== "_") {
if (ch) this.unput(1);
break;
}
}
return this.tok.T_LNUMBER;
},
// read an octal number
consume_ONUM: function () {
while (this.offset < this.size) {
const ch = this.input();
if (!this.is_OCTAL()) {
if (ch) this.unput(1);
break;
}
}
return this.tok.T_LNUMBER;
},
};