1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\PhpDocParser\Parser;
4:
5: use Exception;
6: use PHPStan\PhpDocParser\Lexer\Lexer;
7: use function assert;
8: use function json_encode;
9: use function sprintf;
10: use const JSON_INVALID_UTF8_SUBSTITUTE;
11: use const JSON_UNESCAPED_SLASHES;
12: use const JSON_UNESCAPED_UNICODE;
13:
14: class ParserException extends Exception
15: {
16:
17: /** @var string */
18: private $currentTokenValue;
19:
20: /** @var int */
21: private $currentTokenType;
22:
23: /** @var int */
24: private $currentOffset;
25:
26: /** @var int */
27: private $expectedTokenType;
28:
29: /** @var string|null */
30: private $expectedTokenValue;
31:
32: /** @var int|null */
33: private $currentTokenLine;
34:
35: public function __construct(
36: string $currentTokenValue,
37: int $currentTokenType,
38: int $currentOffset,
39: int $expectedTokenType,
40: ?string $expectedTokenValue = null,
41: ?int $currentTokenLine = null
42: )
43: {
44: $this->currentTokenValue = $currentTokenValue;
45: $this->currentTokenType = $currentTokenType;
46: $this->currentOffset = $currentOffset;
47: $this->expectedTokenType = $expectedTokenType;
48: $this->expectedTokenValue = $expectedTokenValue;
49: $this->currentTokenLine = $currentTokenLine;
50:
51: parent::__construct(sprintf(
52: 'Unexpected token %s, expected %s%s at offset %d%s',
53: $this->formatValue($currentTokenValue),
54: Lexer::TOKEN_LABELS[$expectedTokenType],
55: $expectedTokenValue !== null ? sprintf(' (%s)', $this->formatValue($expectedTokenValue)) : '',
56: $currentOffset,
57: $currentTokenLine === null ? '' : sprintf(' on line %d', $currentTokenLine)
58: ));
59: }
60:
61:
62: public function getCurrentTokenValue(): string
63: {
64: return $this->currentTokenValue;
65: }
66:
67:
68: public function getCurrentTokenType(): int
69: {
70: return $this->currentTokenType;
71: }
72:
73:
74: public function getCurrentOffset(): int
75: {
76: return $this->currentOffset;
77: }
78:
79:
80: public function getExpectedTokenType(): int
81: {
82: return $this->expectedTokenType;
83: }
84:
85:
86: public function getExpectedTokenValue(): ?string
87: {
88: return $this->expectedTokenValue;
89: }
90:
91:
92: public function getCurrentTokenLine(): ?int
93: {
94: return $this->currentTokenLine;
95: }
96:
97:
98: private function formatValue(string $value): string
99: {
100: $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE);
101: assert($json !== false);
102:
103: return $json;
104: }
105:
106: }
107: