1
- /*! php-parser - BSD3 License - 2017-07-10 */
1
+ /*! php-parser - BSD3 License - 2017-07-16 */
2
2
3
3
require = ( function e ( t , n , r ) { function s ( o , u ) { if ( ! n [ o ] ) { if ( ! t [ o ] ) { var a = typeof require == "function" && require ; if ( ! u && a ) return a ( o , ! 0 ) ; if ( i ) return i ( o , ! 0 ) ; var f = new Error ( "Cannot find module '" + o + "'" ) ; throw f . code = "MODULE_NOT_FOUND" , f } var l = n [ o ] = { exports :{ } } ; t [ o ] [ 0 ] . call ( l . exports , function ( e ) { var n = t [ o ] [ 1 ] [ e ] ; return s ( n ?n :e ) } , l , l . exports , e , t , n , r ) } return n [ o ] . exports } var i = typeof require == "function" && require ; for ( var o = 0 ; o < r . length ; o ++ ) s ( r [ o ] ) ; return s } ) ( { 1 :[ function ( require , module , exports ) {
4
4
// shim for using process in browser
@@ -309,6 +309,96 @@ AST.prototype.position = function(parser) {
309
309
) ;
310
310
} ;
311
311
312
+
313
+ // operators in ascending order of precedence
314
+ AST . precedence = { } ;
315
+ var binOperatorsPrecedence = [
316
+ [ 'or' ] ,
317
+ [ 'xor' ] ,
318
+ [ 'and' ] ,
319
+ // TODO: assignment / not sure that PHP allows this with expressions
320
+ [ '?' ] ,
321
+ [ '??' ] ,
322
+ [ '||' ] ,
323
+ [ '&&' ] ,
324
+ [ '|' ] ,
325
+ [ '^' ] ,
326
+ [ '&' ] ,
327
+ [ '==' , '!=' , '===' , '!==' , /* '<>', */ '<=>' ] ,
328
+ [ '<' , '<=' , '>' , '>=' ] ,
329
+ [ '<<' , '>>' ] ,
330
+ [ '+' , '-' , '.' ] ,
331
+ [ '*' , '/' , '%' ] ,
332
+ [ '!' ] ,
333
+ [ 'instanceof' ] ,
334
+ // TODO: typecasts
335
+ // TODO: [ (array)
336
+ // TODO: clone, new
337
+ ] . forEach ( function ( list , index ) {
338
+ list . forEach ( function ( operator ) {
339
+ AST . precedence [ operator ] = index + 1 ;
340
+ } ) ;
341
+ } ) ;
342
+
343
+
344
+ /**
345
+ * Check and fix precence, by default using right
346
+ */
347
+ AST . prototype . resolvePrecedence = function ( result ) {
348
+ var buffer ;
349
+ // handling precendence
350
+ if ( result . kind === 'bin' ) {
351
+ if ( result . right ) {
352
+ if ( result . right . kind === 'bin' ) {
353
+ var lLevel = AST . precedence [ result . type ] ;
354
+ var rLevel = AST . precedence [ result . right . type ] ;
355
+ if ( lLevel && rLevel && rLevel <= lLevel ) {
356
+ // https://github.com/glayzzle/php-parser/issues/79
357
+ // shift precedence
358
+ buffer = result . right ;
359
+ result . right = result . right . left ;
360
+ buffer . left = this . resolvePrecedence ( result ) ;
361
+ result = buffer ;
362
+ }
363
+ } else if ( result . right . kind === 'retif' ) {
364
+ var lLevel = AST . precedence [ result . type ] ;
365
+ var rLevel = AST . precedence [ '?' ] ;
366
+ if ( lLevel && rLevel && rLevel <= lLevel ) {
367
+ buffer = result . right ;
368
+ result . right = result . right . test ;
369
+ buffer . test = this . resolvePrecedence ( result ) ;
370
+ result = buffer ;
371
+ }
372
+ }
373
+ }
374
+ } else if ( result . kind === 'unary' ) {
375
+ // https://github.com/glayzzle/php-parser/issues/75
376
+ if ( result . what ) {
377
+ // unary precedence is allways lower
378
+ if ( result . what . kind === 'bin' ) {
379
+ buffer = result . what ;
380
+ result . what = result . what . left ;
381
+ buffer . left = this . resolvePrecedence ( result ) ;
382
+ result = buffer ;
383
+ } else if ( result . what . kind === 'retif' ) {
384
+ buffer = result . what ;
385
+ result . what = result . what . test ;
386
+ buffer . test = this . resolvePrecedence ( result ) ;
387
+ result = buffer ;
388
+ }
389
+ }
390
+ } else if ( result . kind === 'retif' ) {
391
+ // https://github.com/glayzzle/php-parser/issues/77
392
+ if ( result . falseExpr && result . falseExpr . kind === 'retif' ) {
393
+ buffer = result . falseExpr ;
394
+ result . falseExpr = buffer . test ;
395
+ buffer . test = this . resolvePrecedence ( result ) ;
396
+ result = buffer ;
397
+ }
398
+ }
399
+ return result ;
400
+ } ;
401
+
312
402
/**
313
403
* Prepares an AST node
314
404
* @param {String|null } kind - Defines the node type
@@ -357,22 +447,7 @@ AST.prototype.prepare = function(kind, parser) {
357
447
}
358
448
var result = Object . create ( node . prototype ) ;
359
449
node . apply ( result , args ) ;
360
- if (
361
- result . kind === 'bin' &&
362
- result . right &&
363
- typeof result . right . precedence === 'function'
364
- ) {
365
- var out = result . right . precedence ( result ) ;
366
- if ( out ) { // shift with precedence
367
- result = out ;
368
- }
369
- } else if ( result . kind === 'unary' && result . what ) {
370
- var out = result . precedence ( result . what ) ;
371
- if ( out ) { // shift with precedence
372
- result = out ;
373
- }
374
- }
375
- return result ;
450
+ return self . resolvePrecedence ( result ) ;
376
451
} ;
377
452
} ;
378
453
@@ -556,37 +631,6 @@ module.exports = Assign;
556
631
557
632
var Operation = require ( './operation' ) ;
558
633
var KIND = 'bin' ;
559
-
560
- // operators in ascending order of precedence
561
- var binOperatorsPrecedence = [
562
- [ 'or' ] ,
563
- [ 'xor' ] ,
564
- [ 'and' ] ,
565
- // TODO: assignment / not sure that PHP allows this with expressions
566
- [ 'retif' ] ,
567
- [ '??' ] ,
568
- [ '||' ] ,
569
- [ '&&' ] ,
570
- [ '|' ] ,
571
- [ '^' ] ,
572
- [ '&' ] ,
573
- [ '==' , '!=' , '===' , '!==' , /* '<>', */ '<=>' ] ,
574
- [ '<' , '<=' , '>' , '>=' ] ,
575
- [ '<<' , '>>' ] ,
576
- [ '+' , '-' , '.' ] ,
577
- [ '*' , '/' , '%' ] ,
578
- [ '!' ] ,
579
- [ 'instanceof' ] ,
580
- // TODO: typecasts
581
- // TODO: [ (array)
582
- // TODO: clone, new
583
- ] ;
584
-
585
- /*
586
- x OP1 (y OP2 z)
587
- z OP1 (x OP2 y)
588
- z OP2 (x OP1 y)
589
- */
590
634
/**
591
635
* Binary operations
592
636
* @constructor Bin
@@ -602,25 +646,6 @@ var Bin = Operation.extends(function Bin(type, left, right, location) {
602
646
this . right = right ;
603
647
} ) ;
604
648
605
- Bin . prototype . precedence = function ( node ) {
606
- var lLevel = Bin . precedence [ node . type ] ;
607
- var rLevel = Bin . precedence [ this . type ] ;
608
- if ( lLevel && rLevel && rLevel < lLevel ) {
609
- // shift precedence
610
- node . right = this . left ;
611
- this . left = node ;
612
- return this ;
613
- }
614
- } ;
615
-
616
- // define nodes shifting
617
- Bin . precedence = { } ;
618
- binOperatorsPrecedence . forEach ( function ( list , index ) {
619
- list . forEach ( function ( operator ) {
620
- Bin . precedence [ operator ] = index + 1 ;
621
- } ) ;
622
- } ) ;
623
-
624
649
module . exports = Bin ;
625
650
626
651
} , { "./operation" :57 } ] , 6 :[ function ( require , module , exports ) {
@@ -2296,8 +2321,6 @@ module.exports = PropertyLookup;
2296
2321
2297
2322
var Statement = require ( './statement' ) ;
2298
2323
var KIND = 'retif' ;
2299
- var Bin = require ( './bin' ) ;
2300
- var PRECEDENCE = Bin . precedence [ KIND ] ;
2301
2324
2302
2325
/**
2303
2326
* Defines a short if statement that returns a value
@@ -2314,26 +2337,9 @@ var RetIf = Statement.extends(function RetIf(test, trueExpr, falseExpr, location
2314
2337
this . falseExpr = falseExpr ;
2315
2338
} ) ;
2316
2339
2317
- /**
2318
- * Handles precedence over items
2319
- */
2320
- RetIf . prototype . precedence = function ( node ) {
2321
- var what = node . kind === 'bin' ? node . type : node . kind ;
2322
- var lLevel = Bin . precedence [ what ] ;
2323
- if ( lLevel && PRECEDENCE < lLevel ) {
2324
- if ( node . kind === 'bin' ) {
2325
- node . right = this . test ;
2326
- this . test = node ;
2327
- return this ;
2328
- } else {
2329
- throw new Error ( '@todo ' + node . kind ) ;
2330
- }
2331
- }
2332
- } ;
2333
-
2334
2340
module . exports = RetIf ;
2335
2341
2336
- } , { "./bin" : 5 , "./ statement" :70 } ] , 68 :[ function ( require , module , exports ) {
2342
+ } , { "./statement" :70 } ] , 68 :[ function ( require , module , exports ) {
2337
2343
/*!
2338
2344
* Copyright (C) 2017 Glayzzle (BSD3 License)
2339
2345
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
@@ -2719,18 +2725,6 @@ var Unary = Operation.extends(function Unary(type, what, location) {
2719
2725
this . what = what ;
2720
2726
} ) ;
2721
2727
2722
- Unary . prototype . precedence = function ( node ) {
2723
- if ( node . kind === 'bin' ) {
2724
- this . what = node . left ;
2725
- node . left = this ;
2726
- return node ;
2727
- } else if ( node . kind === 'retif' ) {
2728
- this . what = node . test ;
2729
- node . test = this ;
2730
- return node ;
2731
- }
2732
- } ;
2733
-
2734
2728
module . exports = Unary ;
2735
2729
2736
2730
} , { "./operation" :57 } ] , 83 :[ function ( require , module , exports ) {
@@ -5940,9 +5934,20 @@ module.exports = {
5940
5934
if ( this . is ( 'VARIABLE' ) ) {
5941
5935
var result = this . node ( ) ;
5942
5936
expr = this . read_variable ( false , false , false ) ;
5937
+
5938
+ // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L877
5939
+ // should accept only a variable
5940
+ var isConst = (
5941
+ expr . kind === 'constref' || (
5942
+ expr . kind === 'staticlookup' &&
5943
+ expr . offset . kind === 'constref'
5944
+ )
5945
+ ) ;
5946
+
5943
5947
// VARIABLES SPECIFIC OPERATIONS
5944
5948
switch ( this . token ) {
5945
5949
case '=' :
5950
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5946
5951
var right ;
5947
5952
if ( this . next ( ) . token == '&' ) {
5948
5953
if ( this . next ( ) . token === this . tok . T_NEW ) {
@@ -5957,45 +5962,59 @@ module.exports = {
5957
5962
5958
5963
// operations :
5959
5964
case this . tok . T_PLUS_EQUAL :
5965
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5960
5966
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '+=' ) ;
5961
5967
5962
5968
case this . tok . T_MINUS_EQUAL :
5969
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5963
5970
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '-=' ) ;
5964
5971
5965
5972
case this . tok . T_MUL_EQUAL :
5973
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5966
5974
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '*=' ) ;
5967
5975
5968
5976
case this . tok . T_POW_EQUAL :
5977
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5969
5978
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '**=' ) ;
5970
5979
5971
5980
case this . tok . T_DIV_EQUAL :
5981
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5972
5982
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '/=' ) ;
5973
5983
5974
5984
case this . tok . T_CONCAT_EQUAL :
5985
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5975
5986
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '.=' ) ;
5976
5987
5977
5988
case this . tok . T_MOD_EQUAL :
5989
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5978
5990
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '%=' ) ;
5979
5991
5980
5992
case this . tok . T_AND_EQUAL :
5993
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5981
5994
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '&=' ) ;
5982
5995
5983
5996
case this . tok . T_OR_EQUAL :
5997
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5984
5998
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '|=' ) ;
5985
5999
5986
6000
case this . tok . T_XOR_EQUAL :
6001
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5987
6002
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '^=' ) ;
5988
6003
5989
6004
case this . tok . T_SL_EQUAL :
6005
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5990
6006
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '<<=' ) ;
5991
6007
5992
6008
case this . tok . T_SR_EQUAL :
6009
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5993
6010
return result ( 'assign' , expr , this . next ( ) . read_expr ( ) , '>>=' ) ;
5994
6011
5995
6012
case this . tok . T_INC :
6013
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5996
6014
this . next ( ) ;
5997
6015
return result ( 'post' , '+' , expr ) ;
5998
6016
case this . tok . T_DEC :
6017
+ if ( isConst ) this . error ( 'VARIABLE' ) ;
5999
6018
this . next ( ) ;
6000
6019
return result ( 'post' , '-' , expr ) ;
6001
6020
}
@@ -7413,18 +7432,19 @@ module.exports = {
7413
7432
case this . tok . T_STRING :
7414
7433
var current = [ this . token , this . lexer . getState ( ) ] ;
7415
7434
var label = this . text ( ) ;
7435
+ // AST : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L457
7416
7436
if ( this . next ( ) . token === ':' ) {
7417
7437
var result = this . node ( 'label' ) ;
7418
7438
this . next ( ) ;
7419
7439
return result ( label ) ;
7420
- } else {
7421
- // default fallback expr
7422
- this . lexer . tokens . push ( current ) ;
7423
- var expr = this . next ( ) . read_expr ( ) ;
7424
- this . expect ( [ ';' , this . tok . T_CLOSE_TAG ] ) && this . nextWithComments ( ) ;
7425
- return expr ;
7426
7440
}
7427
7441
7442
+ // default fallback expr / T_STRING '::' (etc...)
7443
+ this . lexer . tokens . push ( current ) ;
7444
+ var expr = this . next ( ) . read_expr ( ) ;
7445
+ this . expectEndOfStatement ( ) ;
7446
+ return expr ;
7447
+
7428
7448
case this . tok . T_GOTO :
7429
7449
var result = this . node ( 'goto' ) , label = null ;
7430
7450
if ( this . next ( ) . expect ( this . tok . T_STRING ) ) {
0 commit comments