Skip to content

Commit 5747a93

Browse files
committed
add pre node
1 parent 88871e0 commit 5747a93

File tree

5 files changed

+208
-103
lines changed

5 files changed

+208
-103
lines changed

docs/AST.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- [ConstRef](#constref)
2323
- [Operation](#operation)
2424
- [Coalesce](#coalesce)
25+
- [Pre](#pre)
2526
- [Post](#post)
2627
- [Bin](#bin)
2728
- [Bool](#Bool)
@@ -734,6 +735,17 @@ Defines a post operation `$i++` or `$i--`
734735
- `type` **[String](#string)**
735736
- `what` **[Variable](#variable)**
736737

738+
# Pre
739+
740+
**Extends Operation**
741+
742+
Defines a pre operation `++$i` or `--$i`
743+
744+
**Properties**
745+
746+
- `type` **[String](#string)**
747+
- `what` **[Variable](#variable)**
748+
737749
# Print
738750

739751
**Extends Sys**

src/ast.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var Position = require('./ast/position');
2828
* - [ConstRef](#constref)
2929
* - [Operation](#operation)
3030
* - [Coalesce](#coalesce)
31+
* - [Pre](#pre)
3132
* - [Post](#post)
3233
* - [Bin](#bin)
3334
* - [Bool](#Bool)
@@ -207,6 +208,7 @@ AST.prototype.prepare = function(kind, parser) {
207208
require('./ast/number'),
208209
require('./ast/parameter'),
209210
require('./ast/post'),
211+
require('./ast/pre'),
210212
require('./ast/print'),
211213
require('./ast/program'),
212214
require('./ast/property'),

src/ast/pre.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*!
2+
* Copyright (C) 2017 Glayzzle (BSD3 License)
3+
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
4+
* @url http://glayzzle.com
5+
*/
6+
"use strict";
7+
8+
var Operation = require('./operation');
9+
var KIND = 'pre';
10+
11+
/**
12+
* Defines a pre operation `++$i` or `--$i`
13+
* @constructor Pre
14+
* @extends {Operation}
15+
* @property {String} type
16+
* @property {Variable} what
17+
*/
18+
var Pre = Operation.extends(function Pre(type, what, location) {
19+
Operation.apply(this, [KIND, location]);
20+
this.type = type;
21+
this.what = what;
22+
});
23+
24+
module.exports = Pre;

src/parser/expr.js

Lines changed: 119 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -96,112 +96,117 @@ module.exports = {
9696

9797
if (this.token === '@')
9898
return this.node('silent')(this.next().read_expr());
99-
100-
switch(this.token) {
101-
case '-':
102-
var result = this.node();
99+
if (this.token === '+')
100+
return this.node('unary')('+', this.next().read_expr());
101+
if (this.token === '!')
102+
return this.node('unary')('!', this.next().read_expr());
103+
if (this.token === '~')
104+
return this.node('unary')('~', this.next().read_expr());
105+
106+
if (this.token === '-') {
107+
var result = this.node();
108+
this.next();
109+
if (
110+
this.token === this.tok.T_LNUMBER ||
111+
this.token === this.tok.T_DNUMBER
112+
) {
113+
// negative number
114+
result = result('number', '-' + this.text());
103115
this.next();
104-
if (
105-
this.token === this.tok.T_LNUMBER ||
106-
this.token === this.tok.T_DNUMBER
107-
) {
108-
// negative number
109-
result = result('number', '-' + this.text());
110-
this.next();
111-
return result;
112-
} else {
113-
return result('unary', '-', this.read_expr());
114-
}
116+
return result;
117+
} else {
118+
return result('unary', '-', this.read_expr());
119+
}
120+
}
115121

116-
case '+':
117-
case '!':
118-
case '~':
119-
return this.node('unary')(this.token, this.next().read_expr());
122+
if (this.token === '(') {
123+
var expr = this.next().read_expr();
124+
this.expect(')') && this.next();
125+
// handle dereferencable
126+
if (this.token === this.tok.T_OBJECT_OPERATOR) {
127+
return this.recursive_variable_chain_scan(expr, false);
128+
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === '[') {
129+
return this.read_dereferencable(expr);
130+
} else if (this.token === '(') {
131+
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118
132+
return this.node('call')(
133+
expr, this.read_function_argument_list()
134+
);
135+
} else {
136+
return expr;
137+
}
138+
}
120139

121-
case '(':
122-
var expr = this.next().read_expr();
123-
if (this.expect(')')) {
124-
this.next();
125-
}
140+
if (this.token === '`') {
141+
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1048
142+
return this.node('shell')(
143+
this.next().read_encapsed_string('`')
144+
);
145+
}
126146

127-
// handle dereferencable
128-
if (this.token === this.tok.T_OBJECT_OPERATOR) {
129-
return this.recursive_variable_chain_scan(expr, false);
130-
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === '[') {
131-
return this.read_dereferencable(expr);
132-
} else if (this.token === '(') {
133-
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118
134-
return this.node('call')(
135-
expr, this.read_function_argument_list()
136-
);
137-
} else {
138-
return expr;
139-
}
147+
if (this.token === this.tok.T_LIST) {
148+
var result = this.node('list'), assign = null;
149+
var isInner = this.innerList;
150+
if (!isInner) {
151+
assign = this.node('assign');
152+
}
153+
if (this.next().expect('(')) {
154+
this.next();
155+
}
140156

141-
case '`':
142-
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1048
143-
var result = this.node('shell');
144-
var expr = this.next().read_encapsed_string('`');
145-
return result(expr);
157+
if (!this.innerList) this.innerList = true;
158+
var assignList = this.read_assignment_list();
146159

147-
case this.tok.T_LIST:
148-
var result = this.node('list'), assign = null;
149-
var isInner = this.innerList;
150-
if (!isInner) {
151-
assign = this.node('assign');
160+
// check if contains at least one assignment statement
161+
var hasItem = false;
162+
for(var i = 0; i < assignList.length; i++) {
163+
if (assignList[i] !== null) {
164+
hasItem = true;
165+
break;
152166
}
153-
if (this.next().expect('(')) {
154-
this.next();
155-
}
156-
157-
if (!this.innerList) this.innerList = true;
158-
var assignList = this.read_assignment_list();
167+
}
168+
if (!hasItem) {
169+
this.raiseError(
170+
'Fatal Error : Cannot use empty list on line ' + this.lexer.yylloc.first_line
171+
);
172+
}
173+
if (this.expect(')')) {
174+
this.next();
175+
}
159176

160-
// check if contains at least one assignment statement
161-
var hasItem = false;
162-
for(var i = 0; i < assignList.length; i++) {
163-
if (assignList[i] !== null) {
164-
hasItem = true;
165-
break;
166-
}
167-
}
168-
if (!hasItem) {
169-
this.raiseError(
170-
'Fatal Error : Cannot use empty list on line ' + this.lexer.yylloc.first_line
177+
if (!isInner) {
178+
this.innerList = false;
179+
if (this.expect('=')) {
180+
return assign(
181+
result(assignList),
182+
this.next().read_expr(),
183+
'='
171184
);
172-
}
173-
if (this.expect(')')) {
174-
this.next();
175-
}
176-
177-
if (!isInner) {
178-
this.innerList = false;
179-
if (this.expect('=')) {
180-
return assign(
181-
result(assignList),
182-
this.next().read_expr(),
183-
'='
184-
);
185-
} else {
186-
// fallback : list($a, $b);
187-
return result(assignList);
188-
}
189185
} else {
186+
// fallback : list($a, $b);
190187
return result(assignList);
191188
}
189+
} else {
190+
return result(assignList);
191+
}
192+
}
192193

193-
case this.tok.T_CLONE:
194-
return this.node('clone')(
195-
this.next().read_expr()
196-
);
194+
if (this.token === this.tok.T_CLONE)
195+
return this.node('clone')(
196+
this.next().read_expr()
197+
);
198+
199+
switch(this.token) {
197200

198201
case this.tok.T_INC:
199-
var name = this.next().read_variable(false, false, false);
200-
return ['set', name, ['bin', '+', name, ['number', 1]]];
202+
return this.node('pre')(
203+
'+', this.next().read_variable(false, false, false)
204+
);
201205

202206
case this.tok.T_DEC:
203-
var name = this.next().read_variable(false, false, false);
204-
return ['set', name, ['bin', '-', name, ['number', 1]]];
207+
return this.node('pre')(
208+
'-', this.next().read_variable(false, false, false)
209+
);
205210

206211
case this.tok.T_NEW:
207212
return this.next().read_new_expr();
@@ -351,38 +356,49 @@ module.exports = {
351356

352357
// operations :
353358
case this.tok.T_PLUS_EQUAL:
354-
return ['set', expr, ['bin', '+', expr, this.next().read_expr()]];
359+
return this.node('assign')(expr, this.next().read_expr(), '+=');
360+
355361
case this.tok.T_MINUS_EQUAL:
356-
return ['set', expr, ['bin', '-', expr, this.next().read_expr()]];
362+
return this.node('assign')(expr, this.next().read_expr(), '-=');
363+
357364
case this.tok.T_MUL_EQUAL:
358-
return ['set', expr, ['bin', '*', expr, this.next().read_expr()]];
365+
return this.node('assign')(expr, this.next().read_expr(), '*=');
366+
359367
case this.tok.T_POW_EQUAL:
360-
return ['set', expr, ['bin', '**', expr, this.next().read_expr()]];
368+
return this.node('assign')(expr, this.next().read_expr(), '**=');
369+
361370
case this.tok.T_DIV_EQUAL:
362-
return ['set', expr, ['bin', '/', expr, this.next().read_expr()]];
371+
return this.node('assign')(expr, this.next().read_expr(), '/=');
372+
363373
case this.tok.T_CONCAT_EQUAL:
364-
// NB : convert as string and add
365-
return ['set', expr, ['bin', '.', expr, this.next().read_expr()]];
374+
return this.node('assign')(expr, this.next().read_expr(), '.=');
375+
366376
case this.tok.T_MOD_EQUAL:
367-
return ['set', expr, ['bin', '%', expr, this.next().read_expr()]];
377+
return this.node('assign')(expr, this.next().read_expr(), '%=');
378+
368379
case this.tok.T_AND_EQUAL:
369-
return ['set', expr, ['bin', '&', expr, this.next().read_expr()]];
380+
return this.node('assign')(expr, this.next().read_expr(), '&=');
381+
370382
case this.tok.T_OR_EQUAL:
371-
return ['set', expr, ['bin', '|', expr, this.next().read_expr()]];
383+
return this.node('assign')(expr, this.next().read_expr(), '|=');
384+
372385
case this.tok.T_XOR_EQUAL:
373-
return ['set', expr, ['bin', '^', expr, this.next().read_expr()]];
386+
return this.node('assign')(expr, this.next().read_expr(), '^=');
387+
374388
case this.tok.T_SL_EQUAL:
375-
return ['set', expr, ['bin', '<<', expr, this.next().read_expr()]];
389+
return this.node('assign')(expr, this.next().read_expr(), '<<=');
390+
376391
case this.tok.T_SR_EQUAL:
377-
return ['set', expr, ['bin', '>>', expr, this.next().read_expr()]];
392+
return this.node('assign')(expr, this.next().read_expr(), '>>=');
393+
378394
case this.tok.T_INC:
379395
var result = this.node('post');
380396
this.next();
381397
return result('+', expr);
382398
case this.tok.T_DEC:
383399
var result = this.node('post');
384400
this.next();
385-
return result('+', expr);
401+
return result('-', expr);
386402
}
387403
} else if (this.is('SCALAR')) {
388404
expr = this.read_scalar();

0 commit comments

Comments
 (0)