From 8bf1fa822dd9bb3d91ead43ec08e506285f8168b Mon Sep 17 00:00:00 2001 From: Vadym Slizov Date: Sat, 26 Dec 2020 19:38:45 +0200 Subject: [PATCH] refactoring: update ast structure of "Foreach" node --- internal/php5/parser_test.go | 461 +++++------------------------- internal/php5/php5.go | Bin 265070 -> 265275 bytes internal/php5/php5.y | 81 ++++-- internal/php7/parser_test.go | 461 +++++------------------------- internal/php7/php7.go | Bin 219555 -> 219466 bytes internal/php7/php7.y | 50 ++-- pkg/ast/node.go | 1 + pkg/ast/visitor/dumper.go | 1 + pkg/ast/visitor/formatter.go | 3 + pkg/ast/visitor/formatter_test.go | 38 +++ pkg/ast/visitor/printer.go | 1 + pkg/ast/visitor/printer_test.go | 33 +++ 12 files changed, 310 insertions(+), 820 deletions(-) diff --git a/internal/php5/parser_test.go b/internal/php5/parser_test.go index 6ff6707..10e9084 100644 --- a/internal/php5/parser_test.go +++ b/internal/php5/parser_test.go @@ -15045,61 +15045,53 @@ func TestStmtForeach_WithRef(t *testing.T) { }, }, }, - Var: &ast.ExprReference{ + AmpersandTkn: &token.Token{ + ID: token.ID(38), + Value: []byte("&"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, - EndPos: 27, + EndPos: 25, }, - AmpersandTkn: &token.Token{ - ID: token.ID(38), - Value: []byte("&"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 24, - EndPos: 25, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 23, - EndPos: 24, - }, + FreeFloating: []*token.Token{ + { + ID: token.T_WHITESPACE, + Value: []byte(" "), + Position: &position.Position{ + StartLine: 1, + EndLine: 1, + StartPos: 23, + EndPos: 24, }, }, }, - Var: &ast.ExprVariable{ + }, + Var: &ast.ExprVariable{ + Position: &position.Position{ + StartLine: 1, + EndLine: 1, + StartPos: 25, + EndPos: 27, + }, + VarName: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, - VarName: &ast.Identifier{ + IdentifierTkn: &token.Token{ + ID: token.T_VARIABLE, + Value: []byte("$v"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, - IdentifierTkn: &token.Token{ - ID: token.T_VARIABLE, - Value: []byte("$v"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - }, - Value: []byte("$v"), }, + Value: []byte("$v"), }, }, CloseParenthesisTkn: &token.Token{ @@ -31770,7 +31762,7 @@ func TestExprClosure_Use(t *testing.T) { EndPos: 36, }, FunctionTkn: &token.Token{ - ID: token.T_FUNCTION, + ID: token.T_FUNCTION, Value: []byte("function"), Position: &position.Position{ StartLine: 1, @@ -31780,7 +31772,7 @@ func TestExprClosure_Use(t *testing.T) { }, FreeFloating: []*token.Token{ { - ID: token.T_OPEN_TAG, + ID: token.T_OPEN_TAG, Value: []byte(" &$v) {}` - - expected := &ast.Root{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 3, - EndPos: 31, - }, - Stmts: []ast.Vertex{ - &ast.StmtForeach{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 3, - EndPos: 31, - }, - ForeachTkn: &token.Token{ - ID: token.T_FOREACH, - Value: []byte("foreach"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 3, - EndPos: 10, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_OPEN_TAG, - Value: []byte(""), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 21, - EndPos: 23, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 20, - EndPos: 21, - }, - }, - }, - }, - Var: &ast.ExprReference{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 24, - EndPos: 27, - }, - AmpersandTkn: &token.Token{ - ID: token.ID(38), - Value: []byte("&"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 24, - EndPos: 25, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 23, - EndPos: 24, - }, - }, - }, - }, - Var: &ast.ExprVariable{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - VarName: &ast.Identifier{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - IdentifierTkn: &token.Token{ - ID: token.T_VARIABLE, - Value: []byte("$v"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - }, - Value: []byte("$v"), - }, - }, - }, - CloseParenthesisTkn: &token.Token{ - ID: token.ID(41), - Value: []byte(")"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 27, - EndPos: 28, - }, - }, - Stmt: &ast.StmtStmtList{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 29, - EndPos: 31, - }, - OpenCurlyBracketTkn: &token.Token{ - ID: token.ID(123), - Value: []byte("{"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 29, - EndPos: 30, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 28, - EndPos: 29, - }, - }, - }, - }, - Stmts: []ast.Vertex{}, - CloseCurlyBracketTkn: &token.Token{ - ID: token.ID(125), - Value: []byte("}"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 30, - EndPos: 31, - }, - }, - }, - }, - }, - EndTkn: &token.Token{}, - } - - lexer := scanner.NewLexer([]byte(src), "5.6", nil) - php5parser := php5.NewParser(lexer, nil) - php5parser.Parse() - actual := php5parser.GetRootNode() - assert.DeepEqual(t, expected, actual) -} - func TestExprShellExec(t *testing.T) { src := "L0jG_}Ng;j&c(lz_{mWIE%Frl4S&3JBV+Qc8PJ(;8*`j3TWSjGS&imdAPEDWr{Xc)*_w3Jk*6;J2dwOyB z>raK($B1?%6%}O_l?yK1AUqrM#i7nJHDhjcR~_9|tWhFO?~M`zg-mzRjv_Igs$)d1 zNTn5ZB9Sh{h&;+k5Rud{QfAU-r?`wh8zw`jf4s_};x*)L-`!If7>O6-TU7Vt7JVYFH_XG$!~7 zI*_lrQ_B$HPh;I8oC;5?G5X$q;woV;(4*ZVO44~3Xjw4Vo~to;oWzU;VKSa##^9tc zlSMZnQmE*dc%KUQiV7N*iX|(~VM%?eSnONegQ{v|EV;r}uKs9%ND&m3;hhLNT8AB! z885q$>#TI?;HyNrB=>6E@a6#`hH73=aa10xk{16U`%_3qb-7-WC3*{LNddbTUklD0 zC|2DyHry_0bB@RtNj}o1Q{MHMfZYsf1@!&(Ai!`IoBu3)=j2>UL0?IUgD~^5h0?HW zAcYqS2bG7aIc-m$Kg5OEZ4RSUM3cATmfRe=UmTjr}=_cmO__O~FUqa}CQJ|hT{!f%$C#i0<$P=mh^k~sh zvGT?0xN%}B%Np9R!9}C^E5~D}<2|6kQ4>Jyz2CwFTGl|x7frxGPPIy=&|;Cxl-UE- z#XPWDMN)a52w)YSEm$Yaa5OzT5wl;}3FW>xQLGXojhZq+=Obkzl!D@A7}dMvL)37+ zET*Q(U`K}TdaHOsS)y7tMMP8cIhCjTm5Mi|UwU9bz}@uCUD&PjbTL9&vVFKxjFx_G zGnRF`NYJ6TiDw+GlP}kY?h?bT$y7QUc2s)?2Opm;deYzD106LVivX%WCql@%Lj+U% z**>voOivV+%wC@(LWJcM_@;#R_{AT=Ag`>#Mpeti2x__)JTsQj&>IT0ex4|_&Wfr2 z4`=;&AGp_;DV;p|6b+t-CR>9>v%j$J_j9!fht=xP2gE!fJcQqPaz@Djz2iYKNn;ll8_&gu~i{u*Y7ieN5!}rTTbC@2(a8I%2*!BRZO1j08+9t0*a& zFv)pUrjz0piumBbHofG2TwF=@ABaA*zn2X5wdUZGBdB>S-U6IHcrGXQtEJ`eRWAZ|$X*wk;Ba zg4+x_seYgAO26C=2bi@`w3}lum}TxWd7|^SqN!Ip%ck%}y~}VyV(-31l`|4^?}NuR5E-reT7JMWxYat9_A6jfA~RP;$igc(>=T0FI+B5!8tgx*%bNgP^o zdoG8b-aVM;lBp%rO6HW#a84*HEiIej9ADxra#nbE?{OuQl9)5CyriNMTaB1fnpjX) zIeEt9veG_%+TPLT0MGs}E`up;FEi46UfbJvFW&ZW@c7^9xr7MpYfr%!Eq_gP_6csz zlVW%$_y1IB!Xy?|TkiiB^Z%zxzoSYwk{I63WBID^r$ukwMB;u))89lWf^YSsrTygt zbnzLHFH=2)kde&cx)1F*BiidV&x$xnjun7CwQ~U**ct1um$E01*d#k!f$HkzVvkU6 zmyP&5E8uyfR*E29y+S;tupeSy0$sNfu^`!U$*Wh2Swf~H(ezEqMWgC)c8Xa&Q>G?! z`0PO~NivH5xXQ$j1$h8?u1|r=LdT1abYhhlhUjM^Z^3Gjt0-rtGPDHJ<~5>PCAmBn z>@se7(po?@x~pD9P)nBdw~*p{>p#>`}YYv(0wh&(PE)k-0 zwutePVJrhi6XVuw12(MsTE+3=|@lP5WCQeDCg9( z8ZbqsrBacQ33TgD5EAhrSZE~Hv{M8Mnc;48gRos0-QM;O$;MkkIyF|g>5Ak83@bq9e5Hoh%t z84c&iB)b0{3l?NydGpVzoj&u92nF#;`r&^8k~ha( zI1F^>X@kQsw8KDsCKoupAIm2vvB55yfve%uBb=!Y+1>jkS}6NZeeFNBNvQb0#eL8T4|%WF6^2DS*5=1#H>j{QpH zqm^o%T>F&>lC1BBsK(Pc31-AZ5r%Tv!9-H{YpR2Wmr0ShpUL5jrgb|D<$&fOi=&Wp zBAp6W$z=NKtXOCvUU&jl*cZRWG}{Sa8X1R_M2EjaBAUV58Ci9t*xhhje>soI=~OdU z4dVPEoIGj&6i_TQ0@2J1DUpi|!XP58ozJnjfIH(Ml-?;w*#XYlq04^rn&nX@ozF!lbX+4w)}ATt4{g zN9F#q7loIAy#`G?{p3q3!|m4l{3LeIfJcIzY0NrcjII$m85);Sd4Rl6dOUoGSZZ0S zLaFw4B-UBii8x;~l$zsUDLlHUQ30C=$_9(wW|Q_*7$U>1baTyN;iR{MWj_iJmU&c^ zA)@%4-bz@gVu?=3CH#mW9f1WO|xL{(GyiL=sEgBjf`z$;B4pq^gdx z3$=9RFZOz4H>mgM>}5E5N~8>>n{R?5HblUZ662A{y5`Gtdb@*s65ic5?D8rAcWm-C z^dDPtp54$@2J2;!@*OEt(ptL+T{CrfH@Qx-i{vy>e;6gNVpqdqgwUAGXgot7jg@B+ z%-rd$u8CH_iRdARDR+{c*e&P*0UPHRt1tAB>sn6_84c|?mLQ$Na)L(Q{d!55q|0cN zrSky%bCgU=(*=FyKP0om>qrae`F=8wd%W(nf>Qd+JeB12Y)ksf{SuTI&jt(i(+|4j z&8!zKQ{eXllW-U!m5HnKxPc($ji<#-M(eGfN|psaE`@mHYL2~zi)gf`lODMQihW7Q zX|L;2@T{Ivsv9h$8u%9^0kl-x!Xhx28D zrBdC=IFXA3EgfT9HyzHwa3YATQC2f&2*!=qw8zK)0UZ!E*OJVFxi^@*8_hBuFAT+f z(%lp{T;52HH;Xu3I81JrD#hi}=zBns_)$f-1~~omNa>VTd~6%{(0#4XR9+VJ=s;DGa9bw3{B%tR<=iY44b6R}fD zx?cXODikz(5?X04LTmcsk5OI%XZ&>GWa&UyH*w220<+I(nQog`zbROik!;DiZi-Q= zoMX_>_f8Wa1W5rQg6?kD(*?4IDc=?_IqU%_vCPWl1bY< zm!|-A+O&q~ym{P{W|8QcCnNQv)v^nUC;7lKSQ0`LhN%*2sg|Ym!UMQyhDH0Zhh&iM z^dJ_KeiWz*?VczS1;}WQ0uH_CVJSF{WG_`ttsg;yvTLMMA9+;bJJ|+o91?zbjAwc% zVh}t@_9*2~kNsIS()W+I+DyaCGLVOk(6tMU;TV5fI6_70jSE1nqyl^Z#{|0i0#ZF@6ZtnTLjxQ=}^^jaCX)r8OwxzbA$Sso*{UHWS7fgQ20<4qQjn& zo#6^yl)W0tVwMbj8f=wGK#n6-g06W6(!z~Ee=o`ypbpUUOK`$BQ@}viAkcDGF0S+O zQgaW2uqW08uR8oCnN%o$!$wT#i5SHd!A^h>am^1t+K;bYWM8uKznfm>K-3>|x4mfZy>PBvXZYh?`d-R8%zbuyYI zV&sX2KixVWP@%Nm2*W@+#3bYM+EKyhDu(Kh!trLelOAf=3n-ZNCGdaY{c4hadb7MtQIBoV z!?6<;itFEQ!SShfcxLvYdn^qrQFT$b#zd*Uzkah8P z>Bl<6($zd_6o&OquWOLXuyZaDSmAcrzV7fF#sDmJ;+=lnDKFA9yFpa9UF^e>leP12 z@-D{NY|47eZrPr#xHZ!~w+FOsdPGnk=ew*Ub^mt|i#%qxx|4^@H!Fiy zhvhgX%-ew5c;<-ZSo!J~*Qo?SJ&zi>8)jHN8;*hcrebIh+R+xIG+EQIRmxA-9G6un zHdrpw-ecrPxL^t*39BF$`RT{5Ru2jqd_v|Mw_-X8oj0Q}-GLfTs|1?ejJKAWt5hNt z^uasT`o95B-_TLTlPeih)?TYT6nPT+dXn1Y*$YmBHUnAUu1nZ;@>>|bBlN6KP0$hjNbfD%#fKEH!M;fyJ3?#K51$X_^DY;Xs zR9A||CZqAixT5W{UK&Y77fG(YF#2qNfU+w4ZONfKpOqarUxie!rttZ45S1T77Ey|B z-T0mCqP+TP1Zx(XS#zc#z?oU|FUa%Wd|lT#)F4Tp`~r`c=5-ZAF3S6Xx!opWXtZ)9 zB|B6e4KEg*c}0yyn#S%)te~7oX#f_eKg`H}4Dr+J1JxwfIpDzV`i=r|3VI?;aWJ`LO%Fkl5h|Ahq<7^ZR##ZOS@u`1`D2BfhILZxvCMOe(fGZc6xXY~ zHWESM53AACX}-FNYBZ9h9i7z_J*Tr;D?t{tI?^(oaototALqr{1~hb_@46|VFAu}O zM4Hwe4divDi_|!Zj8bJF8+h5k*id>o3OgV{WP%wDwe>-!g5k{)9jul;Y1DP9E1j8z z>ewgIDxV`}7n_tAm8UY;{qdoPV^ls`h6Dp>57Yi!0Eh%9h)K3_$}%)ymI?vf*wAJjNpuV$HuI}9P zCi(Zm7U>L5%!)V3eK|S+kQusS&pkAzw;BLEZPKDBjYUDiYI4qr=5DI*s|GkcE-NWA z`|hTrSEvD;2Ldjdvv-rD9~8oP9J6sdT7NsdgELFy8JiAwsbGD&pL)oE9$VAeS!82o zu`e5U5T-82wKtRldNjJ!7p#f6fGzT`lfd?ht&pGL(Jjg5f~XGI<0q^RgP9u3RSFe+ zBf9Crsj5WKPbpY?%hgD5F>(uKm8t&p_*50H1Jl%Tftr;m7$E`#Qevr^Xx?(o_}UEh zx}fK>V9~-)+|4+wtx0SDg{Ae1J1+zME9rlGVc2jk>k+?Af9$%aT zrlwj^%JRMsUk9DBqcfn(0or>#I*f!-*<_&A_^dogLAmI)BANwy?#xwPywTZ)Q-Cl{ z^iV$ZA2GNUWdX-D(Vl_e)JuO*m(#noX!;LU1F7W(6{i6~B7Fc5NGM3J8ln&)Z2$;3 z_CBq;0f*c9k|7Db{yKW7GT_yRp@_Q)0Ii8U1?E;9t}Lhrtn@zJd84_Sk2DR$glyjj z{s>6!5Q!1iRRMT3z+|xw_XAN6AAiV*i}icDNsuMAHesf{*u-4YZF@w;V|6&wRJ5LG^re? zdR6i_O{`MTsS2ng&;#U`c4@WhFjdWfF{Ds7Kj!~{Z@cE~rplSv*+iBkIz1D_+J%1h znfgz+sZ>@^pVQQEH<_)44da9UM(^H=u!_4Ir|>010wqzhyH+X6yd1lpi1M)N;>swQkT)zi3sy~O=`IAIa|Fb=<&G# zwBH|8gSE3ty~V1-Zb!H5!%j44F1FuNt&kSS;!fAz2a9MKhr$HP!g$u1r{+-&SM|T2 z2StKvcDDZJP+4sp2SQ2Q?@Dt^n>)4*b^ivp8y-+wEc9&tM6vck>~87|_May%f5>zg zKV@dD;EoJSM*z4ZG~)Nc05~f1$DvLOaW#DZs!q^>*6>g|)z*prl(2~Tm!T1QJXrE9gplm!@o!#0r?ibWH;2T7#)J{=x7Be0vY>CFtpOun(xBP0Cc0(%^lLmes3Vt~}Xjjq`>} ztHB!8;O=)7>`%qVu)T*nRpC=ag^;)x5?zzr-HG_Dwpa92!GnY1?7MN^I(xzev7by`sEIoyD= z9;)9147cP>U|JKx;Cj3Ai^&Kia6S+7fnk?XVFT zu3}!!`cnVr)hOC@pIS)i_(K;I(TjA=c&^W{WKwA(bPX@VKKG^JzV;xW@Mv_Ml7?#C zau^oD1r-yK;Izh2%?Dx-g})&~Hy>3w02!@CypB|TOclta3`XctlztqqZjVOe-+7_O zVJaNgjLgjQbLHP5hfU2W_O7oJ9W~S=+s;mZ6$wh4aT6pgoLhmj|DJ>rl2AW-{Gu49 zYfl(^Mm0>AomBrsirhx0KIF?I$;*UntB$Jn^yp`5h5hboB?B6oHRT5}#ca;Z&PFEpdh zu}s=nu5LJ|zJ#x{vT6O!d38HyRg8DI;TE*;f&t>D=Z6cby?GvS>K;F;VCJW}iK+1o z{Yl-%(T969UWPGjd`qkjzR18wj1y6dvK_=VSW^V97mn9Bf>*<(J}Vt?Odu=)u(^}s z2CCicCHK43^LVuI<1V`fiUd4J*9JJ20EJwGKS5mK?_l?0Je4&)HNY{DHtd9spvdCK Nuz#tbYl0j}{{rI`ib((f delta 10024 zcmds7_j{Dpwtn{B6G%cxLJg1}N+^O;GBXJ+i9!e<(iBBnXd(g!0tW$UK@borQ6x)` z2%)32fXD1B3Ivc|OgtcjtFL#holoA5yiyQZ z6ekw87Y&8$!_necluSvPo?TmK*B0xQ@aUT{B3npr8l}gHVsZ|XHL1uYD^vbj5k~dm zMHXe2h-gY^CYu&aSC#a(co8l{iawkmT1sK3kh)?lIg*rvHq{kvY1 RZxTt4eDX* zW@U5Gd-X&+ns!7+Q(=~{=^BHDS5Wf?{=tlQMG#$UDEiXb?`4DzPZqlby>T4Nc}8O< zUsC_BBAyBxh}x7Fq$<(+o2mz4WhmVqCMwa?;rMm7rK(EtYs5S{@d(bYy2HA#qRwb4 zRtr8MiSRR$N}^-}jk>Me`ievRQ&6GV9gUWs=kQOh3R6p6b`;G8wWnlVr$^PG^veWiXgo$opq~B9okk*6oKn9 z`TD<0>e(KbKnATIynZ=W`ZSZoGrmjndy2;-ef6Zs5~(_|GjqB#RwdHZ87jG;4Fp-I zD=r>g)e>>}#VLY3-7$lUa`fr$%r~s(ulVjIX!EmJnY-z~@C_2cx0^obB^^{b1tPuJ zOD>djzOQJv=!Pwt&i0i-x>G-~m{-AgbE($=(CeVYLX~8hZz%?(BaLnJQEE5Py3Rp6 z_!op&(-^9E5WYaA^|c9K!b4>ZMI2k|6u~-m(w^rbzFjwbwCct~#9D!6{SW)BnwtMh zgclDLj|-7X#kX-?PIcLc3Y*Aaz4ArjRF*;x3=^@`<+jSA1IwY?A%7EE3a^gO72{wb z0T=mbjOYd5(p6p(yKKTsn6FFgCyHQw?`6^L{*|L9i%?_R@r0lKj0@43$)Y|b%n(me z-c-McM{O6O`odHZCM=DdpDG4etDnj9uf8*lS9_taxzj}seLh)4&>zz=d-t3Or@~i7 z2$c>|m8mdKRHo$VqAlD%AOVd%kNWHmKQGemS0S=;o*K>+kpi09J{!Cg&H^ukW{I9c zxHLv)2QCdU|26U^}*)hu%i zy*o}sS04I&!h{KJMh+j|e{?SoW$u;LY50B>Vjc6|BCMF4FnIWw!3pL{oWKQ%1F~Rv zophyHPKGGjl;&Q8F-=%35~XzeJa_97(aiWK(uNK$6#E6evqV&(M++fsli9>_k)`aZ zZrx$IC{!FZj=;I^9)h7qtcDwm+5{b%NdD4lFjL?%8}-w#Fii;x(E~&DVvkt!Y>f-*aB)>O;+I~He19;QtU<8 z{3QOoxCvPgpTX9Wix?A53cm=_2W`P`OT7Bf7SUHpw_7(U79ZQNB6pUIv2u3MCt{eC zc1yaHzfBxqi7^XcDnw7&j+~7RmbW*D;SMelpW$4N?mAY12l>F0*15q1Xyw!yVscCfk0_lQ2>age{5dN!Y<+X2iSjvR{aE(+?QW97Ht(|`-z>{B`fmX5p?-K zaAHpy#OSAh;;sP)6-@%erHg^ZGL8eX{&-m|6jZhhK4P{lxr)ObB+f8c+o9rgooiwZ zvMQjfWltAwU;&u)`KXPa{8`*%H|}c1hzJ_<3s(62no%vUNTsv4UFhpy!H752$tVxTIpQ{dra3i`L?s&s0zaex zM-yZBPwO|V4wWzdAq*GCt93x#GsuC)bC_F?~puQ0@G%(kcc2|~J zkff0{wgL5r%U@`eSHx(1h9NXK1Ch~Y0f*NjW%`5Y>)%!6ECzb8{sbNOchyYLj%r{K zL%Fx0_B=vN!gwvp`w%b|*z6FZX&P<*QpTHcjq!PcZq$T?9OY=A@}p#!9u_4JOX<3w z4jw0rkL9y!l06Z@)qaXAlheo`b8}_*q8!s1Nz7a{FnCmUy+Pm=AFJq>yb;M%@*Wj5t>#aVmn%8iVj0`&=f)eA+` z+WInq12VuI5|JC4`lEqtC!Oy53<>^GO#@|2Ma*~V*e3G4ln(DhIDcd_T<%EqM@?z> z36()2((&iie}jnCPdj8ErowoXaj}z5T<3sVU2?p1nsnKkPPt?@(*SSnKqFG{@qkRf zN|En#T=(Ze8?ANAm9ULKTG6>4d6YG8sx{*|>r!!%$K!LHR?T5dPIjzV>Qe%pY;P%R zbHV4NYlQ&Zs)dYZx#S&@QI=e~wFE~_m8%O8w1xmLlN zaBKLh4Cs|@8^uBmD{$0&OmbK-9+q$YHpHWnol8?6ht}9N4X!X1L%~pShpxAQB#;0h zD+dj4ixa#o$+{Gg00`M2$kvUDeoxx^H5>Va1cqmiHj5pdu-Ikk z!whtL(l{^TqS>&WMt8=g$Vpea$*%frlUf*A4F#f2r!=D-}4@9^?&hyu_;Z|5K8_2|`8PrAgL2@7v4;vQh z?$d)!U@%b%cGsEmpT~eRfb{Cqrf5}-l83N`dsrRgrOT!JEmj`ENU%12vQ<@~jzck@ z;wFsel06mqr?4qd|Gke@3gvHyVcmU9)gil<&1w6KattipxD*cXU6417Z6$>-aMGP& zkiN%KaK;EQH+DD-z~glX(sMX{HyrZt09_gj={WNmbnQYmqxO5o#y^t{Qkj%hTRplengoq|=M0zTr~S2>UOIlywA%^qbl(m=@BN!gm z7)~%~Z}Z!-9+^dz7V%zy3rI)fibl+aiDO82O##!=7G1ZQ%d3#Riz=fH??C%bq&*`K zb8PfKSd@0k?5FDMKJP+9Am6AF(-rlS#nuR;U#9v5ZCYaN-ssSr5WCdkpq$j+g&2`3 z9{R2g4qd#ASuuz|T9+;dmGs7+unDs{ex)UR_*J~_w@NBekitot)AhGQ)i%ml1Iznu z1+YV_j_N3lTMG|GV&u#8w`&ouI1R=Wf56AiULzB!^lg}0=XElP?FPrz*R-BvzRO}d zr=R+UHf{tDz@*@r>;u7O-A$aK8ARzWMH1)@G3&eQ%6 zK?jnhp~L=9-s0eLDT>2J4ADm>r~-O8DYBTCS_y{o;?b>)y{O^};#50EQ(n4u0R+Tq z*-K%u5#sj2sxKAwM)n%j9eAnn^H_Rjh#E^JpMY-5Rx}oY`KH@IR_=QLy=%8YTI09E z5+k;=C7MJTuN^yBP=@-F-7>>F$+KZeQ`RX-!hmk5m4uU6R28BoDLFq};!;i{K66w!F_ys&O9yqJu zsC-dhDU+{oBO2E|#URQ{caF)oppQV*SW|S|Fl?->^h+cqNYVdMOVE&0P!a4E?i{Z_ zKP875NArKx7nJu6Kmsx}4-pnXZ2lfH<*!jey3c8u2a~rVpw8H+>Iq6ZYp?){QW*P2 zELw0@evS@qRo^$^yN`wqbU?uKa%JSCzUPd0nZRba-+NB>#<&U7kNqeY;t~hVzbuF9 zj0^G$DLr=nf)&kx@B2|`IAwf?tTO2uWVrOa3fJ~KB3;ng>j=z9#FK?`r`k34^^(e+ zmKr#rgK7C`>L#j+kTkgrWobXam%9O595g)~=JTU0<9N$O_SrDYM zd?|xBW=L9H5e{PFtT_!gI=N+Jgoq+&7uBkyjKAX@qoA^~>AXs6kk8#Ss;ajHEeOY% z7OLb01Olt;C#$O-g8D^b%4>=!|6WA#AF8OfzJwQDTv?$#eyo~mOQUXyT7)A*0w*j+ zwA%yAh8x6CY)yseDh*%Fy^V zLR!h7CPhZ8f#}gNhHlQ7qZh>&s(MyWt9gt9IPg-70@aUxh*2Yv#H#EDbQm9ti;=z< z*A@)Jxu&&y^?TWnro^e2d1@Nk;S?FK1|YEkKLkpR74fPahSF%+cJ+v^ouH5`?UcY! zbyy;OEM(eq`Q!HfjVSVlkg#ArEGGjQ?*HST3b%fUYv0T;zGlLlk~M%6V<*#NX;+*FZ% z-Xf1vkHO#$l_*;r1D8%d#2HWj1?p@AXXYS4!cS@3P$&(d#g{FB3r&@Zh!tHtOtoR0 zy!kD>(Ty7p$pUI{6~oDso#~Drdj5qQUA8chhJ(dQDjvhTjb2O|LAPiuvaLx!4%#~w zELdG!>zy#;B@o4--Mk@g#TQ5R+(vM>%Iq6VY>GFCgVDfQ&*XyW+8=p5rd~FFXw0n z@M!pLppkY%?6qEJwEY&EK1iV;HL%iA{J7Echeg&-j4vn1C{3 z4t|>^WwJ(I{8tFslc3!1-@>r_;d*<*BHt;2e07~iJSiGEaGVW2)Rc#6@TydEF=ULw z9yK^xXNc!)l}(qZ8?ax~I++PBOw*)GTV#b(g}B)Fq=VL0IAtv}102*1CnflnZkG;S zt~Qy6jAarDIb#*F*|C*?323sG<0T-L3L10GxxnNulsRIXm`7^)9wF3%lT%pI>Zz|*g&a9^*)9< zr=&eJ-cx!U4{n}8Cq4m}COVnc)HeF{Q`OF@F8{g+yU$dg*$&WSPjhJy6wExB2R%F$ z+>j2_qt8acztb=S?tmP2DdIL+eL8zgJ$m0;#>m~ubieUl^rw|;u^`3zAAtC|Ckv+sZq7W+p8#!t9RpS~{m^y5`%&oz zmHH7gdRhEuJthE5q84Qweh_=7sA)Rr3so#xrRH2wLgXKSNhkY8vS}) z)!;r@WqSJ*#Jc}$1N!~VF!Qb&OwWA-v$5k9CR@hnl5bQ73MqqK(<$=|H~}_b)Jj0D zhpEO2^xtys;lGvN8qY8Vpk=%*zJokwpHY#Nw@KhHfZ%}y53KcYnOEtGOchkTM$Mq( zKft{3xWd7s zr2a5f55hVi{vE1x4J#hP*BdD5Iz;An=;7DZFiG970jK%19o|gp--Ogq#lo)>^!%IZ zCqZBSjH2IuTR8+B{LLuA$PFXoIKA-)UHtsb= z^PlWbR$oh>x(D=yn9hlupTRm)Z(%dR+v>Sqkv7f*Cgi-JYyi&YxylNC-(vuK(bG-T w?>Qh;x*WtytT!DE{Jm1p?TR+vOTNJa7`!BC*#Tr^v^|1&-+O2^gxQ?`3#VndQ~&?~ diff --git a/internal/php5/php5.y b/internal/php5/php5.y index 50edcc3..6b33687 100644 --- a/internal/php5/php5.y +++ b/internal/php5/php5.y @@ -5,6 +5,7 @@ import ( "strconv" "github.com/z7zmey/php-parser/pkg/ast" + "github.com/z7zmey/php-parser/pkg/errors" "github.com/z7zmey/php-parser/pkg/token" ) @@ -983,39 +984,63 @@ unticked_statement: } | T_FOREACH '(' variable T_AS foreach_variable foreach_optional_arg ')' foreach_statement { - $8.(*ast.StmtForeach).ForeachTkn = $1 - $8.(*ast.StmtForeach).OpenParenthesisTkn = $2 - $8.(*ast.StmtForeach).Expr = $3 - $8.(*ast.StmtForeach).AsTkn = $4 - if $6 == nil { - $8.(*ast.StmtForeach).Var = $5 - } else { - $8.(*ast.StmtForeach).Key = $5 - $8.(*ast.StmtForeach).DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn - $8.(*ast.StmtForeach).Var = $6.(*ast.StmtForeach).Var - } - $8.(*ast.StmtForeach).CloseParenthesisTkn = $7 - $8.(*ast.StmtForeach).Position = yylex.(*Parser).builder.NewTokenNodePosition($1, $8) + foreach := $8.(*ast.StmtForeach) - $$ = $8 + foreach.Position = yylex.(*Parser).builder.NewTokenNodePosition($1, $8) + foreach.ForeachTkn = $1 + foreach.OpenParenthesisTkn = $2 + foreach.Expr = $3 + foreach.AsTkn = $4 + foreach.Var = $5 + foreach.CloseParenthesisTkn = $7 + + if $6 != nil { + foreach.Key = foreach.Var + foreach.DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn + foreach.Var = $6.(*ast.StmtForeach).Var + } + + if val, ok := foreach.Key.(*ast.ExprReference); ok { + yylex.(*Parser).errHandlerFunc(errors.NewError("Key element cannot be a reference", val.AmpersandTkn.Position)) + foreach.Key = val.Var + } + + if val, ok := foreach.Var.(*ast.ExprReference); ok { + foreach.AmpersandTkn = val.AmpersandTkn + foreach.Var = val.Var + } + + $$ = foreach } | T_FOREACH '(' expr_without_variable T_AS foreach_variable foreach_optional_arg ')' foreach_statement { - $8.(*ast.StmtForeach).ForeachTkn = $1 - $8.(*ast.StmtForeach).OpenParenthesisTkn = $2 - $8.(*ast.StmtForeach).Expr = $3 - $8.(*ast.StmtForeach).AsTkn = $4 - if $6 == nil { - $8.(*ast.StmtForeach).Var = $5 - } else { - $8.(*ast.StmtForeach).Key = $5 - $8.(*ast.StmtForeach).DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn - $8.(*ast.StmtForeach).Var = $6.(*ast.StmtForeach).Var - } - $8.(*ast.StmtForeach).CloseParenthesisTkn = $7 - $8.(*ast.StmtForeach).Position = yylex.(*Parser).builder.NewTokenNodePosition($1, $8) + foreach := $8.(*ast.StmtForeach) - $$ = $8 + foreach.Position = yylex.(*Parser).builder.NewTokenNodePosition($1, $8) + foreach.ForeachTkn = $1 + foreach.OpenParenthesisTkn = $2 + foreach.Expr = $3 + foreach.AsTkn = $4 + foreach.Var = $5 + foreach.CloseParenthesisTkn = $7 + + if $6 != nil { + foreach.Key = foreach.Var + foreach.DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn + foreach.Var = $6.(*ast.StmtForeach).Var + } + + if val, ok := foreach.Key.(*ast.ExprReference); ok { + yylex.(*Parser).errHandlerFunc(errors.NewError("Key element cannot be a reference", val.AmpersandTkn.Position)) + foreach.Key = val.Var + } + + if val, ok := foreach.Var.(*ast.ExprReference); ok { + foreach.AmpersandTkn = val.AmpersandTkn + foreach.Var = val.Var + } + + $$ = foreach } | T_DECLARE '(' declare_list ')' declare_statement { diff --git a/internal/php7/parser_test.go b/internal/php7/parser_test.go index c33bafd..eb10949 100644 --- a/internal/php7/parser_test.go +++ b/internal/php7/parser_test.go @@ -16524,61 +16524,53 @@ func TestStmtForeach_WithRef(t *testing.T) { }, }, }, - Var: &ast.ExprReference{ + AmpersandTkn: &token.Token{ + ID: token.ID(38), + Value: []byte("&"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, - EndPos: 27, + EndPos: 25, }, - AmpersandTkn: &token.Token{ - ID: token.ID(38), - Value: []byte("&"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 24, - EndPos: 25, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 23, - EndPos: 24, - }, + FreeFloating: []*token.Token{ + { + ID: token.T_WHITESPACE, + Value: []byte(" "), + Position: &position.Position{ + StartLine: 1, + EndLine: 1, + StartPos: 23, + EndPos: 24, }, }, }, - Var: &ast.ExprVariable{ + }, + Var: &ast.ExprVariable{ + Position: &position.Position{ + StartLine: 1, + EndLine: 1, + StartPos: 25, + EndPos: 27, + }, + VarName: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, - VarName: &ast.Identifier{ + IdentifierTkn: &token.Token{ + ID: token.T_VARIABLE, + Value: []byte("$v"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, - IdentifierTkn: &token.Token{ - ID: token.T_VARIABLE, - Value: []byte("$v"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - }, - Value: []byte("$v"), }, + Value: []byte("$v"), }, }, CloseParenthesisTkn: &token.Token{ @@ -36268,7 +36260,7 @@ func TestExprClosure_Use(t *testing.T) { EndPos: 36, }, FunctionTkn: &token.Token{ - ID: token.T_FUNCTION, + ID: token.T_FUNCTION, Value: []byte("function"), Position: &position.Position{ StartLine: 1, @@ -36278,7 +36270,7 @@ func TestExprClosure_Use(t *testing.T) { }, FreeFloating: []*token.Token{ { - ID: token.T_OPEN_TAG, + ID: token.T_OPEN_TAG, Value: []byte(" &$v) {}` - - expected := &ast.Root{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 3, - EndPos: 31, - }, - Stmts: []ast.Vertex{ - &ast.StmtForeach{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 3, - EndPos: 31, - }, - ForeachTkn: &token.Token{ - ID: token.T_FOREACH, - Value: []byte("foreach"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 3, - EndPos: 10, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_OPEN_TAG, - Value: []byte(""), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 21, - EndPos: 23, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 20, - EndPos: 21, - }, - }, - }, - }, - Var: &ast.ExprReference{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 24, - EndPos: 27, - }, - AmpersandTkn: &token.Token{ - ID: token.ID(38), - Value: []byte("&"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 24, - EndPos: 25, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 23, - EndPos: 24, - }, - }, - }, - }, - Var: &ast.ExprVariable{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - VarName: &ast.Identifier{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - IdentifierTkn: &token.Token{ - ID: token.T_VARIABLE, - Value: []byte("$v"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 25, - EndPos: 27, - }, - }, - Value: []byte("$v"), - }, - }, - }, - CloseParenthesisTkn: &token.Token{ - ID: token.ID(41), - Value: []byte(")"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 27, - EndPos: 28, - }, - }, - Stmt: &ast.StmtStmtList{ - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 29, - EndPos: 31, - }, - OpenCurlyBracketTkn: &token.Token{ - ID: token.ID(123), - Value: []byte("{"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 29, - EndPos: 30, - }, - FreeFloating: []*token.Token{ - { - ID: token.T_WHITESPACE, - Value: []byte(" "), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 28, - EndPos: 29, - }, - }, - }, - }, - Stmts: []ast.Vertex{}, - CloseCurlyBracketTkn: &token.Token{ - ID: token.ID(125), - Value: []byte("}"), - Position: &position.Position{ - StartLine: 1, - EndLine: 1, - StartPos: 30, - EndPos: 31, - }, - }, - }, - }, - }, - EndTkn: &token.Token{}, - } - - lexer := scanner.NewLexer([]byte(src), "7.4", nil) - php7parser := php7.NewParser(lexer, nil) - php7parser.Parse() - actual := php7parser.GetRootNode() - assert.DeepEqual(t, expected, actual) -} - func TestExprShellExec(t *testing.T) { src := "cBzk{Fn#o9`9`h4#s-8ci@`hjgN7mg*X>xBZb?erpOJZUh zU0RmYw9f0&Wi%kxUXritDO(o5!rg{?Oh$~mqh`MULjS^r7gx`jQ#t=vc~eJJRo^(H z^ZlJGD6?zZ`70~u%aS{&SJ%!b)-Ih1qGYu2r#awixF$iwq#py~bytz-(ykyOVgO<{_WZL6q> zLm^Z97(Kw0C*`9k%S427iNdmTg5xubpP>CD{pu-MYR6ErsaiwN5f?;c%xub)OX{hF z3!>)Hda86d7?4M@*eA&iv>dM%O3UA9fNZa)IP+EmjV3$|o_(b0G$+aMbu^wr_JUct zj_xBo-yvA&X?l>uLCe8>_B4$pjs#`iW)8^YXXz4(Sm^{8W6kzw>A1s%d6FGNeI&Vp zdPviAR6>Q4(gRE{eV)d1G~8+TmFKBMntMXU$VSK?3b+qL>{#>UMtX~7=S1!+4U;KR z8p=3T{1>oaioWFYB)*)}%$d#9n{m5nHq^_?=XAOJMZ6I%P@|;Ej$9`qM?ryPnmiXa$7j5Qy>La_vUuKl6yK+LPwz~x8DZ|1&AFQ`kK z|48S_xb0Mo|JK-6=Z)K`ks$267Tn!&9i>a{4%j6>C~GG>esg*UB@yLoaQLKU6357~ z3hrV8uhSk9YNoy>`AvF>DC%mnXBUl-qIw)_*h`nm^}DE;!!Yql*y*Xa5DWWu(N>b9 zAH&2uc2PH3u?LaVc449n+C#;z19aD5_f?Gz4NaM~m-Yz7JDzi}45`gVn%DNxBy!DL zR6|{)=m0Qv^E$d*Y8tth{C+=uzy(3cK7gnId8$ckqBxRygPe3}{4-@r<|4e>xDU7f z;{Y9!;`b5oxd&*d+5cy{ouuMJ>L*j*rzuV(5Ov*L^C9J!6YtYp;-E`1Ak9))vvcs1 z^bs8N@-94R-&iMprMH#!u)OlARAz zFKKL`p3=}v3G(6Rv_$+5W0|~%6Xf!q+*S5haFWUYl=iAO5PN;Ze;ORa&2VSb=416g zUU~JGxRP~*0;CStcr-OfDastO=Z6`*Q_mc>tMjGy7=+N$BRiHMJyta1jdza0I9=~U z=vN(~A}Q3sr;pkbp47AsBHQg4|%k-N(i*noQw zg+QlksZ=JM)XdFO5Xh<<$2rD-5hsuw{*sEFfU0?z&&#Dg5jF`pV0$c{$2n10 z*B)<8!11XGe38W>o5NMzI8k0tn!K*OT3H1+WLzO@R50VKv{5y_DTr2h)!0WX-TH^ri z6U^rW7&(gYYXK_$JRJF(F#zO4gZK?w2o)?l$omF^EKd#NYc;tF&48hNw+Gng92>@c zJfQZ9N_sBJ6{^=%3)FeiI0BCF{0{cnGJOQXYe$N6fhKIC6cquVAI;@olU7AroUD!3 z2cc;Qode`D2_c?>eNXQvA`o?Dp6=(nwkaJ#v0KC38=>w&C4e(Yq7m5H7R^3_OE+*N z&~D2cITG$<#&`4KJD?Gq)L*OTHfbs72x?16iGonzf`ui7M#A*Lt00VBP8x-MTamn^ zz4aGd;^YN7GkyF*NR4zv%3VS-crM2XvQft^%@v z0lJbbQ(eLJtRiJgO$ARA|0*p~6}&*2^3jqF>*o0CR#TEGx|XMrW@dQ>mudklsJou$ z$fMI>o`_{7U=_FZI-X1_kblFi(^MnVe42v>!+GY198^Wl)}v(y9CM z)NGD7(`SK*09Iw)V<2athtQhcaqRdUJ!bL5Jto!Fcr~{QB1?^?yT6Ki$d-qArj*U) zD!HTvz6TUSe6zWR2a-my-<+Dq(AtY&?YcIk-ok{sXAPHW@^8g97eKSNw#-!A29gUZ zzPg3bYtaG~5H9h{^hF#mix)t-y|=4?7Amup94DoBLcNrQFpH{p80sn6fb3UI00YV{ z#nj)WW^sGi1)OXS-OZU00VsAC4>bOJaojEJHM%x?U@nxvrkokH3pgLe^E(83hJInn|`Abl&LQ*gOd;F8p)V$Zx4S^FGS?PeoqH! zd&fD;XRoSPp(ut|A0cBMIgmFg1eFu=`^;kbO0<+>wITIyi;mmb$Q!Zwzz5}*!L zCDa6R&uSbQ^Ms4*9d-a2XP`s7vv#j>t*y?oO}dGz=dcQIJI=;4d{(Y_l8a;V0*D}V zJwbWrNmP0)t$j`SDX#G>pJm=`;E5f96K4w6L2|9`Kj7Zd^~hA)ko%$%m_ zz!FUAGq9mFr($@>f0i+q4{XWghRD+93*F6;vc1G5uQuk%E>CC?WFC4R~b~Mf zn^iA!H9AkP>#JcW-ki6MTXmS87mpqn<7kph*a0z-TA85ka{t>dw`Mw$GPskkRuFyR z6rwt?6N&fYPF{w1?S$8h-{4Z4X$Riq7i7h59;q|w7_*}bqjDAR2750`H|^&0^>J&i z@Aq)X9cE3@KE~{y=fX_OeqPG5=RJUtB8!m&IM?PRTRzvluX=iclJNn$2Ad;xJoHK3 z2Y3)|g!aG5AKL%Oa&IubM+qKo*|0nO7gUyG2hoZ8v(eH1q8?4^l#fu2!|o`RBib?4 zg^{UyKSFM{jZ@ks_$1?F)OA2ux}cd&&{jECR(y=wfC$uK*t(_nCwLPU*U6Q4mxTdvVSH1m(p7u>RC?h*dZ zwiRa4QN|c-6-$@JM|rnYX45##gF&hMJ0FoX|HZ}H)4&qm{-3@8vcrbTXY+qz=>O`k zAXq%}3E1tHet&N(+jjZOV_K&zzoRnuI2YUEV%|N@DXe2lhBO`L9BCPikz?QGXu}(e zoH!{t!O8O76PUr8)i|?GBARovI8BOHW{Y zusm7=m{>Dkz(CRz;-1PaAiw?EwkOu!)4zcj&Nq;4^C_eume)J^u)%@#z}(Nj;kUKg zYOS84k-eKj4Y7QAifCFqs;v$<+E3;*BLpq()pmF42rX}_gTgtw2cB`^v#yVG zMjDdw%E_K+Dy#|T& zKiKK*&QaRS%8mifE<~O!H})OucYNOROY1=A7TcTtd7^ z%4{v!@g&CjYvlDI&KjuS0el_O*r~2>IUw+xq0T6_T~hm-n8WmQW<$hDG21S1PS_r~ z?d#<|T6^pw`Fx5uzX~`-qgi$vhZ^vw?@^z)0s$>O9-r zAbST&({{{XI2tv%7doG|$63doRZqX9%A!UjZ{R{FWDbsYwy-7)_+8|JU(>(wee&#B zxZa(2E%?W3N%+&Y h`&q&cle4aJ#+&8}nm}^40uhRjw|-~1%)8nN{SO=Lo{Rth delta 6510 zcma)Ad3e-C(tfIXa&aW#N+9PX+_FGsl9^;cAXz2hCPA)ML?W<)EEtqUP~=n*K>`A) zZ@D&zk`-78AoQw;LAeBxfQX`~AgsG8%Lb1XG~oAk|7IZiJnpl9&2;~|tLu2{t?E9! zz2W*D4J#8{aF%agatoc@f?^(&zm`(G3|L4F{XlIU>QdXVeEsH3r z&W`?zC`AT7TX%=6)6n7vWzIBe;;I)F6;)^P+=s|5-AZxL=BMiJkT+-05P5YW<{}=Y zgoy0BJ573E%vc%u3=Im;_Cv~}(r6l`hm9>BJ+6HnEmNjZGnbhZT1q}K!{8dLX0vIO z5***u^X8(mQc9FMYtl=pt)tn^HBuN_GSg66&b} zfegKL3GHCXTg&lMJ{a~SB=b{paT)dEj2t<7i8_mWF}Y+`2DO*klN6~}E~j*6uTSRW zQHnlOMxBW=WnB)X>JI-$he;-vagtPLkxMsQNgGMN`xC`Vc{_OW->V?j@6&ha~&lPJSTjgvL6QjDBjM+KO$8*&d(J$>tQ^cYF; zcfqsd^m=-Vz1eoZOj+7B00o~FxEdXQFfhSy?BdLN>PcJjj!Oov4G zm*q!{XlJ{|x7W$KPgftM-x2Z*wkBFg%3UWA-uNb;|D4Qeo{F~KmmiZl=izx~Fx zIPLucAY;E*E??sedF3l$*5ac2TZ)t=cfxtzi!>P6@XQC!mki`W`T8Ps%?_BHO_j=C z#+fFz54w&!V1(p6We0dclh&Smolvf&5J!*~ z;GpONf;#CiN6Vh09JD($j2774NusM^!z0X94j+J`!;FYX8L9XUlaE%9&`hkvv{!e^ z78kDsX0Dx~RGT+ihYy#-BLA{PXS z{?|ccoVQPQByoXL06;j)XpuaZ3~f*al5}_qdypBHG7C*Hc?_HA&69P=f!yEyl*HrdSMZ&ow0e_B^6&CTGff9r&eSj8kM!CqumX?3Ubr za=MP{$cdJDy)v{D^m2l$vFbcfhvJ2LA&I7#_w{hTsaKYFOMK+IaJFp* zY%WPQ_kuARd6r62@-Cm2(*dkl_ZW`0D}Lx=?XY=dClYTpq0TY%{GoL3#yw4~vq|%7 zWZ}g9SaK)%OmRlexKS3_||8mme zo;V3v_=}Tr^Kp{jo+PEW!I6K>=lx__3X?mbnOP)peYmH}4EXiPK0GFf5x1Q0i;P1c zER(M8XSFt7DeKSUr14uJs$bO~hi7K|clvZZ(s3Xc$hiLCk`NvDlTQaiuqDkzlZ**c zbCinomO^0PG-)I5;2BENx*$50jg?DQ-N8}Pwv>zI-eJ6qvn-%ek>wn&lZJB{L*o^b zRjR}f=aCZlGe_$lcX7C3jLVa_wO~yLDJkal5*UetGYuYt+bc%$U~*JRtw+4e!Il=TBMp=!SHiUv`^&D2hEy-ZrtyfNFCZ|WT8o4TVKgd{! z&S(<0ef$ug+!X-Ls6HPgAF{@XN|37?{eOx2ia zLvs1B<3g9S;>aZ?$$0ztbhviK94s}3&xR)UamYJ07xtSzZrfZeh<_Z?O$XXW4|&3P*lYC@m=dm+ zKk3ZaY_|Zj5>C!{46(tn8Z=&D_yRoARu6yLIK=0~Mi#Qm0%JOy_Ua-IGng=Hrs{Lg zaGdRl+&aD#t2ifE!mYsHE&*g1B@b4&*7KKgx^Xh%-C7@e)<6plhIMl6a)T|eW9{G- zfE7G!jkOj?8Mh+N3P$9d;Jazu+>U*%{)DfF0}v5sX3|Or$=2fXA{DN;u41o2f;HA8 z=B_o|gOoR5DG$xfhe*CDYe5m-fW2=xc+nrN=(~Rp0<=p=!GCo-cr42H0pEKJ# zuQwd(^zFKAy@8%%g#O#}@R?+oTa59){`dtmo_uEzHkvDpgW+w1$~J#74)zD-^nH<) zQQYEu(njlIkDjuLr?aVgq0EZX(OWn&=-r?>y|;o}LBa;8m0S5XlXo{TP|;)?^s|JK zD#<(8C%FyL3oh8sQ;gP#bOmOu)2-> z?(#A}piD6g9T}mI?&j;bM4>fznOoU#wAhzl2SFjO5jb>Wl_e`1_V=oI1g5M*iuUp{ z9Q{AA@0-$TA7q4XAtPv@oWq1oGM&4hzaweCpSwuaNHAPs3U|?m4)RWv-MWrk`xbkH zcgi3LYL1{t7`?6S80E2iP>oWb84ObQ^>m6Sgs7^zyJ{shJ!oiIf|@Ijzi*09K$f;cmsg7c%9!mF(#5t8 z6F&f7$=mM(hv*d&W#4I(f6!N`Uu`J94|%X@ge*`;o4RI!7$r#`^WFA(w)`U=ZQ+W* zuP9Yv8eb}q*g2FeXFuT|Oy%8s2^m-WDgOuhqrpltAHt;RIsQ+uvpCO(dEG_yv+S-@|&O#zbW4+V24pYfeyfiz~3tKKYCHauEO3dFvvCb$RilY(JP!K-(7`J%i_3{*8$Z$8T_Nk*WiYC%m9>* z-CpTkYadO1!Z*Sz2D_o^a5))y~Ad>~|WKou#S`t!S_EW&Cw~s!UbU z+RZABWG7(~ICR@3lBbk0+1CFGrRKA#q(R~LhT~iCo@q}zg9+!JX}vonLKWQTU0fBp zO%=)RNX*%ST3Jt}1v_}dYG?bXQ!=QYGH*}DppJQM5hQ)MM8~Ud<@0EWaags^Y(cC7_gfEoWG@CmyI?4CvwveKwm4SZbOu_A z(@n6-T8QqaDgK)rGYoS>?05299K7I{rCX7C17g%w;pSLqL5F)*qIz9gwZMuT)BpZF zT5rj@nbh0?=CuTD!V@1}y)-t38RXq4gk@{^syvpgOur7S2LX2_+1Qh%^HS7sk{&7O z!tTFOIy_rb^OL*@$%6X8Ybi0tCg_Zl$_8x0jZwM?e){Qs6O@zj>~|?L8F+n z>>bQLLj|7`S9gZne1bbzvgQnxYxn{z-LlS2cCN=7dGn?xpzGtZ&#Ug2!yXkYqq^dO z$94t4-5;T2K+sORS1iHx-rhkCLZx#PaPl(^I6(678cvXsCThIIXWO`1L<2#|&ia~K z_UW2z^`w0Zwa;ppIV`pdp|$$;)|ols&tKTgV@}!(`{C*1c>okXyci+Q{OapxXLfRkohpL+uPc zt^SOX2Hd7_d$#v!%k4X4?CmOFc>>vb%k2u!ubwQOSfKi;5b^yy%QdpxTt~e6r@ra{ zBNW>PDYyQ7fSPI=C`+|73RNW8o0djf7(gIbFKigc!-M769=R7GNs3@ pF~;2n`TdLAXQN>X@5LAJPWNlqWDWS&H"))) + p.printToken(n.AmpersandTkn, nil) p.printNode(n.Var) p.printToken(n.CloseParenthesisTkn, []byte(")")) p.printToken(n.ColonTkn, nil) diff --git a/pkg/ast/visitor/printer_test.go b/pkg/ast/visitor/printer_test.go index 571f51e..8671134 100644 --- a/pkg/ast/visitor/printer_test.go +++ b/pkg/ast/visitor/printer_test.go @@ -3799,6 +3799,39 @@ func TestPrinterPrintStmtForeach(t *testing.T) { } } +func TestPrinterPrintStmtForeach_Reference(t *testing.T) { + o := bytes.NewBufferString("") + + p := visitor.NewPrinter(o).WithState(visitor.PrinterStatePHP) + n := &ast.StmtForeach{ + Expr: &ast.ExprVariable{ + VarName: &ast.Identifier{Value: []byte("$a")}, + }, + Key: &ast.ExprVariable{ + VarName: &ast.Identifier{Value: []byte("$k")}, + }, + AmpersandTkn: &token.Token{ + Value: []byte("&"), + }, + Var: &ast.ExprVariable{ + VarName: &ast.Identifier{Value: []byte("$v")}, + }, + Stmt: &ast.StmtStmtList{ + Stmts: []ast.Vertex{ + &ast.StmtNop{}, + }, + }, + } + n.Accept(p) + + expected := `foreach($a as$k=>&$v){;}` + actual := o.String() + + if expected != actual { + t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual) + } +} + func TestPrinterPrintStmtFunction(t *testing.T) { o := bytes.NewBufferString("")