UNPKG

php-parser

Version:

Parse PHP code from JS and returns its AST

169 lines (164 loc) 4.98 kB
/** * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; module.exports = { /* * Reads a while statement * ```ebnf * while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';') * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L587 * @return {While} */ read_while: function () { const result = this.node("while"); this.expect(this.tok.T_WHILE) && this.next(); let test = null; let body = null; let shortForm = false; if (this.expect("(")) this.next(); test = this.read_expr(); if (this.expect(")")) this.next(); if (this.token === ":") { shortForm = true; body = this.read_short_form(this.tok.T_ENDWHILE); } else { body = this.read_statement(); } return result(test, body, shortForm); }, /* * Reads a do / while loop * ```ebnf * do ::= T_DO statement T_WHILE '(' expr ')' ';' * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L423 * @return {Do} */ read_do: function () { const result = this.node("do"); this.expect(this.tok.T_DO) && this.next(); let test = null; let body = null; body = this.read_statement(); if (this.expect(this.tok.T_WHILE)) { if (this.next().expect("(")) this.next(); test = this.read_expr(); if (this.expect(")")) this.next(); if (this.expect(";")) this.next(); } return result(test, body); }, /* * Read a for incremental loop * ```ebnf * for ::= T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement * for_statement ::= statement | ':' inner_statement_list T_ENDFOR ';' * for_exprs ::= expr? (',' expr)* * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L425 * @return {For} */ read_for: function () { const result = this.node("for"); this.expect(this.tok.T_FOR) && this.next(); let init = []; let test = []; let increment = []; let body = null; let shortForm = false; if (this.expect("(")) this.next(); if (this.token !== ";") { init = this.read_list(this.read_expr, ","); if (this.expect(";")) this.next(); } else { this.next(); } if (this.token !== ";") { test = this.read_list(this.read_expr, ","); if (this.expect(";")) this.next(); } else { this.next(); } if (this.token !== ")") { increment = this.read_list(this.read_expr, ","); if (this.expect(")")) this.next(); } else { this.next(); } if (this.token === ":") { shortForm = true; body = this.read_short_form(this.tok.T_ENDFOR); } else { body = this.read_statement(); } return result(init, test, increment, body, shortForm); }, /* * Reads a foreach loop * ```ebnf * foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L438 * @return {Foreach} */ read_foreach: function () { const result = this.node("foreach"); this.expect(this.tok.T_FOREACH) && this.next(); let source = null; let key = null; let value = null; let body = null; let shortForm = false; if (this.expect("(")) this.next(); source = this.read_expr(); if (this.expect(this.tok.T_AS)) { this.next(); value = this.read_foreach_variable(); if (this.token === this.tok.T_DOUBLE_ARROW) { key = value; value = this.next().read_foreach_variable(); } } // grammatically correct but not supported by PHP if (key && key.kind === "list") { this.raiseError("Fatal Error : Cannot use list as key element"); } if (this.expect(")")) this.next(); if (this.token === ":") { shortForm = true; body = this.read_short_form(this.tok.T_ENDFOREACH); } else { body = this.read_statement(); } return result(source, key, value, body, shortForm); }, /* * Reads a foreach variable statement * ```ebnf * foreach_variable = * variable | * '&' variable | * T_LIST '(' assignment_list ')' | * '[' assignment_list ']' * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L544 * @return {Expression} */ read_foreach_variable: function () { if (this.token === this.tok.T_LIST || this.token === "[") { const isShort = this.token === "["; const result = this.node("list"); this.next(); if (!isShort && this.expect("(")) this.next(); const assignList = this.read_array_pair_list(isShort); if (this.expect(isShort ? "]" : ")")) this.next(); return result(assignList, isShort); } else { return this.read_variable(false, false); } }, };