1 | <?php |
||
8 | class Tokens implements \Iterator, \Countable { |
||
9 | private $tokens = []; |
||
10 | private $iterator = 0; |
||
11 | |||
12 | public function __construct($tokens = []) { |
||
15 | |||
16 | public function count() { |
||
19 | |||
20 | // Iterator Functions |
||
21 | public function current() { |
||
24 | |||
25 | public function key() { |
||
28 | |||
29 | public function next() { |
||
32 | |||
33 | public function valid() { |
||
36 | |||
37 | public function rewind() { |
||
40 | |||
41 | public function add($token) { |
||
42 | if ($token instanceof Tokens) $this->tokens = array_merge($this->tokens, $token->tokens); |
||
43 | else $this->tokens[] = $token; |
||
44 | } |
||
45 | |||
46 | |||
47 | public function end() { |
||
48 | return end($this->tokens); |
||
49 | } |
||
50 | |||
51 | private function getKeysOfTokenType($tokenType) { |
||
52 | return array_keys(array_column($this->tokens, 'type'), $tokenType); |
||
53 | } |
||
54 | |||
55 | private function getKeyToSlice($tokenType) { |
||
56 | $keys = $this->getKeysOfTokenType($tokenType); |
||
57 | if (empty($keys)) return false; |
||
58 | $key = $keys[0]; |
||
59 | for ($i = 0; $key < $this->iterator && isset($keys[$i]); $i++) $key = $keys[$i]; |
||
60 | return $key; |
||
61 | } |
||
62 | |||
63 | public function from($tokenType, $inclusive = false) { |
||
64 | return $this->sliceTokens($tokenType, "from", !$inclusive); |
||
65 | } |
||
66 | |||
67 | public function to($tokenType, $inclusive = false) { |
||
68 | return $this->sliceTokens($tokenType, "to", $inclusive); |
||
69 | } |
||
70 | |||
71 | private function sliceTokens($tokenType, $type, $increment = false) { |
||
72 | $key = $this->getKeyToSlice($tokenType); |
||
73 | if ($key === false) return new Tokens([]); |
||
74 | if ($increment) $key++; |
||
75 | if ($type === "from") return new Tokens(array_slice($this->tokens, $key)); |
||
76 | else return new Tokens(array_slice($this->tokens, $this->iterator, $key)); |
||
77 | } |
||
78 | |||
79 | public function skip($count) { |
||
80 | $this->iterator += $count; |
||
81 | } |
||
82 | |||
83 | public function splitOnToken($tokenType) { |
||
84 | $splitTokens = []; |
||
85 | $i = 0; |
||
86 | foreach ($this->tokens as $token) { |
||
87 | if ($token['type'] === $tokenType) $i++; |
||
88 | else $splitTokens[$i][] = $token; |
||
89 | } |
||
90 | return array_map(function ($tokens) { |
||
91 | return new Tokens($tokens); |
||
92 | }, $splitTokens); |
||
93 | //return $splitTokens; |
||
94 | } |
||
95 | |||
96 | public function trim() { |
||
97 | $tokens = $this->tokens; |
||
98 | $tokensToTrim = [Tokenizer::WHITESPACE, Tokenizer::NEW_LINE]; |
||
99 | // Remove end whitespace |
||
100 | while ($tokens && in_array(end($tokens)['type'], $tokensToTrim)) { |
||
|
|||
101 | array_pop($tokens); |
||
102 | } |
||
103 | // Remove begining whitespace |
||
104 | while (isset($tokens[0]) && in_array($tokens[0]['type'], $tokensToTrim)) { |
||
105 | array_shift($tokens); |
||
106 | } |
||
107 | return new Tokens($tokens); |
||
108 | } |
||
109 | |||
110 | public function removeLine() { |
||
115 | |||
116 | public function read($offset = 0) { |
||
119 | |||
120 | public function type($offset = 0) { |
||
123 | } |
||
124 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.