Passed
Push — master ( c01dfe...f39ce2 )
by Edward
04:04
created

anonymous//src/Lexer/TokenMatcherTemplate.php$0   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 115
rs 10
c 0
b 0
f 0
wmc 15
1
<?php
2
3
namespace Remorhaz\UniLex\Lexer;
4
5
use Remorhaz\UniLex\Exception;
6
use Remorhaz\UniLex\IO\CharBufferInterface;
7
use Remorhaz\UniLex\IO\TokenExtractInterface;
8
9
use function array_diff;
10
use function array_intersect;
11
use function array_key_first;
12
use function array_keys;
13
use function count;
14
15
abstract class TokenMatcherTemplate implements TokenMatcherInterface
16
{
17
18
    private $token;
19
20
    private $mode = self::DEFAULT_MODE;
21
22
    /**
23
     * @return Token
24
     * @throws Exception
25
     */
26
    public function getToken(): Token
27
    {
28
        if (!isset($this->token)) {
29
            throw new Exception("Token is not defined");
30
        }
31
32
        return $this->token;
33
    }
34
35
    protected function createContext(
36
        CharBufferInterface $buffer,
37
        TokenFactoryInterface $tokenFactory
38
    ): TokenMatcherContextInterface {
39
        $onConstruct = function (): void {
40
            unset($this->token);
41
        };
42
        $onSetNewToken = function (int $tokenType) use ($tokenFactory): void {
43
            $this->token = $tokenFactory->createToken($tokenType);
44
        };
45
        $onGetToken = function (): Token {
46
            return $this->getToken();
47
        };
48
        $onSetMode = function (string $mode): void {
49
            $this->mode = $mode;
50
        };
51
        $onGetMode = function (): string {
52
            return $this->mode;
53
        };
54
55
        return new class (
56
            $buffer,
57
            $onConstruct,
58
            $onSetNewToken,
59
            $onGetToken,
60
            $onSetMode,
61
            $onGetMode
62
        ) implements TokenMatcherContextInterface {
63
64
            private $buffer;
65
66
            private $onSetNewToken;
67
68
            private $onGetToken;
69
70
            private $onSetMode;
71
72
            private $onGetMode;
73
74
            private $regExps = [];
75
76
            public function __construct(
77
                CharBufferInterface $buffer,
78
                callable $onConstruct,
79
                callable $onSetNewToken,
80
                callable $onGetToken,
81
                callable $onSetMode,
82
                callable $onGetMode
83
            ) {
84
                $this->buffer = $buffer;
85
                $this->onSetNewToken = $onSetNewToken;
86
                $this->onGetToken = $onGetToken;
87
                $this->onSetMode = $onSetMode;
88
                $this->onGetMode = $onGetMode;
89
                call_user_func($onConstruct);
90
            }
91
92
            public function setNewToken(int $tokenType): TokenMatcherContextInterface
93
            {
94
                call_user_func($this->onSetNewToken, $tokenType);
95
96
                return $this;
97
            }
98
99
            /**
100
             * @param string $name
101
             * @param        $value
102
             * @return TokenMatcherContextInterface
103
             */
104
            public function setTokenAttribute(string $name, $value): TokenMatcherContextInterface
105
            {
106
                $this
107
                    ->getToken()
108
                    ->setAttribute($name, $value);
109
110
                return $this;
111
            }
112
113
            public function getToken(): Token
114
            {
115
                return call_user_func($this->onGetToken);
116
            }
117
118
            public function getBuffer(): CharBufferInterface
119
            {
120
                return $this->buffer;
121
            }
122
123
            public function getSymbolString(): string
124
            {
125
                $buffer = $this->getBuffer();
126
                if ($buffer instanceof TokenExtractInterface) {
127
                    return $buffer->getTokenAsString();
128
                }
129
                throw new Exception("Extracting strings is not supported by buffer");
130
            }
131
132
            public function getSymbolList(): array
133
            {
134
                $buffer = $this->getBuffer();
135
                if ($buffer instanceof TokenExtractInterface) {
136
                    return $buffer->getTokenAsArray();
137
                }
138
                throw new Exception("Extracting arrays is not supported by buffer");
139
            }
140
141
            public function getMode(): string
142
            {
143
                return call_user_func($this->onGetMode);
144
            }
145
146
            public function setMode(string $mode): TokenMatcherContextInterface
147
            {
148
                call_user_func($this->onSetMode, $mode);
149
150
                return $this;
151
            }
152
153
            public function setRegExps(string ...$regExps): void
154
            {
155
                $this->regExps = $regExps;
156
            }
157
158
            public function allowRegExps(string ...$regExps): void
159
            {
160
                $this->regExps = array_intersect($this->regExps, $regExps);
161
            }
162
163
            public function getRegExp(): string
164
            {
165
                if (count($this->regExps) == 1) {
166
                    return $this->regExps[array_key_first($this->regExps)];
167
                }
168
169
                throw new Exception("Target regular expression is undefined");
170
            }
171
        };
172
    }
173
}
174