refactor: Cleanup git state - commit all staged changes

Major refactoring cleanup:
- Add new controller architecture (class-controller-*.php)
- Add new settings-v2 UI (views/settings-v2/)
- Add new CSS architecture (agentic-sidebar.css, tokens)
- Add esbuild build pipeline (scripts/build.js, package.json)
- Add composer dependencies (vendor/)
- Add frontend src directory (assets/js/src/index.jsx)
- Add documentation files
- Remove old/obsolete files (class-settings.php, old CSS)

This commits all pending changes from previous refactoring efforts.
This commit is contained in:
Dwindi Ramadhana
2026-06-17 05:27:58 +07:00
parent d3f142222c
commit 690991c526
7963 changed files with 941566 additions and 67372 deletions

View File

@@ -0,0 +1,865 @@
<?php
/**
*
* @Name : JsonParser
* @Version : 2.2.1
* @Programmer : Max
* @Date : 2018-06-26, 2018-06-27, 2019-03-23, 2019-03-24, 2019-03-26, 2019-03-27, 2019-04-04
* @Released under : https://github.com/BaseMax/JsonParser/blob/master/LICENSE
* @Repository : https://github.com/BaseMax/JsonParser
*
**/
namespace JPOPHP;
abstract class JsonType
{
// []
const JsonArray = 0;
// {}
const JsonObject = 1;
}
abstract class TokenType
{
// end of file, end of command, end of input string
const TokenEOF = -1;
// {
const TokenArrayOpen = 0;
// }
const TokenArrayClose = 1;
// [
const TokenObjectOpen = 2;
// ]
const TokenObjectClose = 3;
// "...", '...'
const TokenString = 4;
// <int>, <float>, -<int>, -<float>, ...
const TokenNumber = 5;
// ,
const TokenSplit = 6;
// :
const TokenPair = 7;
// null
const TokenNull = 8;
// true, false
const TokenBool = 9;
}
class Json
{
/**
*
* Public variable for whole of the class
*
*/
// token type of current state in decode()
public $token = null;
// length and last index of the input, it update using decode()
public int $length = 0;
// input string, it updates using decode()
public string $input = "";
// current state and index of pointer at the input string
public int $index = 0;
/**
* @function typeToken($token)
* argument: $token
* return : @string
*/
function typeToken($token)
{
switch ($token[0]) {
// EOF
case TokenType::TokenEOF:
return "EOF";
break;
// [
case TokenType::TokenArrayOpen:
return "ArrayOpen";
break;
// ]
case TokenType::TokenArrayClose:
return "ArrayClose";
break;
// {
case TokenType::TokenObjectOpen:
return "ObjectOpen";
break;
// }
case TokenType::TokenObjectClose:
return "ObjectClose";
break;
// "...", '...'
case TokenType::TokenString:
return "String";
break;
// number
case TokenType::TokenNumber:
return "Number";
break;
// ,
case TokenType::TokenSplit:
return "Split";
break;
// :
case TokenType::TokenPair:
return "Pair";
break;
// unknowm, other!
default:
return "None";
break;
}
}
/**
* @function isAssociative($array)
* argument: array $array
* return : @bool
*/
/*
* Arrays are :
* associative or sequential
*/
function isAssociative(array $array)
{
// if(array() === $array)
// return false;
return array_keys($array) !== range(0, count($array) - 1);
}
// function encodeValue($value) {
// if($value === true || $value === false) {//bool
// return $value;
// }
// else if($value === null) {//null
// return $value;
// }
// else if(is_numeric($value) === true) {//number
// return $value;
// }
// else if(is_string($value) === true) {//string
// return "\"".$value."\"";
// }
// else if(is_array($value) === true) {//array
// return encode($value);
// }
// else {
// return false;
// }
// }
/**
* @function encode($array)
* argument: array $array
* return : @string
*/
function encode($array)
{
$response = "";
if ([] !== $array) {
$array_type = $this->isAssociative($array) ? "associative" : "sequential";
if ($array_type == "associative") {//object
$response .= "{";
} else {
$response .= "[";
}
$count = count($array);
$index = 0;
foreach ($array as $key => $value) {
if ($array_type == "associative") {//object
$response .= "\"";
$response .= $key;
$response .= "\"";
$response .= ":";
}
if ($value === true || $value === false) {//bool
$response .= $value;
} elseif ($value === null) {//null
$response .= $value;
} elseif (is_numeric($value) === true) {//number
$response .= $value;
} elseif (is_string($value) === true) {//string
$response .= "\"" . $value . "\"";
} elseif (is_array($value) === true) {//array
$response .= $this->encode($value);
} else {
print "Error: Unknowm type!\n";
break;
}
// if(is_array($value)) {
// $response.=this->encode($value);
// }
// else {
// $response.=encodeValue($value);
// }
if (++$index !== $count) {
$response .= ",";
}
}
if ($array_type == "associative") {//object
$response .= "}";
} else {
$response .= "]";
}
}
// $response.="\n";
return $response;
}
// function nextsIfWithSkips($characterIf,$token,$tok)
// function nextsIfWithSkip($characterIf,$token,$tok)
// function nextIfWithSkips($characterIf,$token,$tok)
// function nextIfWithSkip($characterIf,$token,$tok)
/**
* @function nextsIf($characterIf)
* argument: char $characterIf
* return : @void
*/
function nextsIf($characterIf)
{
$character = $this->input[$this->index];
if (is_array($characterIf)) {
while (in_array($character, $characterIf)) {
if ($this->index + 1 === $this->length) {
break;
}
$this->index++;
$character = $this->input[$this->index];
}
} else {
while ($character == $characterIf) {
if ($this->index + 1 === $this->length) {
break;
}
$this->index++;
$character = $this->input[$this->index];
}
}
}
/**
* @function nextIf($characterIf)
* argument: char $characterIf
* return : @void
*/
function nextIf($characterIf)
{
$character = $this->input[$this->index];
if (is_array($characterIf)) {
if (in_array($character, $characterIf)) {
if ($this->index + 1 === $this->length) {
return;
// break;
}
$this->index++;
// $character=$this->input[$this->index];
}
} else {
if ($character == $characterIf) {
if ($this->index + 1 === $this->length) {
return;
// break;
}
$this->index++;
// $character=$this->input[$this->index];
}
}
}
/**
* @function nextsIf($token,tok)
* argument: token $token, tokentype $tok
* return : @token
*/
function skip($token, $tok)
{
// print "---start\n";
if ($token[0] === $tok) {
$token = $this->nextToken();
// print "---next\n";
}
// print "---finish\n";
return $token;
}
/**
* @function skips($token,tok)
* argument: token $token, tokentype $tok
* return : @token
*/
function skips($token, $tok)
{
// print "---start\n";
while ($token[0] === $tok) {
$token = $this->nextToken();
// print "---next\n";
}
// print "---finish\n";
return $token;
}
/**
* @function nextToken()
* argument: void
* return : @token
*/
function nextToken()
{
if ($this->index + 1 > $this->length) {
return [TokenType::TokenEOF, null];
}
$character = $this->input[$this->index];
while ($character == ' ' || $character == ' ' || $character == "\n") {
if ($this->index + 1 === $this->length) {
break;
}
$this->index++;
$character = $this->input[$this->index];
}
if ($character == '{') {
$this->index++;
return [TokenType::TokenObjectOpen, null];
} elseif ($character == '}') {
$this->index++;
return [TokenType::TokenObjectClose, null];
} elseif ($character == '[') {
$this->index++;
return [TokenType::TokenArrayOpen, null];
} elseif ($character == ']') {
$this->index++;
return [TokenType::TokenArrayClose, null];
} elseif ($character == ',') {
$this->index++;
return [TokenType::TokenSplit, null];
} elseif ($character == ':') {
$this->index++;
return [TokenType::TokenPair, null];
} // n, N
elseif ($character === 'n' || $character === 'N') {
$i = 0;
$i++;
$character = $this->input[$this->index + $i];
// u, U
if ($character === 'u' || $character === 'U') {
$i++;
$character = $this->input[$this->index + $i];
// l, L
if ($character === 'l' || $character === 'L') {
$i++;
$character = $this->input[$this->index + $i];
// l, L
if ($character === 'l' || $character === 'L') {
$this->index++;
$this->index++;
$this->index++;
$this->index++;
return [TokenType::TokenNull, null];
}
}
}
} // t, T
elseif ($character === 't' || $character === 'T') {
$i = 0;
$i++;
$character = $this->input[$this->index + $i];
// r, R
if ($character === 'r' || $character === 'R') {
$i++;
$character = $this->input[$this->index + $i];
// u, U
if ($character === 'u' || $character === 'U') {
$i++;
$character = $this->input[$this->index + $i];
// e, E
if ($character === 'e' || $character === 'E') {
$this->index++;
$this->index++;
$this->index++;
$this->index++;
return [TokenType::TokenBool, true];
}
}
}
} // f, F
elseif ($character === 'f' || $character === 'F') {
$i = 0;
$i++;
$character = $this->input[$this->index + $i];
// a, A
if ($character === 'a' || $character === 'A') {
$i++;
$character = $this->input[$this->index + $i];
// l, L
if ($character === 'l' || $character === 'L') {
$i++;
$character = $this->input[$this->index + $i];
// s, S
if ($character === 's' || $character === 'S') {
$i++;
$character = $this->input[$this->index + $i];
// e, E
if ($character === 'e' || $character === 'E') {
$this->index++;
$this->index++;
$this->index++;
$this->index++;
$this->index++;
return [TokenType::TokenBool, false];
}
}
}
}
} elseif ($character === '"' || $character === '\'') {
$stype = null;
if ($character === '"') {
$stype = 1;
} elseif ($character === '\'') {
$stype = 2;
}
$result = "";
$characterPrev = "";
$this->index++;
$character = $this->input[$this->index];
$characterNext = null;
while (
($stype === 1 && $characterNext !== '"') ||
($stype === 2 && $characterNext !== '\'')
) {
if ($this->index == $this->length) {
break;
}
$character = $this->input[$this->index];
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
// It added by me, not in the standard JSON!
if ($character === '\\' && $characterNext === '\'') {
$this->index++;
// $this->index++;
$character = $characterNext;
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} /**
*
* @Name : Unicode Support
* @Description : This feature is requested by Frederick Behrends.
* @Url, @Issue : https://github.com/BaseMax/JsonParser/issues/1
*/
elseif ($character === '\\' && $characterNext === 'u') {
$unicode = '';
$this->index++;
$this->index++;
$perform = true;
$i = 1; // We require it after the loop!
for (; $i <= 4; $i++) {
// print "...\n";
// if($perform === false) {
// break;
// }
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index]; // As temp variable
$perform = true;
if (
$characterNext >= '0' && $characterNext <= '9' ||
$characterNext >= 'A' && $characterNext <= 'F'
) {
$character = $characterNext;// It will use when loop break! ($perform=false)
$unicode .= $character;
$this->index++;
} else { // May be " character!
// print "A stage\n";
// print $unicode."\n";
// print $character."\n";
$perform = false;
break;
}
} else {
// print "B stage\n";
$perform = false;
break;
}
}
if ($perform === true) {
$this->index--; // Required...
// print "C Stage\n";
// print $unicode."\n";
$unicode = "%u" . $unicode;
# $unicode = preg_replace('/%u([0-9A-F]){4}/', '&#x$1;', $unicode);
$unicode = preg_replace('/%u([0-9A-F]+)/', '&#x$1;', $unicode);
// ENT_COMPAT : Will convert double-quotes and leave single-quotes alone.
// https://www.php.net/manual/en/function.htmlentities.php
// print $unicode."\n";
$character = html_entity_decode($unicode, ENT_COMPAT, 'UTF-8');
// print $character."\n";
} else {
// Last index is $i
// We ($i-1) time rub the $index++
// print $i."\n";
// for($ii=1;$ii<$i-1;$ii++) {
// $this->index--;
// }
$this->index--;
$character = "\\u" . $unicode;
}
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} elseif ($character === '\\' && $characterNext === 'n') {
$this->index++;
// $this->index++;
$character = "\n";
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} elseif ($character === '\\' && $characterNext === '\\') {
$this->index++;
// $this->index++;
$character = "\\";
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} elseif ($character === '\\' && $characterNext === '/') {
$this->index++;
// $this->index++;
$character = "/";
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} elseif ($character === '\\' && $characterNext === 't') {
$this->index++;
// $this->index++;
$character = "\t";
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} elseif ($character === '\\' && $characterNext === 'r') {
$this->index++;
// $this->index++;
$character = "\r";
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} elseif ($character === '\\' && $characterNext === 'b') {
$this->index++;
// $this->index++;
$character = "\b";
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
} elseif ($character === '\\' && $characterNext === '"') {
$this->index++;
// $this->index++;
$character = $characterNext;
// Fix: "hi\"!"
if ($this->index + 1 < $this->length) {
$characterNext = $this->input[$this->index + 1];
} else {
$characterNext = null;
}
}
// else {
// $this->index++;
// }
// else if($character == '"') {
// // $this->index--;
// // $this->index--;
// // $character='"';
// break;
// continue;
// }
$result .= $character;
$this->index++;
}
$this->index++;
return [TokenType::TokenString, $result];
}
// <int>(0 .. 9), -, .
// Allow : .9, .04
// Allow : -5
// Allow : -5.048
elseif (($character >= '0' && $character <= '9') || $character == '-' || $character == '.') {
$result = 0;
$bitflag = false;
$bitfloat = false;
$bitfloatindex = 0;
// while($character >='0' && $character <='9') {
while (
($character >= '0' && $character <= '9') ||
$character == '-' ||
$character == '.'
) {
if ($this->index == $this->length) {
break;
}
// $result*=10+(int)$character;
if ($bitflag === false && $character === '-') {
$bitflag = true;
} elseif ($bitflag === true && $character === '-') {
// Error
exit("Aleady expression has a minus!\n");
} else {
if ($bitfloat === false && $character == '.') {
$bitfloat = true;
// $bitfloatindex=0;
} elseif ($bitflag === true && $character == '.') {
// Error
exit("Aleady expression was a float type!\n");
} // else if($bitflag === true && ($character == 'e' || $character == 'E')) {
elseif ($character == 'e' || $character == 'E') {
//soon
exit("Soon, E+5 likely expression will develope....!\n");
} elseif ($bitfloat === true) {
$bitfloatindex++;
$floatcurrent = pow(10, $bitfloatindex);
$result = $result + ((int)$character / $floatcurrent);
} // else if($bitfloat === false) {
else {
$result = $result * 10;
$result = $result + (int)$character;
}
}
$this->index++;
if ($this->index + 1 < $this->length) {
$character = $this->input[$this->index];
} else {
$character = null;
}
}
if ($bitflag === true) {
$result *= -1;
}
// $this->index++;
return [TokenType::TokenNumber, $result];
} else {
$this->index++;
}
return [TokenType::TokenEOF, null];
}
/**
* @function isValue(token)
* argument: token $token
* return : array[bool $status, string $result]
*/
function isValue($token)
{
/**
* Values:
* <int>, <float>, - <int>, - <float>, -<int>(e|E)(+|-)<int>, <int>(e|E)(+|-)<int>, -<float>(e|E)(+|-)<int>, <float>(e|E)(+|-)<int>
*
* <bool> (true, false)
*
* <null> (null)
*
* <string> ("...", '...')
*
* <object> {...}
*
* <array> [...]
*/
if ($token[0] === TokenType::TokenNumber) {
return [true, $token[1]];
// return [true,null];
// return true;
} elseif ($token[0] === TokenType::TokenString) {
return [true, $token[1]];
// return [true,null];
// return true;
} elseif ($token[0] === TokenType::TokenBool) {
return [true, $token[1]];
} elseif ($token[0] === TokenType::TokenNull) {
return [true, null];
} elseif ($token[0] === TokenType::TokenObjectOpen) {
// $tree=0;
// $result=[];
$this->index--;
// print "...\n";
$result = $this->decode(null, false);
// while($token[0] != TokenType::TokenObjectClose) {
// }
// print_r($result);
return [true, $result];
// return true;
} elseif ($token[0] === TokenType::TokenArrayOpen) {
// $tree=0;
// $result=[];
$this->index--;
// print "...\n";
// print $this->input."\n";
// print $this->index."\n";
// print $this->input[$this->index]."\n";
$result = $this->decode(null, false);
// while($token[0] != TokenType::TokenObjectClose) {
//
// }
return [true, $result];
// return true;
}
return [false, null];
// return false;
}
/**
* @function decode(input,init=true)
* argument: string $input, bool init
* return : array[...]
*/
function decode($input, $init = true)
{
if ($init === true) {
// $this->tree=[];
// $this->trees=[];
$this->index = 0;
$this->input = $input;
$this->length = mb_strlen($input);
// $this->tree=null;
} else {
// $this->tree=0;
}
$result = [];
$this->token = $this->nextToken();
// print_r($token);
// $arrayOpen=false;
// $objectOpen=false;
// // skip spaces
// $this->nextsIf([" ","\n"," "]);
if (
$this->token[0] === TokenType::TokenArrayOpen ||
$this->token[0] === TokenType::TokenObjectOpen
) {
$type = null;
if ($this->token[0] === TokenType::TokenArrayOpen) {
$type = JsonType::JsonArray;
} elseif ($this->token[0] === TokenType::TokenObjectOpen) {
$type = JsonType::JsonObject;
}
// $this->tree[]=$this->token[0];
$this->token = $this->nextToken();
// // skip spaces
// $this->nextsIf([" ","\n"," "]);
// // skip split
// $this->skips($token,TokenType::TokenSplit);
// // skip spaces
// $this->nextsIf([" ","\n"," "]);
// // skip space(s) and split(s)
// $this->nextsIfWithSkips([" ","\n"," "],$token,TokenType::TokenSplit);
// skip split
// print_r($token);
$this->token = $this->skips($this->token, TokenType::TokenSplit);
// print_r($token);
// exit;
// parse until arrayClose
while (
($type === JsonType::JsonArray && $this->token[0] !== TokenType::TokenArrayClose) ||
($type === JsonType::JsonObject && $this->token[0] !== TokenType::TokenObjectClose)
) {
// print "==>".$this->typeToken($this->token) ."\n";
if ($this->token[0] === TokenType::TokenEOF) {
exit("Command is finish, but arrayClose not found!\n");
}
$first = null;
$second = null;
$first = $this->isValue($this->token);
if ($first[0] === true) {
// print "----yes\n";
// $first=$token;
// $first=$this->token;
// next may be was pair or split or arrayClose or EOF!
$this->token = $this->nextToken();
// print "\t==>".$this->typeToken($token) ."\n";
if ($type === JsonType::JsonObject) {
if ($this->token[0] === TokenType::TokenPair) {
if (is_string($first[1]) === true) {
$this->token = $this->nextToken();
// $second=$this->token;
$second = $this->isValue($this->token);
if ($second[0] === true) {
$this->token = $this->nextToken();
} else {
// Error!
exit("Unknowm token, pair value is not a value!\n");
}
} else {
// Error!
exit("Unknowm token, key of pair value is not a string!\n");
}
} else {
// Error!
exit("Unknowm token, all item of object should was a pair value!\n");
}
}
// its a array JSON
if ($second === null) {
/**
* result[index]
* =
* <value> (first)
*/
$result[] = $first[1];
} // its a object JSON
else {
/**
* result[
* <value> (first)
* ]
* =
* <value> (second)
*/
$result[$first[1]] = $second[1];
}
// print_r($result);
$this->token = $this->skips($this->token, TokenType::TokenSplit);
// $this->skips($token,TokenType::TokenSplit);
} else {
// print "----no\n";
// print_r($token);
// print $this->input."\n";
// print $this->index."\n";
// print $this->input[$this->index]."\n";
$this->token = $this->nextToken();
// print_r($token);
}
// print "\t==>".$this->typeToken($token) ."\n";
// print_r($token);
}
}
// else if($this->token[0] === TokenType::TokenObjectOpen) {
// // $this->tree[]=$this->token[0];
// }
elseif ($this->token[0] === TokenType::TokenEOF) {
// ;
// return;
// exit;
} else {
// Error!
exit("Unknowm token at the begin of command!\n");
}
// print_r($result);
return $result;
}
}

