|
16 | 16 | use DevTheorem\HandlebarsParser\Ast\InverseChain; |
17 | 17 | use DevTheorem\HandlebarsParser\Ast\Literal; |
18 | 18 | use DevTheorem\HandlebarsParser\Ast\MustacheStatement; |
| 19 | +use DevTheorem\HandlebarsParser\Ast\Node; |
19 | 20 | use DevTheorem\HandlebarsParser\Ast\OpenBlock; |
20 | 21 | use DevTheorem\HandlebarsParser\Ast\OpenHelper; |
21 | 22 | use DevTheorem\HandlebarsParser\Ast\OpenPartialBlock; |
@@ -167,13 +168,14 @@ protected function postprocessTokens(array $tokens): array |
167 | 168 |
|
168 | 169 | if ($numTokens === 0) { |
169 | 170 | // empty input - just add sentinel token |
170 | | - return [new Token(Lexer::T_EOF, "\0", 0)]; |
| 171 | + return [new Token(Lexer::T_EOF, "\0", 0, 0)]; |
171 | 172 | } |
172 | 173 |
|
173 | 174 | $lastToken = $tokens[$numTokens - 1]; |
174 | 175 |
|
175 | 176 | // Add sentinel token |
176 | | - $tokens[] = new Token(Lexer::T_EOF, "\0", $lastToken->line); |
| 177 | + $column = $lastToken->column + strlen($lastToken->text); |
| 178 | + $tokens[] = new Token(Lexer::T_EOF, "\0", $lastToken->line, $column); |
177 | 179 | return $tokens; |
178 | 180 | } |
179 | 181 |
|
@@ -384,6 +386,12 @@ protected function getErrorMessage(int $symbol, int $state, int $line): string |
384 | 386 | return "Parse error on line $line" . $expectedString . ', got ' . $this->symbolToName[$symbol]; |
385 | 387 | } |
386 | 388 |
|
| 389 | + private function getNodeError(string $message, Node $node): string |
| 390 | + { |
| 391 | + $start = $node->loc->start; |
| 392 | + return $message . ' - ' . $start->line . ':' . $start->column; |
| 393 | + } |
| 394 | + |
387 | 395 | /** |
388 | 396 | * Get limited number of expected tokens in given state. |
389 | 397 | * |
@@ -498,14 +506,11 @@ protected function locInfo(int $tokenStartPos, int $tokenEndPos): SourceLocation |
498 | 506 | { |
499 | 507 | $startToken = $this->tokens[$tokenStartPos]; |
500 | 508 | $endToken = $this->tokens[$tokenEndPos]; |
501 | | - $source = ''; |
502 | 509 |
|
503 | | - for ($i = $tokenStartPos; $i <= $tokenEndPos; $i++) { |
504 | | - $token = $this->tokens[$i]; |
505 | | - $source .= $token->text; |
506 | | - } |
| 510 | + $start = new Position($startToken->line, $startToken->column); |
| 511 | + $end = new Position($endToken->line, $endToken->column + strlen($endToken->text)); |
507 | 512 |
|
508 | | - return new SourceLocation($source, new Position($startToken->line, -1), new Position($endToken->line, -1)); |
| 513 | + return new SourceLocation($start, $end); |
509 | 514 | } |
510 | 515 |
|
511 | 516 | protected function id(string $token): string |
@@ -537,9 +542,9 @@ protected function prepareProgram(array $statements, ?SourceLocation $loc = null |
537 | 542 | if ($statements) { |
538 | 543 | $firstLoc = $statements[0]->loc; |
539 | 544 | $lastLoc = $statements[count($statements) - 1]->loc; |
540 | | - $loc = new SourceLocation($firstLoc->source, $firstLoc->start, $lastLoc->end); |
| 545 | + $loc = new SourceLocation($firstLoc->start, $lastLoc->end); |
541 | 546 | } else { |
542 | | - $loc = new SourceLocation('', new Position(0, -1), new Position(0, -1)); |
| 547 | + $loc = new SourceLocation(new Position(0, 0), new Position(0, 0)); |
543 | 548 | } |
544 | 549 | } |
545 | 550 |
|
@@ -579,7 +584,8 @@ private function validateClose(OpenHelper $open, CloseBlock|string $close): void |
579 | 584 | } |
580 | 585 |
|
581 | 586 | if ($open->path->original !== $close) { |
582 | | - throw new \Exception("{$open->path->original} doesn't match {$close}"); |
| 587 | + $msg = $this->getNodeError("{$open->path->original} doesn't match {$close}", $open->path); |
| 588 | + throw new \Exception($msg); |
583 | 589 | } |
584 | 590 | } |
585 | 591 |
|
@@ -610,7 +616,8 @@ protected function preparePath(bool $data, SubExpression|null $sexpr, array $par |
610 | 616 |
|
611 | 617 | if (!$isLiteral && ($part === '..' || $part === '.' || $part === 'this')) { |
612 | 618 | if (count($tail) > 0) { |
613 | | - throw new \Exception('Invalid path: ' . $original); |
| 619 | + $msg = $this->getNodeError("Invalid path: $original", new Node('', $loc)); |
| 620 | + throw new \Exception($msg); |
614 | 621 | } elseif ($part === '..') { |
615 | 622 | $depth++; |
616 | 623 | } |
|
0 commit comments