File tree 4 files changed +65
-11
lines changed
4 files changed +65
-11
lines changed Original file line number Diff line number Diff line change @@ -164,7 +164,8 @@ AST.precedence = {};
164
164
[ "*" , "/" , "%" ] ,
165
165
[ "!" ] ,
166
166
[ "instanceof" ] ,
167
- [ "cast" , "silent" ]
167
+ [ "cast" , "silent" ] ,
168
+ [ "**" ]
168
169
// TODO: [ (array)
169
170
// TODO: clone, new
170
171
] . forEach ( function ( list , index ) {
@@ -173,6 +174,10 @@ AST.precedence = {};
173
174
} ) ;
174
175
} ) ;
175
176
177
+ AST . prototype . isRightAssociative = function ( operator ) {
178
+ return operator === "**" || operator === "??" ;
179
+ } ;
180
+
176
181
/**
177
182
* Change parent node informations after swapping childs
178
183
*/
@@ -230,7 +235,12 @@ AST.prototype.resolvePrecedence = function(result, parser) {
230
235
if ( result . right . kind === "bin" ) {
231
236
lLevel = AST . precedence [ result . type ] ;
232
237
rLevel = AST . precedence [ result . right . type ] ;
233
- if ( lLevel && rLevel && rLevel <= lLevel ) {
238
+ if (
239
+ lLevel &&
240
+ rLevel &&
241
+ rLevel <= lLevel &&
242
+ ! this . isRightAssociative ( result . type )
243
+ ) {
234
244
// https://github.com/glayzzle/php-parser/issues/79
235
245
// shift precedence
236
246
buffer = result . right ;
Original file line number Diff line number Diff line change @@ -86,6 +86,12 @@ describe("Test precedence", function() {
86
86
it ( "test ??" , function ( ) {
87
87
shouldBeSame ( "1 || 2 ?? 3" , "(1 || 2) ?? 3" ) ;
88
88
} ) ;
89
+ it ( "test ?? right-associative" , function ( ) {
90
+ shouldBeSame ( "1 ?? 2 ?? 3" , "1 ?? (2 ?? 3)" ) ;
91
+ } ) ;
92
+ it ( "test ** right-associative" , function ( ) {
93
+ shouldBeSame ( "1 ** 2 ** 3" , "1 ** (2 ** 3)" ) ;
94
+ } ) ;
89
95
it ( "test ?:" , function ( ) {
90
96
shouldBeSame ( "1 ?? 2 ? 3 : 5" , "(1 ?? 2) ? 3 : 5" ) ;
91
97
shouldBeSame ( "1 and 2 ? 3 : 5" , "1 and (2 ? 3 : 5)" ) ;
Original file line number Diff line number Diff line change @@ -182,6 +182,41 @@ Program {
182
182
}
183
183
` ;
184
184
185
+ exports [` bin ** right-associative 1` ] = `
186
+ Program {
187
+ " children" : Array [
188
+ ExpressionStatement {
189
+ " expression" : Bin {
190
+ " kind" : " bin" ,
191
+ " left" : Variable {
192
+ " curly" : false ,
193
+ " kind" : " variable" ,
194
+ " name" : " a" ,
195
+ },
196
+ " right" : Bin {
197
+ " kind" : " bin" ,
198
+ " left" : Variable {
199
+ " curly" : false ,
200
+ " kind" : " variable" ,
201
+ " name" : " b" ,
202
+ },
203
+ " right" : Variable {
204
+ " curly" : false ,
205
+ " kind" : " variable" ,
206
+ " name" : " c" ,
207
+ },
208
+ " type" : " **" ,
209
+ },
210
+ " type" : " **" ,
211
+ },
212
+ " kind" : " expressionstatement" ,
213
+ },
214
+ ],
215
+ " errors" : Array [],
216
+ " kind" : " program" ,
217
+ }
218
+ ` ;
219
+
185
220
exports [` bin + 1` ] = `
186
221
Program {
187
222
" children" : Array [
@@ -567,25 +602,25 @@ Program {
567
602
ExpressionStatement {
568
603
" expression" : Bin {
569
604
" kind" : " bin" ,
570
- " left" : Bin {
605
+ " left" : Variable {
606
+ " curly" : false ,
607
+ " kind" : " variable" ,
608
+ " name" : " a" ,
609
+ },
610
+ " right" : Bin {
571
611
" kind" : " bin" ,
572
612
" left" : Variable {
573
613
" curly" : false ,
574
614
" kind" : " variable" ,
575
- " name" : " foo " ,
615
+ " name" : " b " ,
576
616
},
577
617
" right" : Variable {
578
618
" curly" : false ,
579
619
" kind" : " variable" ,
580
- " name" : " bar " ,
620
+ " name" : " c " ,
581
621
},
582
622
" type" : " ??" ,
583
623
},
584
- " right" : Variable {
585
- " curly" : false ,
586
- " kind" : " variable" ,
587
- " name" : " bazz" ,
588
- },
589
624
" type" : " ??" ,
590
625
},
591
626
" kind" : " expressionstatement" ,
Original file line number Diff line number Diff line change @@ -103,8 +103,11 @@ describe("bin", () => {
103
103
it ( "??" , ( ) => {
104
104
expect ( parser . parseEval ( "$foo ?? $bar;" ) ) . toMatchSnapshot ( ) ;
105
105
} ) ;
106
+ it ( "** right-associative" , ( ) => {
107
+ expect ( parser . parseEval ( "$a ** $b ** $c;" ) ) . toMatchSnapshot ( ) ;
108
+ } ) ;
106
109
it ( "?? right-associative" , ( ) => {
107
- expect ( parser . parseEval ( "$foo ?? $bar ?? $bazz ;" ) ) . toMatchSnapshot ( ) ;
110
+ expect ( parser . parseEval ( "$a ?? $b ?? $c ;" ) ) . toMatchSnapshot ( ) ;
108
111
} ) ;
109
112
it ( "?? (php < 7)" , function ( ) {
110
113
const astErr = parser . parseEval ( `$var ?? $var;` , {
You can’t perform that action at this time.
0 commit comments