UNPKG

php-parser

Version:

Parse PHP code from JS and returns its AST

357 lines (346 loc) 9.59 kB
/** * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; module.exports = { T_STRING: function () { const token = this.yytext.toLowerCase(); let id = this.keywords[token]; if (typeof id !== "number") { if (token === "yield") { if (this.version >= 700 && this.tryMatch(" from")) { this.consume(5); id = this.tok.T_YIELD_FROM; } else { id = this.tok.T_YIELD; } } else { id = this.tok.T_STRING; if (token === "b" || token === "B") { const ch = this.input(); if (ch === '"') { return this.ST_DOUBLE_QUOTES(); } else if (ch === "'") { return this.T_CONSTANT_ENCAPSED_STRING(); } else if (ch) { this.unput(1); } } } } // https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1546 if (id === this.tok.T_ENUM) { if (this.version < 801) { return this.tok.T_STRING; } const initial = this.offset; let ch = this.input(); while (ch == " ") { ch = this.input(); } let isEnum = false; if (this.is_LABEL_START()) { while (this.is_LABEL()) { ch += this.input(); } const label = ch.slice(0, -1).toLowerCase(); isEnum = label !== "extends" && label !== "implements"; } this.unput(this.offset - initial); return isEnum ? this.tok.T_ENUM : this.tok.T_STRING; } if (this.offset < this.size && id !== this.tok.T_YIELD_FROM) { // If immediately followed by a backslash, this is a T_NAME_RELATIVE or T_NAME_QUALIFIED. let ch = this.input(); if (ch === "\\") { id = token === "namespace" ? this.tok.T_NAME_RELATIVE : this.tok.T_NAME_QUALIFIED; do { if (this._input[this.offset] === "{") { // e.g. when using group use statements, the last '\\' is followed by a '{' this.input(); break; } this.consume_LABEL(); ch = this.input(); } while (ch === "\\"); } if (ch) { this.unput(1); } } return id; }, // reads a custom token consume_TOKEN: function () { const ch = this._input[this.offset - 1]; const fn = this.tokenTerminals[ch]; if (fn) { return fn.apply(this, []); } else { return this.yytext; } }, // list of special char tokens tokenTerminals: { $: function () { this.offset++; if (this.is_LABEL_START()) { this.offset--; this.consume_LABEL(); return this.tok.T_VARIABLE; } else { this.offset--; return "$"; } }, "-": function () { const nchar = this._input[this.offset]; if (nchar === ">") { this.begin("ST_LOOKING_FOR_PROPERTY").input(); return this.tok.T_OBJECT_OPERATOR; } else if (nchar === "-") { this.input(); return this.tok.T_DEC; } else if (nchar === "=") { this.input(); return this.tok.T_MINUS_EQUAL; } return "-"; }, "\\": function () { if (this.offset < this.size) { this.input(); if (this.is_LABEL_START()) { let ch; do { if (this._input[this.offset] === "{") { // e.g. when using group use statements, the last '\\' is followed by a '{' this.input(); break; } this.consume_LABEL(); ch = this.input(); } while (ch === "\\"); this.unput(1); return this.tok.T_NAME_FULLY_QUALIFIED; } else { this.unput(1); } } return this.tok.T_NS_SEPARATOR; }, "/": function () { if (this._input[this.offset] === "=") { this.input(); return this.tok.T_DIV_EQUAL; } return "/"; }, ":": function () { if (this._input[this.offset] === ":") { this.input(); return this.tok.T_DOUBLE_COLON; } else { return ":"; } }, "(": function () { const initial = this.offset; this.input(); if (this.is_TABSPACE()) { this.consume_TABSPACE().input(); } if (this.is_LABEL_START()) { const yylen = this.yytext.length; this.consume_LABEL(); const castToken = this.yytext.substring(yylen - 1).toLowerCase(); const castId = this.castKeywords[castToken]; if (typeof castId === "number") { this.input(); if (this.is_TABSPACE()) { this.consume_TABSPACE().input(); } if (this._input[this.offset - 1] === ")") { return castId; } } } // revert the check this.unput(this.offset - initial); return "("; }, "=": function () { const nchar = this._input[this.offset]; if (nchar === ">") { this.input(); return this.tok.T_DOUBLE_ARROW; } else if (nchar === "=") { if (this._input[this.offset + 1] === "=") { this.consume(2); return this.tok.T_IS_IDENTICAL; } else { this.input(); return this.tok.T_IS_EQUAL; } } return "="; }, "+": function () { const nchar = this._input[this.offset]; if (nchar === "+") { this.input(); return this.tok.T_INC; } else if (nchar === "=") { this.input(); return this.tok.T_PLUS_EQUAL; } return "+"; }, "!": function () { if (this._input[this.offset] === "=") { if (this._input[this.offset + 1] === "=") { this.consume(2); return this.tok.T_IS_NOT_IDENTICAL; } else { this.input(); return this.tok.T_IS_NOT_EQUAL; } } return "!"; }, "?": function () { if (this.version >= 700 && this._input[this.offset] === "?") { if (this.version >= 704 && this._input[this.offset + 1] === "=") { this.consume(2); return this.tok.T_COALESCE_EQUAL; } else { this.input(); return this.tok.T_COALESCE; } } if ( this.version >= 800 && this._input[this.offset] === "-" && this._input[this.offset + 1] === ">" ) { this.consume(1); this.begin("ST_LOOKING_FOR_PROPERTY").input(); return this.tok.T_NULLSAFE_OBJECT_OPERATOR; } return "?"; }, "<": function () { let nchar = this._input[this.offset]; if (nchar === "<") { nchar = this._input[this.offset + 1]; if (nchar === "=") { this.consume(2); return this.tok.T_SL_EQUAL; } else if (nchar === "<") { if (this.is_HEREDOC()) { return this.tok.T_START_HEREDOC; } } this.input(); return this.tok.T_SL; } else if (nchar === "=") { this.input(); if (this.version >= 700 && this._input[this.offset] === ">") { this.input(); return this.tok.T_SPACESHIP; } else { return this.tok.T_IS_SMALLER_OR_EQUAL; } } else if (nchar === ">") { this.input(); return this.tok.T_IS_NOT_EQUAL; } return "<"; }, ">": function () { let nchar = this._input[this.offset]; if (nchar === "=") { this.input(); return this.tok.T_IS_GREATER_OR_EQUAL; } else if (nchar === ">") { nchar = this._input[this.offset + 1]; if (nchar === "=") { this.consume(2); return this.tok.T_SR_EQUAL; } else { this.input(); return this.tok.T_SR; } } return ">"; }, "*": function () { const nchar = this._input[this.offset]; if (nchar === "=") { this.input(); return this.tok.T_MUL_EQUAL; } else if (nchar === "*") { this.input(); if (this._input[this.offset] === "=") { this.input(); return this.tok.T_POW_EQUAL; } else { return this.tok.T_POW; } } return "*"; }, ".": function () { const nchar = this._input[this.offset]; if (nchar === "=") { this.input(); return this.tok.T_CONCAT_EQUAL; } else if (nchar === "." && this._input[this.offset + 1] === ".") { this.consume(2); return this.tok.T_ELLIPSIS; } return "."; }, "%": function () { if (this._input[this.offset] === "=") { this.input(); return this.tok.T_MOD_EQUAL; } return "%"; }, "&": function () { const nchar = this._input[this.offset]; if (nchar === "=") { this.input(); return this.tok.T_AND_EQUAL; } else if (nchar === "&") { this.input(); return this.tok.T_BOOLEAN_AND; } return "&"; }, "|": function () { const nchar = this._input[this.offset]; if (nchar === "=") { this.input(); return this.tok.T_OR_EQUAL; } else if (nchar === "|") { this.input(); return this.tok.T_BOOLEAN_OR; } return "|"; }, "^": function () { if (this._input[this.offset] === "=") { this.input(); return this.tok.T_XOR_EQUAL; } return "^"; }, }, };