%PDF- %PDF-
| Direktori : /home/qgbqkvz/www/wp-content/plugins/wp-scss/scssphp/src/Parser/ |
| Current File : /home/qgbqkvz/www/wp-content/plugins/wp-scss/scssphp/src/Parser/LineScanner.php |
<?php
/**
* SCSSPHP
*
* @copyright 2012-2020 Leaf Corcoran
*
* @license http://opensource.org/licenses/MIT MIT
*
* @link http://scssphp.github.io/scssphp
*/
namespace ScssPhp\ScssPhp\Parser;
/**
* A subclass of {@see StringScanner} that tracks line and column information.
*
* @internal
*/
final class LineScanner extends StringScanner
{
/**
* @var int
*/
private $line = 0;
/**
* @var int
*/
private $column = 0;
/**
* Whether the current position is between a CR character and an LF
* character.
*/
private function betweenCRLF(): bool
{
return $this->peekChar(-1) === "\r" && $this->peekChar() === "\n";
}
public function setPosition(int $position): void
{
$newPosition = $position;
$oldPosition = $this->getPosition();
parent::setPosition($position);
if ($newPosition > $oldPosition) {
$newlines = $this->newlinesIn($this->substring($oldPosition, $newPosition));
$this->line += \count($newlines);
if ($newlines === []) {
$this->column += $newPosition - $oldPosition;
} else {
$last = $newlines[\count($newlines) - 1];
$end = $last[1] + \strlen($last[0]);
$this->column = $newPosition - $end;
}
} else {
$newlines = $this->newlinesIn($this->substring($newPosition, $oldPosition));
if ($this->betweenCRLF()) {
array_pop($newlines);
}
$this->line -= \count($newlines);
if ($newlines === []) {
$this->column -= $oldPosition - $newPosition;
} else {
// TODO check that
$this->column = $newPosition - strrpos($this->getString(), "\n", $newPosition) - 1;
}
}
}
/**
* @phpstan-impure
*/
public function scanChar(string $char): bool
{
if (!parent::scanChar($char)) {
return false;
}
$this->adjustLineAndColumn($char);
return true;
}
/**
* @phpstan-impure
*/
public function readChar(): string
{
$character = parent::readChar();
$this->adjustLineAndColumn($character);
return $character;
}
/**
* @phpstan-impure
*/
public function readUtf8Char(): string
{
$character = parent::readUtf8Char();
$this->adjustLineAndColumn($character);
return $character;
}
/**
* Adjusts {@see line} and {@see column} after having consumed $character.
*/
private function adjustLineAndColumn(string $character): void
{
if ($character === "\n" || ($character === "\r" && $this->peekChar() !== "\n")) {
$this->line += 1;
$this->column = 0;
} else {
$this->column += \strlen($character);
}
}
/**
* @phpstan-impure
*/
public function scan(string $string): bool
{
if (!parent::scan($string)) {
return false;
}
$newlines = $this->newlinesIn($string);
$this->line += \count($newlines);
if ($newlines === []) {
$this->column += \strlen($string);
} else {
$last = $newlines[\count($newlines) - 1];
$end = $last[1] + \strlen($last[0]);
$this->column = \strlen($string) - $end;
}
return true;
}
/**
* @phpstan-return list<array{string, int}>
*/
private function newlinesIn(string $text): array
{
preg_match_all('/\r\n?|\n/', $text, $matches, PREG_OFFSET_CAPTURE);
$newlines = $matches[0];
if ($this->betweenCRLF()) {
array_pop($newlines);
}
return $newlines;
}
}