comparison vendor/symfony/css-selector/Parser/TokenStream.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 1fec387a4317
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\CssSelector\Parser;
13
14 use Symfony\Component\CssSelector\Exception\InternalErrorException;
15 use Symfony\Component\CssSelector\Exception\SyntaxErrorException;
16
17 /**
18 * CSS selector token stream.
19 *
20 * This component is a port of the Python cssselect library,
21 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
22 *
23 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
24 *
25 * @internal
26 */
27 class TokenStream
28 {
29 /**
30 * @var Token[]
31 */
32 private $tokens = array();
33
34 /**
35 * @var bool
36 */
37 private $frozen = false;
38
39 /**
40 * @var Token[]
41 */
42 private $used = array();
43
44 /**
45 * @var int
46 */
47 private $cursor = 0;
48
49 /**
50 * @var Token|null
51 */
52 private $peeked = null;
53
54 /**
55 * @var bool
56 */
57 private $peeking = false;
58
59 /**
60 * Pushes a token.
61 *
62 * @param Token $token
63 *
64 * @return $this
65 */
66 public function push(Token $token)
67 {
68 $this->tokens[] = $token;
69
70 return $this;
71 }
72
73 /**
74 * Freezes stream.
75 *
76 * @return $this
77 */
78 public function freeze()
79 {
80 $this->frozen = true;
81
82 return $this;
83 }
84
85 /**
86 * Returns next token.
87 *
88 * @return Token
89 *
90 * @throws InternalErrorException If there is no more token
91 */
92 public function getNext()
93 {
94 if ($this->peeking) {
95 $this->peeking = false;
96 $this->used[] = $this->peeked;
97
98 return $this->peeked;
99 }
100
101 if (!isset($this->tokens[$this->cursor])) {
102 throw new InternalErrorException('Unexpected token stream end.');
103 }
104
105 return $this->tokens[$this->cursor++];
106 }
107
108 /**
109 * Returns peeked token.
110 *
111 * @return Token
112 */
113 public function getPeek()
114 {
115 if (!$this->peeking) {
116 $this->peeked = $this->getNext();
117 $this->peeking = true;
118 }
119
120 return $this->peeked;
121 }
122
123 /**
124 * Returns used tokens.
125 *
126 * @return Token[]
127 */
128 public function getUsed()
129 {
130 return $this->used;
131 }
132
133 /**
134 * Returns nex identifier token.
135 *
136 * @return string The identifier token value
137 *
138 * @throws SyntaxErrorException If next token is not an identifier
139 */
140 public function getNextIdentifier()
141 {
142 $next = $this->getNext();
143
144 if (!$next->isIdentifier()) {
145 throw SyntaxErrorException::unexpectedToken('identifier', $next);
146 }
147
148 return $next->getValue();
149 }
150
151 /**
152 * Returns nex identifier or star delimiter token.
153 *
154 * @return null|string The identifier token value or null if star found
155 *
156 * @throws SyntaxErrorException If next token is not an identifier or a star delimiter
157 */
158 public function getNextIdentifierOrStar()
159 {
160 $next = $this->getNext();
161
162 if ($next->isIdentifier()) {
163 return $next->getValue();
164 }
165
166 if ($next->isDelimiter(array('*'))) {
167 return;
168 }
169
170 throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next);
171 }
172
173 /**
174 * Skips next whitespace if any.
175 */
176 public function skipWhitespace()
177 {
178 $peek = $this->getPeek();
179
180 if ($peek->isWhitespace()) {
181 $this->getNext();
182 }
183 }
184 }