* @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; } }