Skip to content

Commit e487690

Browse files
fix: support negative offset in encapsed
1 parent 2753f9e commit e487690

File tree

3 files changed

+219
-20
lines changed

3 files changed

+219
-20
lines changed

src/parser/variable.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ module.exports = {
248248
const num = this.text();
249249
this.next();
250250
offset = offset("number", num, null);
251+
} else if (this.token === "-") {
252+
this.next();
253+
const num = -1 * this.text();
254+
this.expect(this.tok.T_NUM_STRING) && this.next();
255+
offset = offset("number", num, null);
251256
} else if (this.token === this.tok.T_VARIABLE) {
252257
const name = this.text().substring(1);
253258
this.next();
@@ -256,6 +261,7 @@ module.exports = {
256261
this.expect([
257262
this.tok.T_STRING,
258263
this.tok.T_NUM_STRING,
264+
"-",
259265
this.tok.T_VARIABLE
260266
]);
261267
// fallback : consider as identifier

test/snapshot/__snapshots__/encapsed.test.js.snap

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,41 @@ Program {
6464
}
6565
`;
6666

67+
exports[`encapsed negative offset in encapsed var offset 1`] = `
68+
Program {
69+
"children": Array [
70+
ExpressionStatement {
71+
"expression": Encapsed {
72+
"kind": "encapsed",
73+
"raw": "\\"$var[-1]\\"",
74+
"type": "string",
75+
"value": Array [
76+
EncapsedPart {
77+
"curly": false,
78+
"expression": OffsetLookup {
79+
"kind": "offsetlookup",
80+
"offset": Number {
81+
"kind": "number",
82+
"value": -1,
83+
},
84+
"what": Variable {
85+
"curly": false,
86+
"kind": "variable",
87+
"name": "var",
88+
},
89+
},
90+
"kind": "encapsedpart",
91+
},
92+
],
93+
},
94+
"kind": "expressionstatement",
95+
},
96+
],
97+
"errors": Array [],
98+
"kind": "program",
99+
}
100+
`;
101+
67102
exports[`encapsed newline before closing curly (complex syntax) 1`] = `
68103
Program {
69104
"children": Array [
@@ -545,6 +580,41 @@ Program {
545580
}
546581
`;
547582

583+
exports[`encapsed positive offset in encapsed var offset 1`] = `
584+
Program {
585+
"children": Array [
586+
ExpressionStatement {
587+
"expression": Encapsed {
588+
"kind": "encapsed",
589+
"raw": "\\"$var[1]\\"",
590+
"type": "string",
591+
"value": Array [
592+
EncapsedPart {
593+
"curly": false,
594+
"expression": OffsetLookup {
595+
"kind": "offsetlookup",
596+
"offset": Number {
597+
"kind": "number",
598+
"value": "1",
599+
},
600+
"what": Variable {
601+
"curly": false,
602+
"kind": "variable",
603+
"name": "var",
604+
},
605+
},
606+
"kind": "encapsedpart",
607+
},
608+
],
609+
},
610+
"kind": "expressionstatement",
611+
},
612+
],
613+
"errors": Array [],
614+
"kind": "program",
615+
}
616+
`;
617+
548618
exports[`encapsed propertylookup (complex syntax) 1`] = `
549619
Program {
550620
"children": Array [
@@ -1316,6 +1386,77 @@ Program {
13161386
}
13171387
`;
13181388

1389+
exports[`encapsed string offset in encapsed var offset 1`] = `
1390+
Program {
1391+
"children": Array [
1392+
ExpressionStatement {
1393+
"expression": Encapsed {
1394+
"kind": "encapsed",
1395+
"raw": "\\"$var[var]\\"",
1396+
"type": "string",
1397+
"value": Array [
1398+
EncapsedPart {
1399+
"curly": false,
1400+
"expression": OffsetLookup {
1401+
"kind": "offsetlookup",
1402+
"offset": Identifier {
1403+
"kind": "identifier",
1404+
"name": "var",
1405+
},
1406+
"what": Variable {
1407+
"curly": false,
1408+
"kind": "variable",
1409+
"name": "var",
1410+
},
1411+
},
1412+
"kind": "encapsedpart",
1413+
},
1414+
],
1415+
},
1416+
"kind": "expressionstatement",
1417+
},
1418+
],
1419+
"errors": Array [],
1420+
"kind": "program",
1421+
}
1422+
`;
1423+
1424+
exports[`encapsed string offset in encapsed var offset 2`] = `
1425+
Program {
1426+
"children": Array [
1427+
ExpressionStatement {
1428+
"expression": Encapsed {
1429+
"kind": "encapsed",
1430+
"raw": "\\"$var[$var]\\"",
1431+
"type": "string",
1432+
"value": Array [
1433+
EncapsedPart {
1434+
"curly": false,
1435+
"expression": OffsetLookup {
1436+
"kind": "offsetlookup",
1437+
"offset": Variable {
1438+
"curly": false,
1439+
"kind": "variable",
1440+
"name": "var",
1441+
},
1442+
"what": Variable {
1443+
"curly": false,
1444+
"kind": "variable",
1445+
"name": "var",
1446+
},
1447+
},
1448+
"kind": "encapsedpart",
1449+
},
1450+
],
1451+
},
1452+
"kind": "expressionstatement",
1453+
},
1454+
],
1455+
"errors": Array [],
1456+
"kind": "program",
1457+
}
1458+
`;
1459+
13191460
exports[`encapsed two variable (simple syntax) 1`] = `
13201461
Program {
13211462
"children": Array [

test/snapshot/encapsed.test.js

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const parser = require('../main');
1+
const parser = require("../main");
22

33
describe("encapsed", function() {
44
it("variable (simple syntax)", function() {
@@ -14,13 +14,17 @@ describe("encapsed", function() {
1414
expect(parser.parseEval('"string $array[0] string";')).toMatchSnapshot();
1515
});
1616
it("offsetlookup (2) (simple syntax)", function() {
17-
expect(parser.parseEval('"string $array[koolaid1] string";')).toMatchSnapshot();
17+
expect(
18+
parser.parseEval('"string $array[koolaid1] string";')
19+
).toMatchSnapshot();
1820
});
1921
it("offsetlookup (3) (simple syntax)", function() {
2022
expect(parser.parseEval('"string $array[0][0] string";')).toMatchSnapshot();
2123
});
2224
it("propertylookup (simple syntax)", function() {
23-
expect(parser.parseEval('"string $obj->property string";')).toMatchSnapshot();
25+
expect(
26+
parser.parseEval('"string $obj->property string";')
27+
).toMatchSnapshot();
2428
});
2529
it("variable with space opening before curly", function() {
2630
expect(parser.parseEval('"string { $var} string";')).toMatchSnapshot();
@@ -32,22 +36,34 @@ describe("encapsed", function() {
3236
expect(parser.parseEval('"string {$var} string";')).toMatchSnapshot();
3337
});
3438
it("propertylookup (complex syntax)", function() {
35-
expect(parser.parseEval('"string {$obj->property} string";')).toMatchSnapshot();
39+
expect(
40+
parser.parseEval('"string {$obj->property} string";')
41+
).toMatchSnapshot();
3642
});
3743
it("offsetlookup (complex syntax)", function() {
38-
expect(parser.parseEval('"string {$array["key"]} string";')).toMatchSnapshot();
44+
expect(
45+
parser.parseEval('"string {$array["key"]} string";')
46+
).toMatchSnapshot();
3947
});
4048
it("offsetlookup 2 (complex syntax)", function() {
41-
expect(parser.parseEval('"string {$array[4][3]} string";')).toMatchSnapshot();
49+
expect(
50+
parser.parseEval('"string {$array[4][3]} string";')
51+
).toMatchSnapshot();
4252
});
4353
it("offsetlookup 3 (complex syntax)", function() {
44-
expect(parser.parseEval('"string {$arr[foo][3]} string";')).toMatchSnapshot();
54+
expect(
55+
parser.parseEval('"string {$arr[foo][3]} string";')
56+
).toMatchSnapshot();
4557
});
4658
it("offsetlookup 4 (complex syntax)", function() {
47-
expect(parser.parseEval('"string {$arr["foo"][3]} string";')).toMatchSnapshot();
59+
expect(
60+
parser.parseEval('"string {$arr["foo"][3]} string";')
61+
).toMatchSnapshot();
4862
});
4963
it("propertylookup and offsetlookup (complex syntax)", function() {
50-
expect(parser.parseEval('"string {$obj->values[3]->name} string";')).toMatchSnapshot();
64+
expect(
65+
parser.parseEval('"string {$obj->values[3]->name} string";')
66+
).toMatchSnapshot();
5167
});
5268
it("value of the var (complex syntax)", function() {
5369
expect(parser.parseEval('"string {${$name}} string";')).toMatchSnapshot();
@@ -59,31 +75,47 @@ describe("encapsed", function() {
5975
expect(parser.parseEval('"string {${call()}} string";')).toMatchSnapshot();
6076
});
6177
it("value of the var named by the return value (3) (complex syntax)", function() {
62-
expect(parser.parseEval('"string {${$obj->property}} string";')).toMatchSnapshot();
78+
expect(
79+
parser.parseEval('"string {${$obj->property}} string";')
80+
).toMatchSnapshot();
6381
});
6482
it("value of the var named by the return value (4) (complex syntax)", function() {
65-
expect(parser.parseEval('"string {${$obj->call()}} string";')).toMatchSnapshot();
83+
expect(
84+
parser.parseEval('"string {${$obj->call()}} string";')
85+
).toMatchSnapshot();
6686
});
6787
it("value of the var named by the return value (5) (complex syntax)", function() {
68-
expect(parser.parseEval('"string {${$obj::$var}} string";')).toMatchSnapshot();
88+
expect(
89+
parser.parseEval('"string {${$obj::$var}} string";')
90+
).toMatchSnapshot();
6991
});
7092
it("value of the var named by the return value (6) (complex syntax)", function() {
71-
expect(parser.parseEval('"string {${$obj::call()}} string";')).toMatchSnapshot();
93+
expect(
94+
parser.parseEval('"string {${$obj::call()}} string";')
95+
).toMatchSnapshot();
7296
});
7397
it("propertylookup by variable (complex syntax)", function() {
7498
expect(parser.parseEval('"string {$obj->$var} string";')).toMatchSnapshot();
7599
});
76100
it("propertylookup by variable (2) (complex syntax)", function() {
77-
expect(parser.parseEval('"string {$obj->{$array[1]}} string";')).toMatchSnapshot();
101+
expect(
102+
parser.parseEval('"string {$obj->{$array[1]}} string";')
103+
).toMatchSnapshot();
78104
});
79105
it("propertylookup with multiple call (complex syntax)", function() {
80-
expect(parser.parseEval('"string {$obj->call()->call()} string";')).toMatchSnapshot();
106+
expect(
107+
parser.parseEval('"string {$obj->call()->call()} string";')
108+
).toMatchSnapshot();
81109
});
82110
it("multiple propertylookup (complex syntax)", function() {
83-
expect(parser.parseEval('"string {$obj->property->property} string";')).toMatchSnapshot();
111+
expect(
112+
parser.parseEval('"string {$obj->property->property} string";')
113+
).toMatchSnapshot();
84114
});
85115
it("propertylookup with comments (complex syntax)", function() {
86-
expect(parser.parseEval('"string {$var->foo->bar /* Comment */ } string";')).toMatchSnapshot();
116+
expect(
117+
parser.parseEval('"string {$var->foo->bar /* Comment */ } string";')
118+
).toMatchSnapshot();
87119
});
88120
it("newline before closing curly (complex syntax)", function() {
89121
expect(parser.parseEval('"string {$var\n} string";')).toMatchSnapshot();
@@ -92,12 +124,32 @@ describe("encapsed", function() {
92124
expect(parser.parseEval('"string {$obj::$var} string";')).toMatchSnapshot();
93125
});
94126
it("staticlookup (2) (complex syntax)", function() {
95-
expect(parser.parseEval('"string {$obj::call()} string";')).toMatchSnapshot();
127+
expect(
128+
parser.parseEval('"string {$obj::call()} string";')
129+
).toMatchSnapshot();
96130
});
97131
it("staticlookup (3) (complex syntax)", function() {
98-
expect(parser.parseEval('"string {$obj::$var::$var} string";')).toMatchSnapshot();
132+
expect(
133+
parser.parseEval('"string {$obj::$var::$var} string";')
134+
).toMatchSnapshot();
99135
});
100136
it("staticlookup (4) (complex syntax)", function() {
101-
expect(parser.parseEval('"string {$var::$target::$resource::$binary::$foo::$bar::$foobar::$bar::$foo::$foobar::$bar::$foo} string";')).toMatchSnapshot();
137+
expect(
138+
parser.parseEval(
139+
'"string {$var::$target::$resource::$binary::$foo::$bar::$foobar::$bar::$foo::$foobar::$bar::$foo} string";'
140+
)
141+
).toMatchSnapshot();
142+
});
143+
it("string offset in encapsed var offset", () => {
144+
expect(parser.parseEval(`"$var[var]";`)).toMatchSnapshot();
145+
});
146+
it("positive offset in encapsed var offset", () => {
147+
expect(parser.parseEval(`"$var[1]";`)).toMatchSnapshot();
148+
});
149+
it("negative offset in encapsed var offset", () => {
150+
expect(parser.parseEval(`"$var[-1]";`)).toMatchSnapshot();
151+
});
152+
it("string offset in encapsed var offset", () => {
153+
expect(parser.parseEval(`"$var[$var]";`)).toMatchSnapshot();
102154
});
103155
});

0 commit comments

Comments
 (0)