refactor: susun semula struktur folder — Laravel source ke src/

This commit is contained in:
Saufi
2026-05-19 15:58:35 +08:00
parent f052251b94
commit bf53c71b45
10806 changed files with 1385379 additions and 121 deletions

View File

@@ -0,0 +1,5 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
class Exception extends \Exception {
}

View File

@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
use function sprintf;
use function strpos;
class NamespaceUri {
/** @var string */
private $value;
public function __construct(string $value) {
$this->ensureValidUri($value);
$this->value = $value;
}
public function asString(): string {
return $this->value;
}
private function ensureValidUri($value): void {
if (strpos($value, ':') === false) {
throw new NamespaceUriException(
sprintf("Namespace URI '%s' must contain at least one colon", $value)
);
}
}
}

View File

@@ -0,0 +1,5 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
class NamespaceUriException extends Exception {
}

34
vendor/theseer/tokenizer/src/Token.php vendored Normal file
View File

@@ -0,0 +1,34 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
class Token {
/** @var int */
private $line;
/** @var string */
private $name;
/** @var string */
private $value;
/**
* Token constructor.
*/
public function __construct(int $line, string $name, string $value) {
$this->line = $line;
$this->name = $name;
$this->value = $value;
}
public function getLine(): int {
return $this->line;
}
public function getName(): string {
return $this->name;
}
public function getValue(): string {
return $this->value;
}
}

View File

@@ -0,0 +1,85 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
use ArrayAccess;
use ArrayIterator;
use Countable;
use Iterator;
use IteratorAggregate;
use function count;
use function get_class;
use function gettype;
use function is_int;
use function sprintf;
/**
* @implements IteratorAggregate<int, Token>
*/
class TokenCollection implements IteratorAggregate, ArrayAccess, Countable {
/** @var Token[] */
private $tokens = [];
public function addToken(Token $token): void {
$this->tokens[] = $token;
}
public function getIterator(): Iterator {
return new ArrayIterator($this->tokens);
}
public function count(): int {
return count($this->tokens);
}
public function offsetExists($offset): bool {
return isset($this->tokens[$offset]);
}
/**
* @throws TokenCollectionException
*/
public function offsetGet($offset): Token {
if (!$this->offsetExists($offset)) {
throw new TokenCollectionException(
sprintf('No Token at offest %s', $offset)
);
}
return $this->tokens[$offset];
}
/**
* @param Token $value
*
* @throws TokenCollectionException
*/
public function offsetSet($offset, $value): void {
if (!is_int($offset)) {
$type = gettype($offset);
throw new TokenCollectionException(
sprintf(
'Offset must be of type integer, %s given',
$type === 'object' ? get_class($value) : $type
)
);
}
if (!$value instanceof Token) {
$type = gettype($value);
throw new TokenCollectionException(
sprintf(
'Value must be of type %s, %s given',
Token::class,
$type === 'object' ? get_class($value) : $type
)
);
}
$this->tokens[$offset] = $value;
}
public function offsetUnset($offset): void {
unset($this->tokens[$offset]);
}
}

View File

@@ -0,0 +1,5 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
class TokenCollectionException extends Exception {
}

View File

@@ -0,0 +1,150 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
use PhpToken;
use function preg_split;
class Tokenizer {
/**
* Token Map for "non-tokens"
*
* @var array
*/
private const MAP = [
'(' => 'T_OPEN_BRACKET',
')' => 'T_CLOSE_BRACKET',
'[' => 'T_OPEN_SQUARE',
']' => 'T_CLOSE_SQUARE',
'{' => 'T_OPEN_CURLY',
'}' => 'T_CLOSE_CURLY',
';' => 'T_SEMICOLON',
'.' => 'T_DOT',
',' => 'T_COMMA',
'=' => 'T_EQUAL',
'<' => 'T_LT',
'>' => 'T_GT',
'+' => 'T_PLUS',
'-' => 'T_MINUS',
'*' => 'T_MULT',
'/' => 'T_DIV',
'?' => 'T_QUESTION_MARK',
'!' => 'T_EXCLAMATION_MARK',
':' => 'T_COLON',
'"' => 'T_DOUBLE_QUOTES',
'@' => 'T_AT',
'%' => 'T_PERCENT',
'|' => 'T_PIPE',
'$' => 'T_DOLLAR',
'^' => 'T_CARET',
'~' => 'T_TILDE',
'`' => 'T_BACKTICK'
];
public function parse(string $source): TokenCollection {
$result = new TokenCollection();
if ($source === '') {
return $result;
}
$tokens = PhpToken::tokenize($source);
$lastToken = new Token(
$tokens[0]->line,
'Placeholder',
''
);
foreach ($tokens as $tok) {
if (isset(self::MAP[$tok->text])) {
$token = new Token(
$lastToken->getLine(),
self::MAP[$tok->text],
$tok->text,
);
$result->addToken($token);
$lastToken = $token;
continue;
}
$line = $tok->line;
$values = preg_split('/\R+/Uu', $tok->text);
if (!$values) {
$result->addToken(
new Token(
$line,
$tok->getTokenName(),
'{binary data}'
)
);
continue;
}
foreach ($values as $v) {
$token = new Token(
$line,
$tok->getTokenName(),
$v
);
$lastToken = $token;
$line++;
if ($v === '') {
continue;
}
$result->addToken($token);
}
}
return $this->fillBlanks($result, $lastToken->getLine());
}
private function fillBlanks(TokenCollection $tokens, int $maxLine): TokenCollection {
$prev = new Token(
0,
'Placeholder',
''
);
$final = new TokenCollection();
$prevLine = $prev->getLine();
foreach ($tokens as $token) {
$line = $token->getLine();
$gap = $line - $prevLine;
while ($gap > 1) {
$linebreak = new Token(
$prevLine + 1,
'T_WHITESPACE',
''
);
$final->addToken($linebreak);
$prevLine = $linebreak->getLine();
$gap--;
}
$final->addToken($token);
$prevLine = $line;
}
$gap = $maxLine - $prevLine;
while ($gap > 0) {
$linebreak = new Token(
$prevLine + 1,
'T_WHITESPACE',
''
);
$final->addToken($linebreak);
$prevLine = $linebreak->getLine();
$gap--;
}
return $final;
}
}

View File

@@ -0,0 +1,83 @@
<?php declare(strict_types = 1);
namespace TheSeer\Tokenizer;
use DOMDocument;
use XMLWriter;
use function count;
use const ENT_DISALLOWED;
use const ENT_NOQUOTES;
use const ENT_XML1;
class XMLSerializer {
/** @var NamespaceUri */
private $xmlns;
/**
* XMLSerializer constructor.
*/
public function __construct(?NamespaceUri $xmlns = null) {
if ($xmlns === null) {
$xmlns = new NamespaceUri('https://github.com/theseer/tokenizer');
}
$this->xmlns = $xmlns;
}
public function toDom(TokenCollection $tokens): DOMDocument {
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->loadXML($this->toXML($tokens));
return $dom;
}
public function toXML(TokenCollection $tokens): string {
$writer = new XMLWriter();
$writer->openMemory();
$writer->setIndent(true);
$writer->startDocument();
$this->appendToWriter($writer, $tokens);
$writer->endDocument();
return $writer->outputMemory();
}
public function appendToWriter(XMLWriter $writer, TokenCollection $tokens): void {
$writer->startElement('source');
$writer->writeAttribute('xmlns', $this->xmlns->asString());
if (count($tokens) > 0) {
$writer->startElement('line');
$writer->writeAttribute('no', '1');
$iterator = $tokens->getIterator();
$previousToken = $iterator->current();
$previousLine = $previousToken->getLine();
foreach ($iterator as $token) {
$line = $token->getLine();
if ($previousLine < $line) {
$writer->endElement();
$writer->startElement('line');
$writer->writeAttribute('no', (string)$line);
$previousLine = $line;
}
$value = $token->getValue();
if ($value !== '') {
$writer->startElement('token');
$writer->writeAttribute('name', $token->getName());
$writer->writeRaw(htmlspecialchars($value, ENT_NOQUOTES | ENT_DISALLOWED | ENT_XML1));
$writer->endElement();
}
}
$writer->endElement();
}
$writer->endElement();
}
}