Patched to Drupal 8.4.8 level. See https://www.drupal.org/sa-core-2018-004 and patch...
[yaffs-website] / vendor / symfony / css-selector / Parser / TokenStream.php
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 }