Skip to content

Commit 562c801

Browse files
author
Kirill Nesmeyanov
committed
Improve exception codes
1 parent e221d93 commit 562c801

File tree

7 files changed

+82
-58
lines changed

7 files changed

+82
-58
lines changed

resources/grammar.php

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,7 @@
309309
}
310310

311311
if ($children[0]->variadic) {
312-
throw new SemanticException(
313-
'Cannot have variadic param with a default',
314-
$offset,
315-
SemanticException::CODE_VARIADIC_WITH_DEFAULT,
316-
);
312+
throw SemanticException::fromVariadicWithDefault($offset);
317313
}
318314

319315
$children[0]->optional = true;
@@ -387,11 +383,7 @@
387383
$key = $field->getKey();
388384

389385
if (\in_array($key, $explicit, true)) {
390-
throw new SemanticException(
391-
\sprintf('Duplicate key "%s"', $key),
392-
$field->offset,
393-
SemanticException::CODE_SHAPE_KEY_DUPLICATION,
394-
);
386+
throw SemanticException::fromShapeFieldDuplication($key, $field->offset);
395387
}
396388

397389
$explicit[] = $key;
@@ -401,11 +393,7 @@
401393
}
402394

403395
if ($explicit !== [] && $implicit) {
404-
throw new SemanticException(
405-
\sprintf('Cannot mix explicit and implicit shape keys', $key),
406-
$offset,
407-
SemanticException::CODE_SHAPE_KEY_MIX,
408-
);
396+
throw SemanticException::fromShapeMixedKeys($offset);
409397
}
410398

411399
return new Node\Stmt\Shape\FieldsListNode($children);
@@ -469,10 +457,9 @@
469457
$children[0],
470458
$children[2],
471459
),
472-
default => throw new SemanticException(
473-
\sprintf('Invalid conditional operator "%s"', $children[1]->getValue()),
460+
default => throw SemanticException::fromInvalidConditionalOperator(
461+
$children[1]->getValue(),
474462
$offset,
475-
SemanticException::CODE_INVALID_OPERATOR,
476463
),
477464
};
478465

resources/grammar/callable.pp2

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,7 @@ OptionalCallableParameter -> {
3535
}
3636

3737
if ($children[0]->variadic) {
38-
throw new SemanticException(
39-
'Cannot have variadic param with a default',
40-
$offset,
41-
SemanticException::CODE_VARIADIC_WITH_DEFAULT,
42-
);
38+
throw SemanticException::fromVariadicWithDefault($offset);
4339
}
4440

4541
$children[0]->optional = true;

