1<?php
2
3declare(strict_types=1);
4
5namespace Antlr\Antlr4\Runtime\Dfa;
6
7use Antlr\Antlr4\Runtime\Atn\ATNSimulator;
8use Antlr\Antlr4\Runtime\Vocabulary;
9
10/**
11 * A DFA walker that knows how to dump them to serialized strings.
12 */
13class DFASerializer
14{
15    /** @var DFA */
16    private $dfa;
17
18    /** @var Vocabulary */
19    private $vocabulary;
20
21    public function __construct(DFA $dfa, Vocabulary $vocabulary)
22    {
23        $this->dfa = $dfa;
24        $this->vocabulary = $vocabulary;
25    }
26
27    public function toString() : string
28    {
29        if ($this->dfa->s0 === null) {
30            return '';
31        }
32
33        $string = '';
34
35        /** @var DFAState $state */
36        foreach ($this->dfa->getStates() as $state) {
37            $count = $state->edges === null ? 0 : $state->edges->count();
38
39            for ($i = 0; $i < $count; $i++) {
40                /** @var DFAState $t */
41                $t = $state->edges[$i];
42
43                if ($t !== null && $t->stateNumber !== 0x7FFFFFFF) {
44                    $string .= $this->getStateString($state);
45
46                    $label = $this->getEdgeLabel($i);
47
48                    $string .= \sprintf("-%s->%s\n", $label, $this->getStateString($t));
49                }
50            }
51        }
52
53        return $string;
54    }
55
56    protected function getEdgeLabel(int $i) : string
57    {
58        return $this->vocabulary->getDisplayName($i - 1);
59    }
60
61    protected function getStateString(DFAState $state) : string
62    {
63        if ($state->equals(ATNSimulator::error())) {
64            return 'ERROR';
65        }
66
67        $baseStateStr = \sprintf(
68            '%ss%d%s',
69            $state->isAcceptState ? ':' : '',
70            $state->stateNumber,
71            $state->requiresFullContext ? '^' : ''
72        );
73
74        if ($state->isAcceptState) {
75            if ($state->predicates !== null) {
76                return $baseStateStr . '=>[' . \implode(', ', $state->predicates) . ']';
77            }
78
79            return $baseStateStr . '=>' . $state->prediction;
80        }
81
82        return $baseStateStr;
83    }
84
85    public function __toString() : string
86    {
87        return $this->toString();
88    }
89}
90