TokenStream::prev()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Scabbia2 Scanners Component
4
 * https://github.com/eserozvataf/scabbia2
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @link        https://github.com/eserozvataf/scabbia2-scanners for the canonical source repository
10
 * @copyright   2010-2016 Eser Ozvataf. (http://eser.ozvataf.com/)
11
 * @license     http://www.apache.org/licenses/LICENSE-2.0 - Apache License, Version 2.0
12
 */
13
14
namespace Scabbia\Scanners;
15
16
use Countable;
17
use Exception;
18
use SeekableIterator;
19
use UnexpectedValueException;
20
use OutOfBoundsException;
21
22
/**
23
 * TokenStream
24
 *
25
 * @package     Scabbia\Scanners
26
 * @author      Eser Ozvataf <[email protected]>
27
 * @since       2.0.0
28
 */
29
class TokenStream implements Countable, SeekableIterator
30
{
31
    /** @type array $tokens set of tokens */
32
    public $tokens = [];
33
    /** @type int   $position */
34
    public $position = 0;
35
36
37
    /**
38
     * Creates a new tokenstream instance from a code piece
39
     *
40
     * @param string $uCode  the string consists of codes to turned into tokens
41
     *
42
     * @return TokenStream the new instance
43
     */
44
    public static function fromString($uCode)
45
    {
46
        return new static(token_get_all($uCode));
47
    }
48
49
    /**
50
     * Initializes a token stream
51
     *
52
     * @param array $uTokens    set of tokens
53
     *
54
     * @return TokenStream
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
55
     */
56
    public function __construct(array $uTokens = [])
57
    {
58
        foreach ($uTokens as $tToken) {
59
            if (is_array($tToken)) {
60
                $this->tokens[] = [$tToken[0], $tToken[1]];
61
            } else {
62
                $this->tokens[] = [null, $tToken];
63
            }
64
        }
65
    }
66
67
    /**
68
     * Count elements of an object
69
     *
70
     * @return int the count as an integer
71
     */
72
    public function count()
73
    {
74
        return count($this->tokens);
75
    }
76
77
    /**
78
     * Seeks to a position
79
     *
80
     * @param int $uPosition the position to seek to
81
     *
82
     * @throws OutOfBoundsException
83
     * @return void
84
     */
85
    public function seek($uPosition)
86
    {
87
        if (!isset($this->tokens[$uPosition])) {
88
            throw new OutOfBoundsException("invalid seek position ({$uPosition})");
89
        }
90
91
        $this->position = $uPosition;
92
    }
93
94
    /**
95
     * Rewind the Iterator to the first element
96
     *
97
     * @return void
98
     */
99
    public function rewind()
100
    {
101
        $this->position = 0;
102
    }
103
104
    /**
105
     * Return the current element
106
     *
107
     * @return mixed
108
     */
109
    public function current()
110
    {
111
        return $this->tokens[$this->position];
112
    }
113
114
    /**
115
     * Return the key of the current element
116
     *
117
     * @return int
118
     */
119
    public function key()
120
    {
121
        return $this->position;
122
    }
123
124
    /**
125
     * Move forward to next element
126
     *
127
     * @return void
128
     */
129
    public function next()
130
    {
131
        $this->position++;
132
    }
133
134
    /**
135
     * Checks if current position is valid
136
     *
137
     * @return bool true on success or false on failure
138
     */
139
    public function valid()
140
    {
141
        return isset($this->tokens[$this->position]);
142
    }
143
144
    /**
145
     * Move back to previous element
146
     *
147
     * @return mixed
148
     */
149
    public function prev()
150
    {
151
        $this->position--;
152
    }
153
154
    /**
155
     * Gets next token if condition is true
156
     *
157
     * @param  array|integer     $uType
158
     * @param  array|string|null $uValue
159
     *
160
     * @return bool
161
     */
162
    public function nextIf($uType, $uValue = null)
163
    {
164
        if ($this->test($uType, $uValue)) {
165
            $this->position++;
166
            return true;
167
        }
168
169
        return false;
170
    }
171
172
    /**
173
     * Advances until a token with the given type is found
174
     *
175
     * @param  array|integer     $uType
176
     * @param  array|string|null $uValue
177
     *
178
     * @return mixed
179
     */
180
    public function nextUntil($uType, $uValue = null)
181
    {
182
        while (!$this->test($uType, $uValue)) {
183
            $this->position++;
184
185
            if (!isset($this->tokens[$this->position])) {
186
                return false;
187
            }
188
        }
189
190
        return true;
191
    }
192
193
    /**
194
     * Tests the current token for a condition
195
     *
196
     * @param  array|integer     $uType
197
     * @param  array|string|null $uValue
198
     *
199
     * @return mixed
200
     */
201
    public function test($uType, $uValue = null)
202
    {
203
        $tToken = $this->tokens[$this->position];
204
205
        if ($uValue !== null) {
206
            if (is_array($uValue) && !in_array($tToken[1], $uValue)) {
207
                return false;
208
            }
209
210
            if ($tToken[1] !== $uValue) {
211
                return false;
212
            }
213
        }
214
215
        if ($tToken[0] !== $uType) {
216
            return false;
217
        }
218
219
        return true;
220
    }
221
222
    /**
223
     * Tests the current token for a condition or throws an exception otherwise
224
     *
225
     * @param  array|integer     $uType
226
     * @param  array|string|null $uValue
227
     * @param  string|null       $uMessage
228
     *
229
     * @throws UnexpectedValueException
230
     * @return void
231
     */
232
    public function expect($uType, $uValue = null, $uMessage = null)
233
    {
234
        if (!$this->test($uType, $uValue)) {
235
            $tToken = $this->tokens[$this->position];
236
237
            throw new UnexpectedValueException(sprintf(
238
                "%sUnexpected token \"%s\" of value \"%s\" (\"%s\" expected%s)",
239
                $uMessage ? "{$uMessage}. " : "",
240
                token_name($tToken[0]),
241
                $tToken[1],
242
                token_name($uType),
243
                ($uValue ? sprintf(" with value \"%s\"", $uValue) : "")
244
            ));
245
        }
246
    }
247
}
248