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
42 changes: 12 additions & 30 deletions src/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ AST.precedence = {};
["*", "/", "%"],
["!"],
["instanceof"],
["cast"]
// TODO: typecasts
["cast", "silent"]
// TODO: [ (array)
// TODO: clone, new
].forEach(function(list, index) {
Expand Down Expand Up @@ -254,22 +253,22 @@ AST.prototype.resolvePrecedence = function(result, parser) {
}
}
} else if (
result.kind === "cast" &&
result.what &&
!result.what.parenthesizedExpression
(result.kind === "silent" || result.kind === "cast") &&
result.expr &&
!result.expr.parenthesizedExpression
) {
// https://github.com/glayzzle/php-parser/issues/172
if (result.what.kind === "bin") {
buffer = result.what;
result.what = result.what.left;
this.swapLocations(result, result, result.what, parser);
if (result.expr.kind === "bin") {
buffer = result.expr;
result.expr = result.expr.left;
this.swapLocations(result, result, result.expr, parser);
buffer.left = this.resolvePrecedence(result, parser);
this.swapLocations(buffer, buffer.left, buffer.right, parser);
result = buffer;
} else if (result.what.kind === "retif") {
buffer = result.what;
result.what = result.what.test;
this.swapLocations(result, result, result.what, parser);
} else if (result.expr.kind === "retif") {
buffer = result.expr;
result.expr = result.expr.test;
this.swapLocations(result, result, result.expr, parser);
buffer.test = this.resolvePrecedence(result, parser);
this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser);
result = buffer;
Expand All @@ -285,13 +284,6 @@ AST.prototype.resolvePrecedence = function(result, parser) {
buffer.left = this.resolvePrecedence(result, parser);
this.swapLocations(buffer, buffer.left, buffer.right, parser);
result = buffer;
} else if (result.what.kind === "retif") {
buffer = result.what;
result.what = result.what.test;
this.swapLocations(result, result, result.what, parser);
buffer.test = this.resolvePrecedence(result, parser);
this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser);
result = buffer;
}
}
} else if (result.kind === "retif") {
Expand Down Expand Up @@ -326,16 +318,6 @@ AST.prototype.resolvePrecedence = function(result, parser) {
result = buffer;
}
}
} else if (result.kind === "silent" && !result.expr.parenthesizedExpression) {
if (result.expr.kind === "assign") return result;
// overall least precedence
if (result.expr.right) {
buffer = result.expr;
result.expr = buffer.left;
buffer.left = result;
this.swapLocations(buffer, buffer.left, buffer.right, parser);
result = buffer;
}
} else if (result.kind === "expressionstatement") {
this.swapLocations(result, result.expression, result, parser);
}
Expand Down
6 changes: 3 additions & 3 deletions src/ast/cast.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ const KIND = "cast";
* @extends {Operation}
* @property {String} type
* @property {String} raw
* @property {Expression} what
* @property {Expression} expr
*/
module.exports = Operation.extends(KIND, function Cast(
type,
raw,
what,
expr,
docs,
location
) {
Operation.apply(this, [KIND, docs, location]);
this.type = type;
this.raw = raw;
this.what = what;
this.expr = expr;
});
63 changes: 30 additions & 33 deletions test/precedence.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,39 @@ var parser = require("./main");
/**
* Check precedence by using parenthesis on node B
*/
var checkPrecedence = function(a, b) {
if (!a && !b)
return false;
for (let k in b) {
if (k === 'parenthesizedExpression') continue;
if (b.hasOwnProperty(k)) {
if (!a.hasOwnProperty(k))
return expect(a).toHaveProperty(k, b[k]);
if (typeof b[k] === "object" && b[k] !== null) {
checkPrecedence(a[k], b[k]);
} else {
expect(a[k]).toEqual(b[k]);
}
}
function filterKey(fn, obj) {
if (Array.isArray(obj)) {
return obj.map(e => filterKey(fn, e));
}
for (let k in a) {
if (k === 'parenthesizedExpression') continue;
if (a.hasOwnProperty(k)) {
if (!b.hasOwnProperty(k))
return expect(b).toHaveProperty(k, a[k]);
}
}
return true;
};

var shouldBeSame = function(a, b) {
var ast = parser.parseEval([
a + ";",
b + ";"
].join("\n"));
let result = checkPrecedence(ast.children[0], ast.children[1]);
if (!result) {
console.log("Parsed :", ast.children[0]);
console.log("Expected :", ast.children[1]);
if (typeof(obj) === "object" && obj !== null) {
return Object.keys(obj)
.filter(fn)
.reduce((result, key) => ({
...result,
[key]: filterKey(fn, obj[key])
}), {});
}
expect(result).toBeTruthy();

return obj
}

function shouldBeSame(a, b) {
const fn = key => key !== "parenthesizedExpression";
expect(filterKey(fn, parser.parseEval(a))).toEqual(filterKey(fn, parser.parseEval(b)))
};

// START TESTS HERE

describe("Test infrastructure", function() {
it("should filter parenthesizedExpression prop", function() {
const fn = key => key !== "parenthesizedExpression";
expect(filterKey(fn, {foo: "bar", parenthesizedExpression: true})).toEqual({foo: "bar"});
expect(filterKey(fn, {x: {foo: "bar", parenthesizedExpression: true}})).toEqual({x: {foo: "bar"}});
expect(filterKey(fn, [{foo: "bar", parenthesizedExpression: true}])).toEqual([{foo: "bar"}]);
});
});

describe("Test precedence", function() {
it("test *", function() {
shouldBeSame("5 * 3 - 2", "(5 * 3) - 2");
Expand Down Expand Up @@ -135,6 +129,9 @@ describe("Test precedence", function() {
it("test silent node / div", function() {
shouldBeSame("@$i / 0;", "@($i) / 0;");
});
it("test silent node / retif", function() {
shouldBeSame("@$var ? 1 : 2;", "(@$var) ? 1 : 2;");
});
it("test silent node / ret if", function() {
shouldBeSame("@$i == true ? @$foo : @$bar;", "@($i) == true ? @($foo) : @($bar);");
});
Expand Down
68 changes: 34 additions & 34 deletions test/snapshot/__snapshots__/acid.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3737,23 +3737,7 @@ Program {
"test": Bin {
"kind": "bin",
"left": Cast {
"kind": "cast",
"loc": Location {
"end": Position {
"column": 19,
"line": 90,
"offset": 1817,
},
"source": "(int)$index",
"start": Position {
"column": 8,
"line": 90,
"offset": 1806,
},
},
"raw": "(int)",
"type": "int",
"what": Variable {
"expr": Variable {
"curly": false,
"kind": "variable",
"loc": Location {
Expand All @@ -3771,6 +3755,22 @@ Program {
},
"name": "index",
},
"kind": "cast",
"loc": Location {
"end": Position {
"column": 19,
"line": 90,
"offset": 1817,
},
"source": "(int)$index",
"start": Position {
"column": 8,
"line": 90,
"offset": 1806,
},
},
"raw": "(int)",
"type": "int",
},
"loc": Location {
"end": Position {
Expand Down Expand Up @@ -6177,23 +6177,7 @@ next:
"test": Bin {
"kind": "bin",
"left": Cast {
"kind": "cast",
"loc": Location {
"end": Position {
"column": 41,
"line": 99,
"offset": 2047,
},
"source": "(int)calculateMeaningOfLife()",
"start": Position {
"column": 12,
"line": 99,
"offset": 2018,
},
},
"raw": "(int)",
"type": "int",
"what": Call {
"expr": Call {
"arguments": Array [],
"kind": "call",
"loc": Location {
Expand Down Expand Up @@ -6228,6 +6212,22 @@ next:
"resolution": "uqn",
},
},
"kind": "cast",
"loc": Location {
"end": Position {
"column": 41,
"line": 99,
"offset": 2047,
},
"source": "(int)calculateMeaningOfLife()",
"start": Position {
"column": 12,
"line": 99,
"offset": 2018,
},
},
"raw": "(int)",
"type": "int",
},
"loc": Location {
"end": Position {
Expand Down
Loading