View File

@@ -0,0 +1 @@
This JSON parser was copied from https://github.com/BaseMax/JPOPHP for comparison against Parsica's JSON parser.

View File

@@ -0,0 +1,85 @@
<?php declare(strict_types=1);
/**
* This file is part of the Parsica library.
*
* Copyright (c) 2020 Mathias Verraes <mathias@verraes.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Parsica\Parsica\JSON\JSON as ParsicaJSON;
use Json as BaseMaxJson;
class JSONBench
{
private string $data;
function __construct()
{
$this->data = <<<JSON
{
"name": "mathiasverraes/parsica",
"type": "library",
"alotoftext": [
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet",
"Lorem Ipsum dolor sit amet"
],
"alotmoretext": "Fuga iusto dolores ipsam. Qui excepturi veniam iste autem ducimus porro et voluptas. Veniam veniam ducimus cumque facere repudiandae corrupti sint quas. Cupiditate asperiores iure omnis dolores nihil asperiores qui quo. Assumenda quia iure deserunt deserunt. Perspiciatis velit quia et.\n\nExplicabo non dolores aut facere. Perferendis in est voluptate. Et laboriosam et autem voluptatum rem nam et aut. Voluptatem praesentium et earum fugit accusamus tempore consectetur natus. Beatae sunt nisi rerum blanditiis consequatur rerum ut.\n\nIure ipsa sit assumenda. Vitae nisi qui vero. Eveniet cum aliquam molestiae molestias. Nisi aut ea alias quo ea voluptatem. Minus ea mollitia quis.",
"description": "The easiest way to build robust parsers in PHP.",
"keywords": [
"parser",
"parser-combinator",
"parser combinator",
"parsing"
]
}
JSON;
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_json_encode()
{
json_decode($this->data);
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_Parsica_JSON()
{
$result = ParsicaJSON::json()->tryString($this->data);
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_basemax_jpophp()
{
require_once(__DIR__.'/JPOPHP/JsonParser.php');
(new JPOPHP\Json())->decode($this->data);
}
}

View File

@@ -0,0 +1,96 @@
<?php declare(strict_types=1);
/**
* This file is part of the Parsica library.
*
* Copyright (c) 2020 Mathias Verraes <mathias@verraes.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Parsica\Parsica\Parser;
use function Parsica\Parsica\any;
use function Parsica\Parsica\char;
use function Parsica\Parsica\collect;
use function Parsica\Parsica\many;
use function Parsica\Parsica\map;
use function Parsica\Parsica\pure;
use function Parsica\Parsica\recursive;
use function Parsica\Parsica\satisfy;
use function Parsica\Parsica\takeWhile;
class ManyBench
{
private string $data;
function __construct()
{
$this->data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
$this->takeWhile = takeWhile(fn(string $c): bool => $c === 'a');
$this->manySatisfy = many(satisfy(fn(string $c): bool => $c === 'a'));
$this->manyChar = many(char('a'));
$this->oldManySatisfy = static::oldMany(satisfy(fn(string $c): bool => $c === 'a'));
$this->oldManyChar = static::oldMany(char('a'));
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_takeWhile()
{
$result = $this->takeWhile->tryString($this->data);
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_manySatisfy()
{
$result = $this->manySatisfy->tryString($this->data);
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_manyChar()
{
$result = $this->manyChar->tryString($this->data);
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_oldManySatisfy()
{
$result = $this->oldManySatisfy->tryString($this->data);
}
/**
* @Revs(10)
* @Iterations(10)
*/
public function bench_oldManyChar()
{
$result = $this->oldManyChar->tryString($this->data);
}
public static function oldMany(Parser $parser)
{
$rec = recursive();
$rec->recurse(
any(
map(
collect($parser, $rec),
fn(array $o): array => array_merge([$o[0]], $o[1])
),
pure([]),
)
);
return $rec;
}
}