php-parser
Advanced tools
Comparing version 2.0.0-pre1 to 2.0.0-pre2
{ | ||
"name": "php-parser", | ||
"version": "2.0.0-pre1", | ||
"version": "2.0.0-pre2", | ||
"description": "Parse PHP 5/7 code and returns its AST", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -1,11 +0,12 @@ | ||
<h1 align="center">php-parser</h1> | ||
<p align="center"> | ||
<a href="https://travis-ci.org/glayzzle/php-parser"><img src="https://travis-ci.org/glayzzle/php-parser.svg"></a> | ||
<a href="https://coveralls.io/github/glayzzle/php-parser?branch=master"><img src="https://coveralls.io/repos/github/glayzzle/php-parser/badge.svg?branch=master&v=20170115" alt="Coverage Status" /></a> | ||
<a title="npm version" href="https://www.npmjs.com/package/php-parser"><img src="https://badge.fury.io/js/php-parser.svg"></a> | ||
<a title="npm downloads" href="https://www.npmjs.com/package/php-parser"><img src="https://img.shields.io/npm/dm/php-parser.svg?style=flat"></a> | ||
<a title="Gitter" href="https://gitter.im/glayzzle/Lobby"><img src="https://img.shields.io/badge/GITTER-join%20chat-green.svg"></a> | ||
</p> | ||
<p align="center">This javascript library parses PHP code and convert it to AST.</p> | ||
php-parser | ||
========== | ||
This javascript library parses PHP code and convert it to AST. | ||
[](https://www.npmjs.com/package/php-parser) | ||
[](https://travis-ci.org/glayzzle/php-parser) | ||
[](https://coveralls.io/r/glayzzle/php-parser) | ||
[](https://gitter.im/glayzzle/Lobby) | ||
Installation | ||
@@ -12,0 +13,0 @@ ------------ |
@@ -15,3 +15,3 @@ /*! | ||
* - [Position](#position) | ||
* - [Node](#Node) | ||
* - [Node](#node) | ||
* - [Identifier](#identifier) | ||
@@ -38,2 +38,3 @@ * - [TraitUse](#traituse) | ||
* - [Operation](#operation) | ||
* - [Coalesce](#coalesce) | ||
* - [Pre](#pre) | ||
@@ -43,2 +44,3 @@ * - [Post](#post) | ||
* - [Parenthesis](#parenthesis) | ||
* - [Bool](#Bool) | ||
* - [Unary](#unary) | ||
@@ -121,2 +123,3 @@ * - [Cast](#cast) | ||
* @return {Position} | ||
* @private | ||
*/ | ||
@@ -189,2 +192,3 @@ AST.prototype.position = function(parser) { | ||
require('./ast/block'), | ||
require('./ast/bool'), | ||
require('./ast/boolean'), | ||
@@ -200,2 +204,3 @@ require('./ast/break'), | ||
require('./ast/closure'), | ||
require('./ast/coalesce'), | ||
require('./ast/constant'), | ||
@@ -202,0 +207,0 @@ require('./ast/constref'), |
@@ -11,40 +11,12 @@ /*! | ||
// operators in ascending order of precedence | ||
var binOperatorsPrecedence = [ | ||
['or'], | ||
['xor'], | ||
['and'], | ||
// TODO: assignment | ||
// TODO: ternary ? : | ||
['??'], | ||
['||'], | ||
['&&'], | ||
['|'], | ||
['^'], | ||
['&'], | ||
['==', '!=', '===', '!==', /* '<>', */ '<=>'], | ||
['<', '<=', '>', '>='], | ||
['<<', '>>'], | ||
['+', '-', '.'], | ||
['*', '/', '%'], | ||
// TODO: unary ! | ||
['instanceof'], | ||
// TODO: unary ++, --, ~, @, typecasts | ||
// TODO: [ (array) | ||
// TODO: clone, new | ||
]; | ||
// define nodes shifting | ||
var precedence = {}; | ||
binOperatorsPrecedence.forEach(function (list, index) { | ||
list.forEach(function (operator) { | ||
precedence[operator] = index + 1; | ||
}); | ||
}); | ||
var precedence = { | ||
'+': 1, | ||
'-': 1, | ||
'.': 1, | ||
'*': 2, | ||
'/': 2, | ||
'%': 2 | ||
}; | ||
/* | ||
x OP1 (y OP2 z) | ||
z OP1 (x OP2 y) | ||
z OP2 (x OP1 y) | ||
*/ | ||
/** | ||
@@ -72,5 +44,2 @@ * Binary operations | ||
type = buffer; | ||
buffer = left; | ||
left = right; | ||
right = buffer; | ||
} | ||
@@ -77,0 +46,0 @@ } |
@@ -13,3 +13,3 @@ /*! | ||
* Defines a catch statement | ||
* @constructor Try | ||
* @constructor Catch | ||
* @extends {Statement} | ||
@@ -16,0 +16,0 @@ * @property {Identifier[]} what |
@@ -15,2 +15,3 @@ /*! | ||
* @property {Parameter[]} arguments | ||
* @property {Variable[]} uses | ||
* @property {Identifier} type | ||
@@ -21,4 +22,5 @@ * @property {boolean} byref | ||
*/ | ||
var Closure = Statement.extends(function Closure(args, byref, type, nullable, location) { | ||
var Closure = Statement.extends(function Closure(args, byref, uses, type, nullable, location) { | ||
Statement.apply(this, [KIND, location]); | ||
this.uses = uses; | ||
this.arguments = args; | ||
@@ -25,0 +27,0 @@ this.byref = byref; |
@@ -259,3 +259,3 @@ /*! | ||
/** outputs some debug information on current token **/ | ||
var ignoreStack = ['parser.next', 'parser.nextWithComments']; | ||
var ignoreStack = ['parser.next', 'parser.ignoreComments', 'parser.nextWithComments']; | ||
parser.prototype.showlog = function() { | ||
@@ -262,0 +262,0 @@ var stack = (new Error()).stack.split('\n'); |
@@ -151,3 +151,3 @@ /*! | ||
this.expect(this.tok.T_VARIABLE); | ||
var name = this.text(); | ||
var name = this.text().substring(1); // ignore $ prefix | ||
this.next(); | ||
@@ -154,0 +154,0 @@ if (this.token === ';' || this.token === ',') { |
@@ -38,33 +38,33 @@ /*! | ||
return result('bin', '>>', expr, this.next().read_expr()); | ||
// more binary operations (formerly bool) | ||
// boolean operations | ||
if (this.token === this.tok.T_BOOLEAN_OR) | ||
return result('bin', '||', expr, this.next().read_expr()); | ||
return result('bool', '|', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_LOGICAL_OR) | ||
return result('bin', 'or', expr, this.next().read_expr()); | ||
return result('bool', '|', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_BOOLEAN_AND) | ||
return result('bin', '&&', expr, this.next().read_expr()); | ||
return result('bool', '&', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_LOGICAL_AND) | ||
return result('bin', 'and', expr, this.next().read_expr()); | ||
return result('bool', '&', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_LOGICAL_XOR) | ||
return result('bin', 'xor', expr, this.next().read_expr()); | ||
return result('bool', '^', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_IS_IDENTICAL) | ||
return result('bin', '===', expr, this.next().read_expr()); | ||
return result('bool', '=', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_IS_NOT_IDENTICAL) | ||
return result('bin', '!==', expr, this.next().read_expr()); | ||
return result('bool', '!=', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_IS_EQUAL) | ||
return result('bin', '==', expr, this.next().read_expr()); | ||
return result('bool', '~', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_IS_NOT_EQUAL) | ||
return result('bin', '!=', expr, this.next().read_expr()); | ||
return result('bool', '!~', expr, this.next().read_expr()); | ||
if (this.token === '<') | ||
return result('bin', '<', expr, this.next().read_expr()); | ||
return result('bool', '<', expr, this.next().read_expr()); | ||
if (this.token === '>') | ||
return result('bin', '>', expr, this.next().read_expr()); | ||
return result('bool', '!~', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_IS_SMALLER_OR_EQUAL) | ||
return result('bin', '<=', expr, this.next().read_expr()); | ||
return result('bool', '<=', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_IS_GREATER_OR_EQUAL) | ||
return result('bin', '>=', expr, this.next().read_expr()); | ||
return result('bool', '=>', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_SPACESHIP) | ||
return result('bin', '<=>', expr, this.next().read_expr()); | ||
return result('bool', '<=>', expr, this.next().read_expr()); | ||
if (this.token === this.tok.T_INSTANCEOF) | ||
return result('bin', 'instanceof', expr, this.next().read_expr()); | ||
return result('bool', '?', expr, this.next().read_expr()); | ||
@@ -74,3 +74,3 @@ // extra operations : | ||
if (this.token === this.tok.T_COALESCE) | ||
return result('bin', '??', expr, this.next().read_expr()); | ||
return result('coalesce', expr, this.next().read_expr()); | ||
@@ -77,0 +77,0 @@ // extra operations : |
@@ -106,14 +106,12 @@ /*! | ||
,read_lexical_var: function() { | ||
var result = [false, null]; | ||
var result = this.node('variable'); | ||
var isRef = false; | ||
if (this.token === '&') { | ||
result[0] = true; | ||
isRef = true; | ||
this.next(); | ||
} | ||
if (this.token === this.tok.T_VARIABLE) { | ||
result[1] = this.text(); | ||
this.next(); | ||
} else { | ||
this.expect(['&', this.tok.T_VARIABLE]); | ||
} | ||
return result; | ||
this.expect(this.tok.T_VARIABLE); | ||
var name = this.text().substring(1); | ||
this.next(); | ||
return result(name, isRef); | ||
} | ||
@@ -166,3 +164,3 @@ /** | ||
if (this.expect(this.tok.T_VARIABLE)) { | ||
name = this.text(); | ||
name = this.text().substring(1); | ||
this.next(); | ||
@@ -169,0 +167,0 @@ } |
@@ -12,3 +12,3 @@ /*! | ||
* ```ebnf | ||
* if ::= '(' expr ')' ':' ... | ||
* if ::= T_IF '(' expr ')' ':' ... | ||
* ``` | ||
@@ -29,4 +29,3 @@ */ | ||
var items = []; | ||
while(this.token != this.EOF && this.token !== this.tok.T_ENDIF) { | ||
this.ignoreComments(); | ||
while(this.token !== this.EOF && this.token !== this.tok.T_ENDIF) { | ||
if (this.token === this.tok.T_ELSEIF) { | ||
@@ -42,6 +41,9 @@ alternate = this.next().read_elseif_short(); | ||
body = body(null, items); | ||
if (this.ignoreComments().expect(this.tok.T_ENDIF)) this.next(); | ||
this.expect(this.tok.T_ENDIF) && this.next(); | ||
this.expectEndOfStatement(); | ||
} else { | ||
body = this.read_statement(); | ||
/** | ||
* ignore : if (..) { } /* *./ else { } | ||
*/ | ||
this.ignoreComments(); | ||
@@ -60,5 +62,5 @@ if (this.token === this.tok.T_ELSEIF) { | ||
read_if_expr: function() { | ||
if (this.expect('(')) this.next(); | ||
this.expect('(') && this.next(); | ||
var result = this.read_expr(); | ||
if (this.expect(')')) this.next(); | ||
this.expect(')') && this.next(); | ||
return result; | ||
@@ -65,0 +67,0 @@ }, |
@@ -47,3 +47,3 @@ /*! | ||
body = this.read_statement(); | ||
if (this.expect(this.tok.T_WHILE)) { | ||
if (this.ignoreComments().expect(this.tok.T_WHILE)) { | ||
if (this.next().expect('(')) this.next(); | ||
@@ -117,3 +117,3 @@ test = this.read_expr(); | ||
source = this.read_expr(); | ||
if (this.expect(this.tok.T_AS)) { | ||
if (this.ignoreComments().expect(this.tok.T_AS)) { | ||
this.next(); | ||
@@ -120,0 +120,0 @@ value = this.read_foreach_variable(); |
@@ -25,3 +25,5 @@ /*! | ||
this.currentNamespace = ['']; | ||
return result([''], this.read_code_block(true), true); | ||
var body = this.nextWithComments().read_top_statements(); | ||
this.expect('}') && this.nextWithComments(); | ||
return result([''], body, true); | ||
} else { | ||
@@ -33,6 +35,8 @@ var name = this.read_namespace_name(); | ||
this.expect(this.EOF); | ||
return result(name, body); | ||
return result(name, body, false); | ||
} else if (this.token == '{') { | ||
this.currentNamespace = name; | ||
return result(name, this.read_code_block(true), true); | ||
var body = this.nextWithComments().read_top_statements(); | ||
this.expect('}') && this.nextWithComments(); | ||
return result(name, body, true); | ||
} else if (this.token === '(') { | ||
@@ -51,3 +55,3 @@ // resolve ambuiguity between namespace & function call | ||
this.expect(this.EOF); | ||
return result(name, body); | ||
return result(name, body, false); | ||
} | ||
@@ -54,0 +58,0 @@ } |
@@ -296,3 +296,3 @@ /*! | ||
} else { | ||
this.expect(';') && this.next(); | ||
this.expect(';') && this.nextWithComments(); | ||
while(this.token != this.EOF && this.token !== this.tok.T_DECLARE) { | ||
@@ -329,5 +329,9 @@ // @todo : check declare_statement from php / not valid | ||
// default fallback expr | ||
//console.log(this.lexer.offset); | ||
this.lexer.tokens.push(current); | ||
var expr = this.next().read_expr(); | ||
this.expect([';', this.tok.T_CLOSE_TAG]) && this.nextWithComments(); | ||
//console.log(this.lexer.offset); | ||
this.expect([';', this.tok.T_CLOSE_TAG]); | ||
this.nextWithComments(); | ||
//console.log(this.lexer.offset, this.lexer.size); | ||
return expr; | ||
@@ -334,0 +338,0 @@ } |
@@ -25,6 +25,5 @@ /*! | ||
; | ||
body = this.nextWithComments().read_statement(); | ||
this.ignoreComments(); | ||
body = this.next().read_statement(); | ||
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L455 | ||
while(this.token === this.tok.T_CATCH) { | ||
while(this.ignoreComments().token === this.tok.T_CATCH) { | ||
var item = this.node('catch'), what = [], variable = null; | ||
@@ -37,7 +36,8 @@ this.next().expect('(') && this.next(); | ||
this.expect(')'); | ||
catches.push(item(this.next().read_statement(), what, variable)); | ||
this.ignoreComments(); | ||
catches.push( | ||
item(this.next().read_statement(), what, variable) | ||
); | ||
} | ||
if (this.token === this.tok.T_FINALLY) { | ||
always = this.nextWithComments().read_statement(); | ||
always = this.next().read_statement(); | ||
} | ||
@@ -44,0 +44,0 @@ return result(body, catches, always); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
2227430
260
16195
108