File manager - Edit - /home/ferretapmx/public_html/plugins/system/helixultimate/vendor/scssphp/scssphp/src/Parser/StringScanner.php
Back
<?php /** * SCSSPHP * * @copyright 2012-2020 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * * @link http://scssphp.github.io/scssphp */ namespace ScssPhp\ScssPhp\Parser; use League\Uri\Contracts\UriInterface; use SourceSpan\FileLocation; use SourceSpan\FileSpan; use SourceSpan\SourceFile; /** * A port of Dart's string_scanner package to be used by the parser. * * The scanner only supports UTF-8 strings. * * Differences with Dart: * - reading a character is reading a byte, not a UTF-16 code unit (as PHP strings are not UTF-16). The * {@see readUtf8Char} method can be used to consume a UTF-8 char. * - characters are represented as a single-char string, not as an integer with their UTF-16 char code * - offsets are based on bytes, not on UTF-16 code units. In practice, parsing Sass generally needs * to peak following chars only when already knowing that the current char is an ASCII one, which * makes this safe. When this assumption does not hold anymore, a different logic should be used * - as strings and regexp cannot be used interchangeably in PHP (in Dart, regexps are a different * object, and both String and Regexp are implementing a Pattern interface for matching), the scanner * exposes supports only strings in scan() and expect(). Should we need support for regexps, a * separate method will be added. * * @internal */ class StringScanner { private readonly string $string; private int $position = 0; private readonly SourceFile $sourceFile; private ?int $lastMatchStart = null; private ?int $lastMatchPosition = null; public function __construct(string $content, ?UriInterface $sourceUrl = null) { $this->string = $content; $this->sourceFile = SourceFile::fromString($content, $sourceUrl); } public function getString(): string { return $this->string; } public function getPosition(): int { return $this->position; } public function setPosition(int $position): void { $this->position = $position; $this->lastMatchStart = null; } public function spanFrom(int $start, ?int $end = null): FileSpan { return $this->sourceFile->span($start, $end ?? $this->position); } /** * The current location of the scanner. */ public function getLocation(): FileLocation { return $this->sourceFile->location($this->position); } /** * Returns an empty span at the current location. */ public function getEmptySpan(): FileSpan { return $this->sourceFile->span($this->position, $this->position); } public function isDone(): bool { return $this->position === \strlen($this->string); } /** * @throws FormatException if the end of the string is reached * * @phpstan-impure */ public function readChar(): string { if ($this->position === \strlen($this->string)) { $this->fail('more input'); } return $this->string[$this->position++]; } /** * @throws FormatException if the end of the string is reached * * @phpstan-impure */ public function readUtf8Char(): string { if ($this->position === \strlen($this->string)) { $this->fail('more input'); } if (\ord($this->string[$this->position]) < 0x80) { return $this->string[$this->position++]; } if (!preg_match('/./usA', $this->string, $m, 0, $this->position)) { $this->fail('utf-8 char'); } $this->position += \strlen($m[0]); return $m[0]; } /** * Consumes the next character in the string if it is the provided character. * * @return bool Whether the character was consumed. * * @phpstan-impure */ public function scanChar(string $char): bool { if ($this->position === \strlen($this->string)) { return false; } if ($this->string[$this->position] !== $char) { return false; } ++$this->position; return true; } /** * Consumes the provided string if it appears at the current position. * * @return bool Whether the string was consumed. * * @phpstan-impure */ public function scan(string $string): bool { if (!$this->matches($string)) { return false; } $this->position += \strlen($string); $this->lastMatchPosition = $this->position; return true; } /** * Returns whether or not the provided string appears at the current position. * * This doesn't move the scan pointer forward. */ public function matches(string $string): bool { if ($this->position - 1 + \strlen($string) >= \strlen($this->string)) { return false; } if (substr($this->string, $this->position, \strlen($string)) === $string) { $this->lastMatchStart = $this->position; $this->lastMatchPosition = $this->position; return true; } return false; } /** * If the next character in the string is $character, consumes it. * * If $character could not be consumed, throws an exception * describing the position of the failure. $name is used in this error as * the expected name of the character being matched; if it's `null`, the * character itself is used instead. * * @throws FormatException * * @phpstan-impure */ public function expectChar(string $character, ?string $name = null): void { if ($this->scanChar($character)) { return; } if ($name === null) { $name = '"' . $character . '"'; } $this->fail($name); } /** * @throws FormatException * * @phpstan-impure */ public function expect(string $string): void { if ($this->scan($string)) { return; } $this->fail('"' . $string . '"'); } /** * @throws FormatException */ public function expectDone(): void { if ($this->isDone()) { return; } $this->fail('no more input'); } /** * Returns the character at the given offset of the current position. * * The offset can be negative to peek already seen characters. * Returns null if the offset goes out of range. * This does not affect the position or the last match. */ public function peekChar(int $offset = 0): ?string { $pos = $this->position + $offset; if ($pos < 0 || $pos >= \strlen($this->string)) { return null; } return $this->string[$pos]; } /** * Returns the substring of the string between $start and $end (excluded). * * $end defaults to the current position. */ public function substring(int $start, ?int $end = null): string { if ($end === null) { $end = $this->position; } if ($end < $start) { return ''; } return substr($this->string, $start, $end - $start); } /** * The scanner's current (zero-based) line number. */ public function getLine(): int { return $this->sourceFile->getLine($this->position); } /** * The scanner's current (zero-based) column number. */ public function getColumn(): int { return $this->sourceFile->getColumn($this->position); } /** * @throws FormatException */ public function error(string $message, ?int $position = null, ?int $length = null): never { if ($position === null && $length === null && $this->getLastMatchStart() !== null) { \assert($this->lastMatchStart !== null); $position = $this->lastMatchStart; $length = $this->position - $position; } $position ??= $this->position; $length ??= 0; $span = $this->sourceFile->span($position, $position + $length); throw new FormatException($message, $span); } private function getLastMatchStart(): ?int { // Lazily unset $this->lastMatchStart so that we avoid extra assignments in // character-by-character methods that are used in core loops. if ($this->lastMatchPosition !== $this->position) { $this->lastMatchStart = null; } return $this->lastMatchStart; } /** * @throws FormatException */ private function fail(string $message): never { $this->error("expected $message."); } }
| ver. 1.4 |
Github
|
.
| PHP 8.2.32 | Generation time: 0.06 |
proxy
|
phpinfo
|
Settings