1<?php
2
3declare(strict_types=1);
4
5namespace Antlr\Antlr4\Runtime\Error\Exceptions;
6
7use Antlr\Antlr4\Runtime\Atn\Transitions\PredicateTransition;
8use Antlr\Antlr4\Runtime\Parser;
9
10/**
11 * A semantic predicate failed during validation. Validation of predicates
12 * occurs when normally parsing the alternative just like matching a token.
13 * Disambiguating predicate evaluation occurs when we test a predicate during
14 * prediction.
15 */
16class FailedPredicateException extends RecognitionException
17{
18    /** @var int */
19    private $ruleIndex;
20
21    /** @var int */
22    private $predicateIndex;
23
24    /** @var string|null */
25    private $predicate;
26
27    public function __construct(Parser $recognizer, string $predicate, ?string $message = null)
28    {
29        parent::__construct(
30            $recognizer,
31            $recognizer->getInputStream(),
32            $recognizer->getContext(),
33            $this->formatMessage($predicate, $message)
34        );
35
36        $interpreter = $recognizer->getInterpreter();
37
38        if ($interpreter === null) {
39            throw new \RuntimeException('Unexpected null interpreter.');
40        }
41
42        $s = $interpreter->atn->states[$recognizer->getState()];
43
44        $trans = $s->getTransition(0);
45
46        if ($trans instanceof PredicateTransition) {
47            $this->ruleIndex = $trans->ruleIndex;
48            $this->predicateIndex = $trans->predIndex;
49        } else {
50            $this->ruleIndex = 0;
51            $this->predicateIndex = 0;
52        }
53
54        $this->predicate = $predicate;
55        $this->setOffendingToken($recognizer->getCurrentToken());
56    }
57
58    public function getRuleIndex() : int
59    {
60        return $this->ruleIndex;
61    }
62
63    public function getPredicateIndex() : int
64    {
65        return $this->predicateIndex;
66    }
67
68    public function getPredicate() : ?string
69    {
70        return $this->predicate;
71    }
72
73    public function formatMessage(string $predicate, ?string $message = null) : string
74    {
75        if ($message !== null) {
76            return $message;
77        }
78
79        return 'failed predicate: {' . $predicate . '}?';
80    }
81}
82