scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 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 }