1111use JsPhpize \Nodes \FunctionCall ;
1212use JsPhpize \Nodes \HooksArray ;
1313use JsPhpize \Nodes \Main ;
14+ use JsPhpize \Nodes \Node ;
1415use JsPhpize \Nodes \Parenthesis ;
1516use JsPhpize \Nodes \Ternary ;
1617use JsPhpize \Nodes \Value ;
@@ -33,6 +34,11 @@ class Parser extends TokenExtractor
3334 */
3435 protected $ stack ;
3536
37+ /**
38+ * @var Node|null
39+ */
40+ protected $ letForNextBlock ;
41+
3642 public function __construct (JsPhpize $ engine , $ input , $ filename )
3743 {
3844 $ input = str_replace (["\r\n" , "\r" ], ["\n" , '' ], $ input );
@@ -71,6 +77,7 @@ protected function parseParentheses($allowedSeparators = [',', ';'])
7177 while ($ token = $ this ->next ()) {
7278 if ($ token ->is (') ' )) {
7379 $ next = $ this ->get (0 );
80+
7481 if ($ next && $ next ->type === 'lambda ' ) {
7582 $ this ->skip ();
7683
@@ -106,9 +113,9 @@ protected function parseParentheses($allowedSeparators = [',', ';'])
106113
107114 if ($ token ->type === 'keyword ' && $ token ->valueIn (['var ' , 'const ' , 'let ' ])) {
108115 // @TODO handle let scope here
109- // if ($token->value === 'let') {
110- // $this->letForNextBlock = $this->parseLet();
111- // }
116+ if ($ token ->value === 'let ' ) {
117+ $ this ->letForNextBlock = $ this ->parseLet ();
118+ }
112119
113120 continue ;
114121 }
@@ -204,6 +211,7 @@ protected function parseFunctionCallChildren($function, $applicant = null)
204211 $ children [] = $ value ;
205212
206213 $ next = $ this ->get (0 );
214+
207215 if ($ next && $ next ->is ('( ' )) {
208216 $ this ->skip ();
209217
@@ -238,6 +246,7 @@ protected function parseVariable($name)
238246 $ children [] = $ value ;
239247
240248 $ next = $ this ->get (0 );
249+
241250 if ($ next && $ next ->is ('( ' )) {
242251 $ this ->skip ();
243252
@@ -257,6 +266,7 @@ protected function parseVariable($name)
257266
258267 for ($ i = count ($ this ->stack ) - 1 ; $ i >= 0 ; $ i --) {
259268 $ block = $ this ->stack [$ i ];
269+
260270 if ($ block ->isLet ($ name )) {
261271 $ variable ->setScope ($ block );
262272
@@ -272,6 +282,7 @@ protected function parseTernary(Value $condition)
272282 {
273283 $ trueValue = $ this ->expectValue ($ this ->next ());
274284 $ next = $ this ->next ();
285+
275286 if (!$ next ) {
276287 throw new Exception ("Ternary expression not properly closed after '?' " . $ this ->exceptionInfos (), 14 );
277288 }
@@ -281,6 +292,7 @@ protected function parseTernary(Value $condition)
281292 }
282293
283294 $ next = $ this ->next ();
295+
284296 if (!$ next ) {
285297 throw new Exception ("Ternary expression not properly closed after ':' " . $ this ->exceptionInfos (), 16 );
286298 }
@@ -294,6 +306,7 @@ protected function parseTernary(Value $condition)
294306 protected function jsonMethodToPhpFunction ($ method )
295307 {
296308 $ function = null ;
309+
297310 switch ($ method ) {
298311 case 'stringify ' :
299312 $ function = 'json_encode ' ;
@@ -310,6 +323,7 @@ protected function parseJsonMethod($method)
310323 {
311324 if ($ method ->type === 'variable ' && ($ function = $ this ->jsonMethodToPhpFunction ($ method ->value ))) {
312325 $ this ->skip (2 );
326+
313327 if (($ next = $ this ->get (0 )) && $ next ->is ('( ' )) {
314328 $ this ->skip ();
315329
@@ -344,6 +358,7 @@ protected function parseFunction()
344358 $ function = new Block ('function ' );
345359 $ function ->enableMultipleInstructions ();
346360 $ token = $ this ->get (0 );
361+
347362 if ($ token && $ token ->type === 'variable ' ) {
348363 $ this ->skip ();
349364 $ token = $ this ->get (0 );
@@ -356,6 +371,7 @@ protected function parseFunction()
356371 $ this ->skip ();
357372 $ function ->setValue ($ this ->parseParentheses ());
358373 $ token = $ this ->get (0 );
374+
359375 if ($ token && !$ token ->is ('{ ' )) {
360376 throw $ this ->unexpected ($ token );
361377 }
@@ -370,6 +386,7 @@ protected function parseKeywordStatement($token)
370386 {
371387 $ name = $ token ->value ;
372388 $ keyword = new Block ($ name );
389+
373390 switch ($ name ) {
374391 case 'typeof ' :
375392 throw new Exception ('typeof keyword not supported ' , 26 );
@@ -384,9 +401,11 @@ protected function parseKeywordStatement($token)
384401 'clone ' => 'Object ' ,
385402 ];
386403 $ value = $ this ->get (0 );
404+
387405 if (isset ($ expects [$ name ]) && !$ value ) {
388406 throw new Exception ($ expects [$ name ] . " expected after ' " . $ name . "' " , 25 );
389407 }
408+
390409 $ this ->handleOptionalValue ($ keyword , $ value , $ name );
391410 break ;
392411 case 'case ' :
@@ -407,6 +426,7 @@ protected function parseKeywordStatement($token)
407426 protected function parseKeyword ($ token )
408427 {
409428 $ keyword = $ this ->parseKeywordStatement ($ token );
429+
410430 if ($ keyword ->handleInstructions ()) {
411431 $ this ->parseBlock ($ keyword );
412432 }
@@ -417,6 +437,7 @@ protected function parseKeyword($token)
417437 protected function parseLet ()
418438 {
419439 $ letVariable = $ this ->get (0 );
440+
420441 if ($ letVariable ->type !== 'variable ' ) {
421442 throw $ this ->unexpected ($ letVariable );
422443 }
@@ -445,6 +466,7 @@ protected function parseInstruction($block, $token, &$initNext)
445466 if ($ initNext && $ instruction instanceof Variable) {
446467 $ instruction = new Assignation ('= ' , $ instruction , new Constant ('constant ' , 'null ' ));
447468 }
469+
448470 $ initNext = false ;
449471 $ block ->addInstruction ($ instruction );
450472
@@ -486,15 +508,24 @@ protected function parseInstructions($block)
486508 public function parseBlock ($ block )
487509 {
488510 $ this ->stack [] = $ block ;
511+
489512 if (!$ block ->multipleInstructions ) {
490513 $ next = $ this ->get (0 );
514+
491515 if ($ next && $ next ->is ('{ ' )) {
492516 $ block ->enableMultipleInstructions ();
493517 }
518+
494519 if ($ block ->multipleInstructions ) {
495520 $ this ->skip ();
496521 }
497522 }
523+
524+ if ($ this ->letForNextBlock ) {
525+ $ block ->letAfter ($ this ->letForNextBlock );
526+ $ this ->letForNextBlock = null ;
527+ }
528+
498529 $ this ->parseInstructions ($ block );
499530 array_pop ($ this ->stack );
500531 }
0 commit comments