Skip to content

Commit fbfd46f

Browse files
committed
#205 - implement byref decorator
1 parent 17cf2e4 commit fbfd46f

File tree

8 files changed

+53
-35
lines changed

8 files changed

+53
-35
lines changed

src/ast.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const Position = require("./ast/position");
3535
* - [Expression](#expression)
3636
* - [Entry](#entry)
3737
* - [Closure](#closure)
38+
* - [ByRef](#byref)
3839
* - [Silent](#silent)
3940
* - [RetIf](#retif)
4041
* - [New](#new)
@@ -473,6 +474,7 @@ AST.prototype.checkNodes = function() {
473474
require("./ast/block"),
474475
require("./ast/boolean"),
475476
require("./ast/break"),
477+
require("./ast/byref"),
476478
require("./ast/call"),
477479
require("./ast/case"),
478480
require("./ast/cast"),

src/ast/byref.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Copyright (C) 2018 Glayzzle (BSD3 License)
3+
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
4+
* @url http://glayzzle.com
5+
*/
6+
"use strict";
7+
8+
const Expression = require("./expression");
9+
const KIND = "byref";
10+
11+
/**
12+
* Passing by Reference - so the function can modify the variable
13+
* @constructor ByRef
14+
* @extends {Expression}
15+
* @property {expr} what
16+
*/
17+
module.exports = Expression.extends(KIND, function ByRef(what, docs, location) {
18+
Expression.apply(this, [KIND, docs, location]);
19+
this.what = what;
20+
});

src/ast/variable.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,23 @@ const KIND = "variable";
1515
* @extends {Expression}
1616
* @example
1717
* // PHP code :
18-
* &$foo
18+
* $foo
1919
* // AST output
2020
* {
2121
* "kind": "variable",
2222
* "name": "foo",
23-
* "byref": true,
2423
* "curly": false
2524
* }
2625
* @property {String|Node} name The variable name (can be a complex expression when the name is resolved dynamically)
27-
* @property {boolean} byref Indicate if the variable reference is used, ex `&$foo`
2826
* @property {boolean} curly Indicate if the name is defined between curlies, ex `${foo}`
2927
*/
3028
module.exports = Expression.extends(KIND, function Variable(
3129
name,
32-
byref,
3330
curly,
3431
docs,
3532
location
3633
) {
3734
Expression.apply(this, [KIND, docs, location]);
3835
this.name = name;
39-
this.byref = byref || false;
4036
this.curly = curly || false;
4137
});

src/parser/array.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,16 @@ module.exports = {
7171
return this.node("noop")();
7272
}
7373
if (this.token === "&") {
74-
return this.next().read_variable(true, false, true);
74+
return this.node("byref")(this.next().read_variable(true, false));
7575
} else {
7676
const entry = this.node(ArrayEntry);
7777
const expr = this.read_expr();
7878
if (this.token === this.tok.T_DOUBLE_ARROW) {
7979
if (this.next().token === "&") {
80-
return entry(expr, this.next().read_variable(true, false, true));
80+
return entry(
81+
expr,
82+
this.node("byref")(this.next().read_variable(true, false))
83+
);
8184
} else {
8285
return entry(expr, this.read_expr());
8386
}

src/parser/function.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,16 +144,14 @@ module.exports = {
144144
* ```
145145
*/
146146
read_lexical_var: function() {
147-
const result = this.node("variable");
148-
let isRef = false;
149147
if (this.token === "&") {
150-
isRef = true;
151-
this.next();
148+
return this.node("byref")(this.next().read_lexical_var());
152149
}
150+
const result = this.node("variable");
153151
this.expect(this.tok.T_VARIABLE);
154152
const name = this.text().substring(1);
155153
this.next();
156-
return result(name, isRef, false);
154+
return result(name, false);
157155
},
158156
/**
159157
* reads a list of parameters

src/parser/scalar.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ module.exports = {
206206
// check if lookup an offset
207207
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1243
208208
if (this.token === "[") {
209-
name = name(varName, false, false);
209+
name = name(varName, false);
210210
node = this.node("offsetlookup");
211211
offset = this.next().read_expr();
212212
this.expect("]") && this.next();
@@ -218,7 +218,7 @@ module.exports = {
218218
name = this.read_expr();
219219
}
220220
this.expect("}") && this.next();
221-
result = result("variable", name, false, true);
221+
result = result("variable", name, true);
222222
} else if (this.token === this.tok.T_CURLY_OPEN) {
223223
// expression
224224
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1246
@@ -230,7 +230,7 @@ module.exports = {
230230
// plain variable
231231
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1231
232232
result.destroy();
233-
result = this.read_simple_variable(false);
233+
result = this.read_simple_variable();
234234

235235
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1233
236236
if (this.token === "[") {

src/parser/utils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ module.exports = {
104104
if (this.expect(this.tok.T_VARIABLE)) {
105105
const name = this.text().substring(1);
106106
this.next();
107-
variable = variable(name, false, false);
107+
variable = variable(name, false);
108108
} else {
109-
variable = variable("#ERR", false, false);
109+
variable = variable("#ERR", false);
110110
}
111111
if (this.token === "=") {
112112
return node(variable, this.next().read_expr());

src/parser/variable.js

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,17 @@ module.exports = {
2222
* $var->func()->property // chained calls
2323
* ```
2424
*/
25-
read_variable: function(read_only, encapsed, byref) {
25+
read_variable: function(read_only, encapsed) {
2626
let result;
2727

2828
// check the byref flag
29-
if (!byref && this.token === "&") {
30-
byref = true;
31-
this.next();
29+
if (this.token === "&") {
30+
return this.node("byref")(this.next().read_variable(read_only, encapsed));
3231
}
3332

3433
// reads the entry point
3534
if (this.is([this.tok.T_VARIABLE, "$"])) {
36-
result = this.read_reference_variable(encapsed, byref);
35+
result = this.read_reference_variable(encapsed);
3736
} else if (
3837
this.is([
3938
this.tok.T_NS_SEPARATOR,
@@ -85,7 +84,7 @@ module.exports = {
8584
const result = this.node("staticlookup");
8685
let offset, name;
8786
if (this.next().is([this.tok.T_VARIABLE, "$"])) {
88-
offset = this.read_reference_variable(encapsed, false);
87+
offset = this.read_reference_variable(encapsed);
8988
} else if (
9089
this.token === this.tok.T_STRING ||
9190
this.token === this.tok.T_CLASS ||
@@ -131,7 +130,7 @@ module.exports = {
131130
name = this.text().substring(1);
132131
this.next();
133132
what = this.node("encapsed")(
134-
[what, inner(name, false, false)],
133+
[what, inner(name, false)],
135134
null,
136135
"offset"
137136
);
@@ -151,7 +150,7 @@ module.exports = {
151150
what = this.node("variable");
152151
name = this.text().substring(1);
153152
this.next();
154-
what = what(name, false, false);
153+
what = what(name, false);
155154
break;
156155
case "$":
157156
what = this.node();
@@ -164,7 +163,7 @@ module.exports = {
164163
} else {
165164
// $obj->$$varname
166165
name = this.read_expr();
167-
what = what("variable", name, false, false);
166+
what = what("variable", name, false);
168167
}
169168
break;
170169
case "{":
@@ -264,7 +263,7 @@ module.exports = {
264263
} else if (this.token === this.tok.T_VARIABLE) {
265264
const name = this.text().substring(1);
266265
this.next();
267-
offset = offset("variable", name, false, false);
266+
offset = offset("variable", name, false);
268267
} else {
269268
this.expect([
270269
this.tok.T_STRING,
@@ -289,8 +288,8 @@ module.exports = {
289288
* $foo[123]{1}; // gets the 2nd char from the 123 array entry
290289
* </code>
291290
*/
292-
read_reference_variable: function(encapsed, byref) {
293-
let result = this.read_simple_variable(byref);
291+
read_reference_variable: function(encapsed) {
292+
let result = this.read_simple_variable();
294293
let offset;
295294
while (this.token != this.EOF) {
296295
const node = this.node();
@@ -311,7 +310,7 @@ module.exports = {
311310
* simple_variable ::= T_VARIABLE | '$' '{' expr '}' | '$' simple_variable
312311
* ```
313312
*/
314-
read_simple_variable: function(byref) {
313+
read_simple_variable: function() {
315314
let result = this.node("variable");
316315
let name;
317316
if (
@@ -321,35 +320,35 @@ module.exports = {
321320
// plain variable name
322321
name = this.text().substring(1);
323322
this.next();
324-
result = result(name, byref, false);
323+
result = result(name, false);
325324
} else {
326325
if (this.token === "$") this.next();
327326
// dynamic variable name
328327
switch (this.token) {
329328
case "{": {
330329
const expr = this.next().read_expr();
331330
this.expect("}") && this.next();
332-
result = result(expr, byref, true);
331+
result = result(expr, true);
333332
break;
334333
}
335334
case "$": // $$$var
336335
// @fixme check coverage here
337-
result = result(this.read_simple_variable(false), byref, false);
336+
result = result(this.read_simple_variable(), false);
338337
break;
339338
case this.tok.T_VARIABLE: {
340339
// $$var
341340
name = this.text().substring(1);
342341
const node = this.node("variable");
343342
this.next();
344-
result = result(node(name, false, false), byref, false);
343+
result = result(node(name, false), false);
345344
break;
346345
}
347346
default:
348347
this.error(["{", "$", this.tok.T_VARIABLE]);
349348
// graceful mode
350349
name = this.text();
351350
this.next();
352-
result = result(name, byref, false);
351+
result = result(name, false);
353352
}
354353
}
355354
return result;

0 commit comments

Comments
 (0)