192 lines
4.8 KiB
PHP
192 lines
4.8 KiB
PHP
<?php
|
|
/**
|
|
* @filename ReaderInterface.php
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/17 14:58
|
|
*/
|
|
|
|
|
|
namespace JerryYan\DSL\Reader;
|
|
|
|
|
|
/**
|
|
* 解析器需要使用到的读取类
|
|
* @package JerryYan\DSL\Reader
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/17 15:37
|
|
*/
|
|
abstract class ReaderInterface
|
|
{
|
|
protected $currentLine = 1;
|
|
protected $currentPosition = 0;
|
|
protected $nextPosition = 0;
|
|
protected $currentToken = "";
|
|
protected $currentLineDelta = 0;
|
|
|
|
/**
|
|
* 获取下一个字符
|
|
* @return string
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/18 12:06
|
|
*/
|
|
abstract public function getNextChar(): string;
|
|
|
|
/**
|
|
* 获取下一个识别符
|
|
* @return string
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/18 12:06
|
|
*/
|
|
abstract public function getNextToken(): string;
|
|
|
|
/**
|
|
* 移动至下一个识别符
|
|
* @return bool
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/18 12:06
|
|
*/
|
|
abstract public function moveToNextToken(): bool;
|
|
|
|
abstract protected function getBetween(int $start = 0, int $end = 0): string;
|
|
|
|
/**
|
|
* 从当前位置跳到结束位置
|
|
* @param string[] $chars
|
|
* @param int|null $startAt
|
|
* @param string $matched
|
|
* @return int|null
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/17 15:43
|
|
*/
|
|
abstract public function findNextChars(array $chars, int $startAt = null, string &$matched = ""): ?int;
|
|
|
|
/**
|
|
* 重置读取器
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/18 12:01
|
|
*/
|
|
public function reset(): void
|
|
{
|
|
$this->currentLine = 1;
|
|
$this->currentPosition = 0;
|
|
$this->currentLineDelta = 0;
|
|
$this->nextPosition = 0;
|
|
$this->moveToNextToken();
|
|
}
|
|
|
|
/**
|
|
* 重置读取器
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/18 12:01
|
|
*/
|
|
public function resetCursor(): void
|
|
{
|
|
$this->reset();
|
|
}
|
|
|
|
public function getCurrentPosition(): int
|
|
{
|
|
return $this->currentPosition;
|
|
}
|
|
|
|
public function getNextPosition(): int
|
|
{
|
|
return $this->nextPosition;
|
|
}
|
|
|
|
public function getCurrentLine(): int
|
|
{
|
|
return $this->currentLine;
|
|
}
|
|
|
|
public function getCurrentLinePosition(): int
|
|
{
|
|
return $this->currentPosition - $this->currentLineDelta;
|
|
}
|
|
|
|
public function getCurrentToken(): string
|
|
{
|
|
return $this->currentToken;
|
|
}
|
|
|
|
/**
|
|
* 跳过当前行
|
|
* @return bool
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/17 15:43
|
|
*/
|
|
public function skipCurrentLine(): bool
|
|
{
|
|
$_ = $this->moveCursorToNextLine();
|
|
if ($_ === false) return false;
|
|
return $this->moveToNextToken();
|
|
}
|
|
|
|
/**
|
|
* 移动Cursor至下一字符
|
|
* @param int $charLength
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/19 15:05
|
|
*/
|
|
protected function moveCursorToNextChar(int $charLength = 1): void
|
|
{
|
|
$this->currentPosition += $charLength;
|
|
}
|
|
|
|
/**
|
|
* 移动Cursor至下一行
|
|
* @param int|null $newPos 下一行位置,不提供则手动检测
|
|
* @return bool
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/19 15:05
|
|
*/
|
|
protected function moveCursorToNextLine(int $newPos = null): bool
|
|
{
|
|
if ($newPos === null) {
|
|
$curPos = $this->currentPosition;
|
|
$newPos = $this->findNextChars(["\r\n", "\r", "\n"], $curPos);
|
|
if ($newPos === null) return false;
|
|
$this->nextPosition = $newPos;
|
|
}
|
|
$this->moveCursorToNextChar($newPos - $this->currentPosition);
|
|
$this->currentLineDelta = $this->currentPosition;
|
|
$this->currentLine++;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Cursor向后移动多少字符
|
|
* @param int $length 字符长度
|
|
* @return bool 是否成功
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/19 15:13
|
|
*/
|
|
protected function moveCursorAfter(int $length): bool
|
|
{
|
|
$lastLinePos = $pos = $this->currentPosition;
|
|
$end = $pos + $length;
|
|
while ($pos < $end) {
|
|
$pos = $this->findNextChars(["\r\n", "\r", "\n"], $pos);
|
|
if ($pos === null || $pos > $end) break;
|
|
$this->moveCursorToNextLine($pos);
|
|
$lastLinePos = $pos;
|
|
}
|
|
$this->moveCursorToNextChar($end - $lastLinePos);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 移动到新的位置
|
|
* @param int $newPos
|
|
* @return bool
|
|
* @author Jerry Yan <792602257@qq.com>
|
|
* @date 2020/12/19 15:14
|
|
*/
|
|
protected function moveCursorTo(int $newPos): bool
|
|
{
|
|
// TODO: Forward Or Backward
|
|
$this->moveCursorAfter($newPos - $this->currentPosition);
|
|
return false;
|
|
}
|
|
|
|
} |