Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 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 array $tokens = [];
33
 
34
    /**
35
     * @var Token[]
36
     */
37
    private array $used = [];
38
 
39
    private int $cursor = 0;
40
    private ?Token $peeked;
41
    private bool $peeking = false;
42
 
43
    /**
44
     * Pushes a token.
45
     *
46
     * @return $this
47
     */
48
    public function push(Token $token): static
49
    {
50
        $this->tokens[] = $token;
51
 
52
        return $this;
53
    }
54
 
55
    /**
56
     * Freezes stream.
57
     *
58
     * @return $this
59
     */
60
    public function freeze(): static
61
    {
62
        return $this;
63
    }
64
 
65
    /**
66
     * Returns next token.
67
     *
68
     * @throws InternalErrorException If there is no more token
69
     */
70
    public function getNext(): Token
71
    {
72
        if ($this->peeking) {
73
            $this->peeking = false;
74
            $this->used[] = $this->peeked;
75
 
76
            return $this->peeked;
77
        }
78
 
79
        if (!isset($this->tokens[$this->cursor])) {
80
            throw new InternalErrorException('Unexpected token stream end.');
81
        }
82
 
83
        return $this->tokens[$this->cursor++];
84
    }
85
 
86
    /**
87
     * Returns peeked token.
88
     */
89
    public function getPeek(): Token
90
    {
91
        if (!$this->peeking) {
92
            $this->peeked = $this->getNext();
93
            $this->peeking = true;
94
        }
95
 
96
        return $this->peeked;
97
    }
98
 
99
    /**
100
     * Returns used tokens.
101
     *
102
     * @return Token[]
103
     */
104
    public function getUsed(): array
105
    {
106
        return $this->used;
107
    }
108
 
109
    /**
110
     * Returns next identifier token.
111
     *
112
     * @throws SyntaxErrorException If next token is not an identifier
113
     */
114
    public function getNextIdentifier(): string
115
    {
116
        $next = $this->getNext();
117
 
118
        if (!$next->isIdentifier()) {
119
            throw SyntaxErrorException::unexpectedToken('identifier', $next);
120
        }
121
 
122
        return $next->getValue();
123
    }
124
 
125
    /**
126
     * Returns next identifier or null if star delimiter token is found.
127
     *
128
     * @throws SyntaxErrorException If next token is not an identifier or a star delimiter
129
     */
130
    public function getNextIdentifierOrStar(): ?string
131
    {
132
        $next = $this->getNext();
133
 
134
        if ($next->isIdentifier()) {
135
            return $next->getValue();
136
        }
137
 
138
        if ($next->isDelimiter(['*'])) {
139
            return null;
140
        }
141
 
142
        throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next);
143
    }
144
 
145
    /**
146
     * Skips next whitespace if any.
147
     */
148
    public function skipWhitespace()
149
    {
150
        $peek = $this->getPeek();
151
 
152
        if ($peek->isWhitespace()) {
153
            $this->getNext();
154
        }
155
    }
156
}