Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 27 additions & 25 deletions src/parser/expr.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,7 @@ module.exports = {
const node = this.node("parenthesis");
expr = this.next().read_expr();
this.expect(")") && this.next();
expr = node(expr);
// handle dereferencable
if (this.token === this.tok.T_OBJECT_OPERATOR) {
return this.recursive_variable_chain_scan(expr, false);
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") {
return this.read_dereferencable(expr);
} else if (this.token === "(") {
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118
return this.node("call")(expr, this.read_function_argument_list());
} else {
return expr;
}
return this.handleDereferencable(node(expr));
}

if (this.token === "`") {
Expand Down Expand Up @@ -185,6 +174,15 @@ module.exports = {
}
}

if (this.token === "[") {
expr = this.read_array();
if (this.token === "=") {
return this.node("assign")(expr, this.next().read_expr(), "=");
} else {
return this.handleDereferencable(expr);
}
}

if (this.token === this.tok.T_CLONE)
return this.node("clone")(this.next().read_expr());

Expand Down Expand Up @@ -417,19 +415,7 @@ module.exports = {
}
} else if (this.is("SCALAR")) {
expr = this.read_scalar();
// handle dereferencable
while (this.token !== this.EOF) {
if (this.token === this.tok.T_OBJECT_OPERATOR) {
expr = this.recursive_variable_chain_scan(expr, false);
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") {
expr = this.read_dereferencable(expr);
} else if (this.token === "(") {
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118
expr = this.node("call")(expr, this.read_function_argument_list());
} else {
return expr;
}
}
return this.handleDereferencable(expr);
} else {
this.error("EXPR");
this.next();
Expand Down Expand Up @@ -521,5 +507,21 @@ module.exports = {
result = ["key", result, this.next().read_expr_item()];
}
return result;
},

handleDereferencable: function(expr) {
while (this.token !== this.EOF) {
if (this.token === this.tok.T_OBJECT_OPERATOR) {
expr = this.recursive_variable_chain_scan(expr, false);
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") {
expr = this.read_dereferencable(expr);
} else if (this.token === "(") {
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118
expr = this.node("call")(expr, this.read_function_argument_list());
} else {
return expr;
}
}
return expr;
}
};
34 changes: 21 additions & 13 deletions test/variableTests.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
var parser = require("./main");

describe("Test variables", function() {
describe("array destructuring", function() {
// Get result from parser
var ast = parser.parseEval("[$id1, $name1] = $data[0];");
it("should be assign with array", function() {
ast.children[0].kind.should.be.exactly("assign");
ast.children[0].left.kind.should.be.exactly("array");
ast.children[0].operator.should.be.exactly("=");
});
});

describe("Default variables", function() {
var ast = parser.parseEval(
['$a = "foo";', "$b = &$c;", "$a->b = true;"].join("\n")
Expand Down Expand Up @@ -197,11 +207,9 @@ describe("Test variables", function() {
astErr.errors[0].line.should.be.exactly(1);
astErr.errors[0].message.should.be.exactly(msg);
});

it("should fail on property lookup on static lookup", function() {
var astErr = parser.parseEval([
"$this->foo::bar->baz;"
].join('\n'), {
var astErr = parser.parseEval(["$this->foo::bar->baz;"].join("\n"), {
parser: {
suppressErrors: true
}
Expand All @@ -213,27 +221,27 @@ describe("Test variables", function() {
astErr.errors[0].line.should.be.exactly(1);
astErr.errors[0].message.should.be.exactly(msg);
});
it('should fail $foo->bar::!', function() {
var errAst = parser.parseEval('$foo->bar::!', {

it("should fail $foo->bar::!", function() {
var errAst = parser.parseEval("$foo->bar::!", {
parser: {
suppressErrors: true
}
});
errAst.errors.length.should.be.exactly(1);
errAst.errors[0].token.should.be.exactly('\'!\'');
errAst.children[0].kind.should.be.exactly('staticlookup');
errAst.children[0].offset.name.should.be.exactly('!');
errAst.errors[0].token.should.be.exactly("'!'");
errAst.children[0].kind.should.be.exactly("staticlookup");
errAst.children[0].offset.name.should.be.exactly("!");
});

it('should fail foo::bar::baz', function() {
var errAst = parser.parseEval('foo::bar::baz', {
it("should fail foo::bar::baz", function() {
var errAst = parser.parseEval("foo::bar::baz", {
parser: {
suppressErrors: true
}
});
errAst.errors.length.should.be.exactly(1);
errAst.children[0].kind.should.be.exactly('staticlookup');
errAst.children[0].kind.should.be.exactly("staticlookup");
});
});
});