resources/grammar/shape-fields.pp2

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,7 @@ ShapeFieldsList -> {
4646
$key = $field->getKey();
4747

4848
if (\in_array($key, $explicit, true)) {
49-
throw new SemanticException(
50-
\sprintf('Duplicate key "%s"', $key),
51-
$field->offset,
52-
SemanticException::CODE_SHAPE_KEY_DUPLICATION,
53-
);
49+
throw SemanticException::fromShapeFieldDuplication($key, $field->offset);
5450
}
5551

5652
$explicit[] = $key;
@@ -60,11 +56,7 @@ ShapeFieldsList -> {
6056
}
6157

6258
if ($explicit !== [] && $implicit) {
63-
throw new SemanticException(
64-
\sprintf('Cannot mix explicit and implicit shape keys', $key),
65-
$offset,
66-
SemanticException::CODE_SHAPE_KEY_MIX,
67-
);
59+
throw SemanticException::fromShapeMixedKeys($offset);
6860
}
6961

7062
return new Node\Stmt\Shape\FieldsListNode($children);

resources/grammar/ternary.pp2

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@ TernaryExpressionOrLogicalType -> {
1919
$children[0],
2020
$children[2],
2121
),
22-
default => throw new SemanticException(
23-
\sprintf('Invalid conditional operator "%s"', $children[1]->getValue()),
22+
default => throw SemanticException::fromInvalidConditionalOperator(
23+
$children[1]->getValue(),
2424
$offset,
25-
SemanticException::CODE_INVALID_OPERATOR,
2625
),
2726
};
2827

src/Exception/FeatureNotAllowedException.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@
44

55
namespace TypeLang\Parser\Exception;
66

7-
final class FeatureNotAllowedException extends SemanticException
7+
class FeatureNotAllowedException extends SemanticException
88
{
99
/**
1010
* @param non-empty-string $name
1111
* @param int<0, max> $offset
12+
*
13+
* @return static
1214
*/
1315
public static function fromFeature(string $name, int $offset = 0): self
1416
{
1517
$message = \sprintf('%s not allowed by parser configuration', $name);
1618

17-
return new self($message, $offset);
19+
return new static($offset, $message);
1820
}
1921
}

src/Exception/ParseException.php

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66

77
class ParseException extends \LogicException implements ParserExceptionInterface
88
{
9-
final public const CODE_UNEXPECTED_TOKEN = 0x01;
9+
final public const ERROR_CODE_UNEXPECTED_TOKEN = 0x01;
1010

11-
final public const CODE_UNRECOGNIZED_TOKEN = 0x02;
11+
final public const ERROR_CODE_UNRECOGNIZED_TOKEN = 0x02;
1212

13-
final public const CODE_UNEXPECTED_SYNTAX_ERROR = 0x03;
13+
final public const ERROR_CODE_UNEXPECTED_SYNTAX_ERROR = 0x03;
1414

15-
final public const CODE_INTERNAL_ERROR = 0x05;
15+
final public const ERROR_CODE_INTERNAL_ERROR = 0x05;
1616

17-
final public const CODE_SEMANTIC_ERROR_BASE = 0x06;
17+
final public const ERROR_CODE_SEMANTIC_ERROR_BASE = 0x06;
1818

19-
public const CODE_LAST = self::CODE_SEMANTIC_ERROR_BASE + SemanticException::CODE_LAST;
19+
protected const CODE_LAST = self::ERROR_CODE_SEMANTIC_ERROR_BASE;
2020

2121
final public function __construct(string $message, int $code = 0, ?\Throwable $previous = null)
2222
{
@@ -37,7 +37,7 @@ public static function fromUnexpectedToken(string $char, string $statement, int
3737
Formatter::suffix($statement, $offset),
3838
]);
3939

40-
return new static($message, self::CODE_UNEXPECTED_TOKEN);
40+
return new static($message, self::ERROR_CODE_UNEXPECTED_TOKEN);
4141
}
4242

4343
/**
@@ -53,7 +53,7 @@ public static function fromUnrecognizedToken(string $token, string $statement, i
5353
Formatter::suffix($statement, $offset),
5454
]);
5555

56-
return new static($message, self::CODE_UNRECOGNIZED_TOKEN);
56+
return new static($message, self::ERROR_CODE_UNRECOGNIZED_TOKEN);
5757
}
5858

5959
/**
@@ -66,28 +66,28 @@ public static function fromUnrecognizedSyntaxError(string $statement, int $offse
6666
Formatter::suffix($statement, $offset),
6767
]);
6868

69-
return new static($message, self::CODE_UNEXPECTED_SYNTAX_ERROR);
69+
return new static($message, self::ERROR_CODE_UNEXPECTED_SYNTAX_ERROR);
7070
}
7171

7272
/**
7373
* @param int<0, max> $offset
7474
*/
7575
public static function fromSemanticError(string $message, string $statement, int $offset, int $code = 0): static
7676
{
77-
$message = \vsprintf('Semantic error, %s in %s %s', [
78-
\lcfirst($message),
77+
$message = \vsprintf('%s in %s %s', [
78+
\ucfirst($message),
7979
Formatter::source($statement),
8080
Formatter::suffix($statement, $offset),
8181
]);
8282

83-
return new static($message, self::CODE_SEMANTIC_ERROR_BASE + $code);
83+
return new static($message, self::ERROR_CODE_SEMANTIC_ERROR_BASE + $code);
8484
}
8585

8686
public static function fromInternalError(string $statement, \Throwable $e): static
8787
{
8888
$message = "An internal error occurred while parsing %s";
8989
$message = \sprintf($message, Formatter::source($statement));
9090

91-
return new static($message, self::CODE_INTERNAL_ERROR, $e);
91+
return new static($message, self::ERROR_CODE_INTERNAL_ERROR, $e);
9292
}
9393
}

src/Exception/SemanticException.php

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,25 @@
66

77
class SemanticException extends \LogicException implements ParserExceptionInterface
88
{
9-
final public const CODE_SHAPE_KEY_DUPLICATION = 0x01;
9+
final public const ERROR_CODE_SHAPE_KEY_DUPLICATION = 0x01;
1010

11-
final public const CODE_SHAPE_KEY_MIX = 0x02;
11+
final public const ERROR_CODE_SHAPE_KEY_MIX = 0x02;
1212

13-
final public const CODE_VARIADIC_WITH_DEFAULT = 0x03;
13+
final public const ERROR_CODE_VARIADIC_WITH_DEFAULT = 0x03;
1414

15-
final public const CODE_INVALID_OPERATOR = 0x04;
15+
final public const ERROR_CODE_INVALID_OPERATOR = 0x04;
1616

17-
public const CODE_LAST = self::CODE_INVALID_OPERATOR;
17+
protected const CODE_LAST = self::ERROR_CODE_INVALID_OPERATOR;
1818

1919
/**
2020
* @param int<0, max> $offset
2121
*/
22-
final public function __construct(string $message, public readonly int $offset, int $code = 0, ?\Throwable $previous = null)
23-
{
22+
final public function __construct(
23+
public readonly int $offset,
24+
string $message,
25+
int $code = 0,
26+
?\Throwable $previous = null
27+
) {
2428
parent::__construct($message, $code, $previous);
2529
}
2630

@@ -31,4 +35,48 @@ public function getOffset(): int
3135
{
3236
return $this->offset;
3337
}
38+
39+
/**
40+
* @param non-empty-string $key
41+
*
42+
* @return static
43+
*/
44+
public static function fromShapeFieldDuplication(string $key, int $offset = 0): self
45+
{
46+
$message = \sprintf('Duplicate key "%s"', $key);
47+
48+
return new static($offset, $message, self::ERROR_CODE_SHAPE_KEY_DUPLICATION);
49+
}
50+
51+
/**
52+
* @return static
53+
*/
54+
public static function fromShapeMixedKeys(int $offset = 0): self
55+
{
56+
$message = 'Cannot mix explicit and implicit shape keys';
57+
58+
return new static($offset, $message, self::ERROR_CODE_SHAPE_KEY_MIX);
59+
}
60+
61+
/**
62+
* @return static
63+
*/
64+
public static function fromVariadicWithDefault(int $offset = 0): self
65+
{
66+
$message = 'Cannot have variadic param with a default';
67+
68+
return new static($offset, $message, self::ERROR_CODE_VARIADIC_WITH_DEFAULT);
69+
}
70+
71+
/**
72+
* @param non-empty-string $operator
73+
*
74+
* @return static
75+
*/
76+
public static function fromInvalidConditionalOperator(string $operator, int $offset = 0): self
77+
{
78+
$message = \sprintf('Invalid conditional operator "%s"', $operator);
79+
80+
return new static($offset, $message, self::ERROR_CODE_INVALID_OPERATOR);
81+
}
3482
}

0 commit comments

Comments
 (0)