Skip to content

Commit 14bde63

Browse files
committed
Enhance AST representation of curlies / encapsed strings
1 parent 82233e9 commit 14bde63

File tree

2 files changed

+59
-42
lines changed

2 files changed

+59
-42
lines changed

src/parser/scalar.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ module.exports = {
199199
this.expect("]") && this.next();
200200
name = node(name, offset);
201201
} else {
202-
name = varName;
202+
name = this.node("constref")(varName);
203203
}
204204
} else {
205205
name = this.read_expr();
@@ -210,6 +210,9 @@ module.exports = {
210210
// expression
211211
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1246
212212
result = this.next().read_variable(false, false, false);
213+
if (result.kind === "variable") {
214+
result.curly = true;
215+
}
213216
this.expect("}") && this.next();
214217
} else if (this.token === this.tok.T_VARIABLE) {
215218
// plain variable

test/stringTests.js

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,41 @@
11
var parser = require("../src/index");
22

33
describe("Test strings", function() {
4+
it("fix #101", function() {
5+
let ast = parser.parseEval('"encapsed {$var}";');
6+
ast.children[0].value[1].kind.should.be.exactly("variable");
7+
ast.children[0].value[1].curly.should.be.true();
8+
ast = parser.parseEval('"encapsed {$arr[0]}";');
9+
ast.children[0].value[1].kind.should.be.exactly("offsetlookup");
10+
ast = parser.parseEval('"encapsed ${var}";');
11+
ast.children[0].value[1].name.kind.should.be.exactly("constref");
12+
});
413
it("fix #124", function() {
5-
const ast = parser.parseEval("$string = \"He drank some $juices[koolaid1] juice.\";");
14+
const ast = parser.parseEval(
15+
'$string = "He drank some $juices[koolaid1] juice.";'
16+
);
617
const text = ast.children[0].right;
7-
text.kind.should.be.exactly('encapsed');
18+
text.kind.should.be.exactly("encapsed");
819
text.value.length.should.be.exactly(3);
920
const offset = text.value[1];
10-
offset.kind.should.be.exactly('offsetlookup');
11-
offset.what.name.should.be.exactly('juices');
12-
offset.offset.kind.should.be.exactly('constref');
13-
offset.offset.name.should.be.exactly('koolaid1');
21+
offset.kind.should.be.exactly("offsetlookup");
22+
offset.what.name.should.be.exactly("juices");
23+
offset.offset.kind.should.be.exactly("constref");
24+
offset.offset.name.should.be.exactly("koolaid1");
1425
});
15-
it('fix #123', function() {
26+
it("fix #123", function() {
1627
const ast = parser.parseEval(
17-
"$string = \'Avoid converting \n chars, but \\' or \\\\ is ok.\';"
28+
"$string = 'Avoid converting \n chars, but \\' or \\\\ is ok.';"
1829
);
1930
const text = ast.children[0].right;
20-
text.value.should.be.exactly('Avoid converting \n chars, but \' or \\ is ok.');
31+
text.value.should.be.exactly(
32+
"Avoid converting \n chars, but ' or \\ is ok."
33+
);
2134
});
22-
it('implement #116', function() {
23-
const ast = parser.parseEval("$a = \"foo\\nbar\";");
35+
it("implement #116", function() {
36+
const ast = parser.parseEval('$a = "foo\\nbar";');
2437
const text = ast.children[0].right;
25-
text.raw.should.be.exactly("\"foo\\nbar\"");
38+
text.raw.should.be.exactly('"foo\\nbar"');
2639
});
2740
it("...", function() {
2841
var ast = parser.parseEval("$a = b'\\t\\ra';");
@@ -36,70 +49,71 @@ describe("Test strings", function() {
3649
it("check infinite on $", function() {
3750
var ast = parser.parseEval('echo "$', {
3851
parser: { suppressErrors: true, debug: false },
39-
lexer: { debug: false },
52+
lexer: { debug: false }
4053
});
41-
ast.children[0].arguments[0].value[0].kind.should.be.exactly('string');
42-
ast.children[0].arguments[0].value[0].value.should.be.exactly('$');
54+
ast.children[0].arguments[0].value[0].kind.should.be.exactly("string");
55+
ast.children[0].arguments[0].value[0].value.should.be.exactly("$");
4356

4457
// @todo ...
45-
ast = parser.parseEval('echo `$', {
58+
ast = parser.parseEval("echo `$", {
4659
parser: { suppressErrors: true, debug: false },
47-
lexer: { debug: false },
60+
lexer: { debug: false }
4861
});
49-
ast = parser.parseEval('echo ` -> $', {
62+
ast = parser.parseEval("echo ` -> $", {
5063
parser: { suppressErrors: true, debug: false },
51-
lexer: { debug: false },
64+
lexer: { debug: false }
5265
});
53-
5466
});
5567
it("check infinite on {", function() {
5668
var ast = parser.parseEval('echo "{', {
5769
parser: { suppressErrors: true, debug: false },
58-
lexer: { debug: false },
70+
lexer: { debug: false }
5971
});
60-
ast.children[0].arguments[0].value[0].kind.should.be.exactly('string');
61-
ast.children[0].arguments[0].value[0].value.should.be.exactly('{');
62-
ast = parser.parseEval('echo `{', {
72+
ast.children[0].arguments[0].value[0].kind.should.be.exactly("string");
73+
ast.children[0].arguments[0].value[0].value.should.be.exactly("{");
74+
ast = parser.parseEval("echo `{", {
6375
parser: { suppressErrors: true, debug: false },
64-
lexer: { debug: false },
76+
lexer: { debug: false }
6577
});
66-
ast = parser.parseEval('echo ` -> {', {
78+
ast = parser.parseEval("echo ` -> {", {
6779
parser: { suppressErrors: true, debug: false },
68-
lexer: { debug: false },
80+
lexer: { debug: false }
6981
});
7082
});
7183
it("check infinite on ${", function() {
7284
var ast = parser.parseEval('echo "${', {
7385
parser: { suppressErrors: true, debug: false },
74-
lexer: { debug: false },
86+
lexer: { debug: false }
7587
});
76-
ast.children[0].arguments[0].value[0].kind.should.be.exactly('variable');
77-
ast = parser.parseEval('echo `${', {
88+
ast.children[0].arguments[0].value[0].kind.should.be.exactly("variable");
89+
ast = parser.parseEval("echo `${", {
7890
parser: { suppressErrors: true, debug: false },
79-
lexer: { debug: false },
91+
lexer: { debug: false }
8092
});
81-
ast = parser.parseEval('echo ` -> ${', {
93+
ast = parser.parseEval("echo ` -> ${", {
8294
parser: { suppressErrors: true, debug: false },
83-
lexer: { debug: false },
95+
lexer: { debug: false }
8496
});
8597
});
8698
it("check infinite on {$", function() {
8799
var ast = parser.parseEval('echo "{$', {
88100
parser: { suppressErrors: true, debug: false },
89-
lexer: { debug: false },
101+
lexer: { debug: false }
90102
});
91-
ast.children[0].arguments[0].value[0].kind.should.be.exactly('variable');
92-
ast = parser.parseEval('echo `{$', {
103+
ast.children[0].arguments[0].value[0].kind.should.be.exactly("variable");
104+
ast = parser.parseEval("echo `{$", {
93105
parser: { suppressErrors: true, debug: false },
94-
lexer: { debug: false },
106+
lexer: { debug: false }
95107
});
96-
ast = parser.parseEval('echo ` -> {$', {
108+
ast = parser.parseEval("echo ` -> {$", {
97109
parser: { suppressErrors: true, debug: false },
98-
lexer: { debug: false },
110+
lexer: { debug: false }
99111
});
100112
});
101113
it("binary cast", function() {
102-
var ast = parser.parseEval('echo (binary)"\\colors[1] contains >$colors[1]<\\n";');
114+
var ast = parser.parseEval(
115+
'echo (binary)"\\colors[1] contains >$colors[1]<\\n";'
116+
);
103117
// @todo console.log(ast.children[0].arguments[0]);
104118
});
105119
it("...", function() {
@@ -150,7 +164,7 @@ describe("Test strings", function() {
150164
arg1.value[2].value.should.be.exactly("->name !");
151165
// test the varname
152166
arg1.value[1].kind.should.be.exactly("variable");
153-
arg1.value[1].name.should.be.exactly("obj");
167+
arg1.value[1].name.name.should.be.exactly("obj");
154168
arg1.value[1].curly.should.be.exactly(true);
155169
});
156170
it("Encapsed variable / curly constant", function() {

0 commit comments

Comments
 (0)