diff --git a/.github/workflows/phpqa.yml b/.github/workflows/phpqa.yml
index 661b9e4..f28a069 100644
--- a/.github/workflows/phpqa.yml
+++ b/.github/workflows/phpqa.yml
@@ -8,14 +8,14 @@ jobs:
steps:
- uses: actions/checkout@master
- name: PHPStan
- uses: docker://jakzal/phpqa:php8.0-alpine
+ uses: docker://jakzal/phpqa:php8.4
with:
args: phpstan analyze src/ -l 1
- name: PHP-CS-Fixer
- uses: docker://jakzal/phpqa:php8.0-alpine
+ uses: docker://jakzal/phpqa:php8.4
with:
args: php-cs-fixer --dry-run --allow-risky=yes --no-interaction --ansi fix
- name: Deptrac
- uses: docker://jakzal/phpqa:php8.0-alpine
+ uses: docker://jakzal/phpqa:php8.4
with:
args: deptrac --no-interaction --ansi --formatter-graphviz-display=0
diff --git a/.gitignore b/.gitignore
index 35f8f3f..3e04865 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@
/coverage.clover
/.phpunit.result.cache
/vendor/
+/.idea
+/.composer
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
index 37f56a0..64e37a8 100644
--- a/.scrutinizer.yml
+++ b/.scrutinizer.yml
@@ -35,8 +35,9 @@ tools:
enabled: true
excluded_dirs: [tests]
build:
+ image: default-bionic
environment:
- php: 8.0.1
+ php: 8.4.0
nodes:
analysis:
tests:
diff --git a/.styleci.yml b/.styleci.yml
index 03b0848..93c2ae9 100644
--- a/.styleci.yml
+++ b/.styleci.yml
@@ -1,10 +1,12 @@
---
preset: psr2
risky: true
-version: 8
+version: 8.4
finder:
name:
- "*.php"
enabled:
- short_array_syntax
- cast_spaces
+disabled:
+ - lowercase_constants
diff --git a/.travis.yml b/.travis.yml
index fa2e489..5161ca6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
language: php
php:
- - 8.0
+ - 8.4
script:
- composer install --dev
diff --git a/README.md b/README.md
index a656d84..ad7afe6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
## PHP Rule Engine
-
[](https://travis-ci.org/nicoSWD/php-rule-parser)
[![Build status][Master coverage image]][Master coverage]
[![Code Quality][Master quality image]][Master quality]
@@ -13,13 +12,10 @@ You're looking at a standalone PHP library to parse and evaluate text based rule
This library has initially been used to change and configure the behavior of certain "Workflows" (without changing actual code) in an intranet application, but it may serve a purpose elsewhere.
-
Find me on Twitter: @[nicoSWD](https://twitter.com/nicoSWD)
(If you're using PHP 5, you might want to take a look at [version 0.4.0](https://github.com/nicoSWD/php-rule-parser/tree/0.4.0))
-[](https://insight.sensiolabs.com/projects/67203389-970c-419c-9430-a7f9a005bd94)
-
## Install
Via Composer
@@ -40,23 +36,29 @@ This library works best with one of these bundles below, but they're not require
Test if a value is in a given array
```php
-$variables = ['foo' => 6];
+$variables = [
+ 'coupon_code' => (string) $_POST['coupon_code'],
+];
-$rule = new Rule('foo in [4, 6, 7]', $variables);
+$rule = new Rule('coupon_code in ["summer_discount", "summer21"]', $variables);
var_dump($rule->isTrue()); // bool(true)
```
-Simple array manipulation
+Performing a regular expression
```php
-$rule = new Rule('[1, 4, 3].join(".") === "1.4.3"');
+$variables = [
+ 'coupon_code' => (string) $_POST['coupon_code'],
+];
+
+$rule = new Rule('coupon_code.test(/^summer20[0-9]{2}$/) == true', $variables);
var_dump($rule->isTrue()); // bool(true)
```
Test if a value is between a given range
```php
-$variables = ['threshold' => 80];
+$variables = ['points' => 80];
-$rule = new Rule('threshold >= 50 && threshold <= 100', $variables);
+$rule = new Rule('points >= 50 && points <= 100', $variables);
var_dump($rule->isTrue()); // bool(true)
```
@@ -64,8 +66,6 @@ Call methods on objects from within rules
```php
class User
{
- // ...
-
public function points(): int
{
return 1337;
@@ -180,7 +180,7 @@ $highlighter = new Rule\Highlighter\Highlighter(new Rule\Tokenizer());
// Optional custom styles
$highlighter->setStyle(
- Rule\Constants::GROUP_VARIABLE,
+ TokenType::VARIABLE,
'color: #007694; font-weight: 900;'
);
diff --git a/composer.json b/composer.json
index eabf79b..bbcab55 100644
--- a/composer.json
+++ b/composer.json
@@ -19,7 +19,7 @@
{
"name": "Nicolas Oelgart",
"role": "Developer",
- "homepage": "https://nicoswd.com"
+ "homepage": "https://nico.es"
}
],
"autoload": {
@@ -33,11 +33,11 @@
}
},
"require": {
- "php": ">=8.0"
+ "php": ">=8.4"
},
"require-dev": {
- "phpunit/phpunit": "^7.0|^9.0",
- "mockery/mockery": "^1.0|^1.4"
+ "phpunit/phpunit": "^12.3",
+ "mockery/mockery": "^1.6"
},
"scripts": {
"test": "vendor/bin/phpunit"
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index db6f484..82d373f 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,15 +1,16 @@
-
-
- src
-
-
+ xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/12.3/phpunit.xsd"
+ bootstrap="src/autoload.php"
+ cacheDirectory=".phpunit.cache">
tests/
+
+
+ src
+
+
diff --git a/src/Compiler/CompilerFactory.php b/src/Compiler/CompilerFactory.php
index c4fea98..0be47bc 100644
--- a/src/Compiler/CompilerFactory.php
+++ b/src/Compiler/CompilerFactory.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Compiler;
diff --git a/src/Compiler/CompilerFactoryInterface.php b/src/Compiler/CompilerFactoryInterface.php
index 1e42aec..69a2ed6 100644
--- a/src/Compiler/CompilerFactoryInterface.php
+++ b/src/Compiler/CompilerFactoryInterface.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Compiler;
diff --git a/src/Compiler/CompilerInterface.php b/src/Compiler/CompilerInterface.php
index 90a2121..832cce6 100644
--- a/src/Compiler/CompilerInterface.php
+++ b/src/Compiler/CompilerInterface.php
@@ -3,19 +3,21 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Compiler;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
+use nicoSWD\Rule\TokenStream\Token\Type\Logical;
+use nicoSWD\Rule\TokenStream\Token\Type\Parenthesis;
interface CompilerInterface
{
public function getCompiledRule(): string;
- public function addParentheses(BaseToken $token): void;
+ public function addParentheses(BaseToken & Parenthesis $token): void;
- public function addLogical(BaseToken $token): void;
+ public function addLogical(BaseToken & Logical $token): void;
public function addBoolean(bool $bool): void;
}
diff --git a/src/Compiler/Exception/MissingOperatorException.php b/src/Compiler/Exception/MissingOperatorException.php
index ba6d049..e551ffd 100644
--- a/src/Compiler/Exception/MissingOperatorException.php
+++ b/src/Compiler/Exception/MissingOperatorException.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Compiler\Exception;
diff --git a/src/Compiler/StandardCompiler.php b/src/Compiler/StandardCompiler.php
index 2d1d7f4..4006d39 100644
--- a/src/Compiler/StandardCompiler.php
+++ b/src/Compiler/StandardCompiler.php
@@ -3,26 +3,24 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Compiler;
use nicoSWD\Rule\Compiler\Exception\MissingOperatorException;
+use nicoSWD\Rule\Evaluator\Boolean;
+use nicoSWD\Rule\Evaluator\Operator;
use nicoSWD\Rule\Parser\Exception\ParserException;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
use nicoSWD\Rule\TokenStream\Token\TokenAnd;
use nicoSWD\Rule\TokenStream\Token\TokenOpeningParenthesis;
+use nicoSWD\Rule\TokenStream\Token\Type\Logical;
+use nicoSWD\Rule\TokenStream\Token\Type\Parenthesis;
-class StandardCompiler implements CompilerInterface
+final class StandardCompiler implements CompilerInterface
{
- private const BOOL_TRUE = '1';
- private const BOOL_FALSE = '0';
-
- private const LOGICAL_AND = '&';
- private const LOGICAL_OR = '|';
-
- private const OPENING_PARENTHESIS = '(';
- private const CLOSING_PARENTHESIS = ')';
+ private const string OPENING_PARENTHESIS = '(';
+ private const string CLOSING_PARENTHESIS = ')';
private string $output = '';
private int $openParenthesis = 0;
@@ -58,7 +56,7 @@ private function closeParenthesis(): void
}
/** @throws ParserException */
- public function addParentheses(BaseToken $token): void
+ public function addParentheses(BaseToken & Parenthesis $token): void
{
if ($token instanceof TokenOpeningParenthesis) {
if (!$this->expectOpeningParenthesis()) {
@@ -71,31 +69,27 @@ public function addParentheses(BaseToken $token): void
}
/** @throws ParserException */
- public function addLogical(BaseToken $token): void
+ public function addLogical(BaseToken & Logical $token): void
{
- $lastChar = $this->getLastChar();
-
- if ($lastChar === self::LOGICAL_AND || $lastChar === self::LOGICAL_OR) {
+ if (Operator::tryFrom($this->getLastChar()) !== null) {
throw ParserException::unexpectedToken($token);
}
if ($token instanceof TokenAnd) {
- $this->output .= self::LOGICAL_AND;
+ $this->output .= Operator::LOGICAL_AND->value;
} else {
- $this->output .= self::LOGICAL_OR;
+ $this->output .= Operator::LOGICAL_OR->value;
}
}
/** @throws MissingOperatorException */
public function addBoolean(bool $bool): void
{
- $lastChar = $this->getLastChar();
-
- if ($lastChar === self::BOOL_TRUE || $lastChar === self::BOOL_FALSE) {
+ if (Boolean::tryFrom($this->getLastChar()) !== null) {
throw new MissingOperatorException();
}
- $this->output .= $bool ? self::BOOL_TRUE : self::BOOL_FALSE;
+ $this->output .= Boolean::fromBool($bool)->value;
}
private function numParenthesesMatch(): bool
@@ -105,11 +99,7 @@ private function numParenthesesMatch(): bool
private function isIncompleteCondition(): bool
{
- $lastChar = $this->getLastChar();
-
- return
- $lastChar === self::LOGICAL_AND ||
- $lastChar === self::LOGICAL_OR;
+ return Operator::tryFrom($this->getLastChar()) !== null;
}
private function expectOpeningParenthesis(): bool
@@ -118,9 +108,8 @@ private function expectOpeningParenthesis(): bool
return
$lastChar === '' ||
- $lastChar === self::LOGICAL_AND ||
- $lastChar === self::LOGICAL_OR ||
- $lastChar === self::OPENING_PARENTHESIS;
+ $lastChar === self::OPENING_PARENTHESIS ||
+ Operator::tryFrom($lastChar) !== null;
}
private function getLastChar(): string
diff --git a/src/Evaluator/Boolean.php b/src/Evaluator/Boolean.php
new file mode 100644
index 0000000..529ee71
--- /dev/null
+++ b/src/Evaluator/Boolean.php
@@ -0,0 +1,19 @@
+
+ */
+namespace nicoSWD\Rule\Evaluator;
+
+enum Boolean: string
+{
+ case TRUE = '1';
+ case FALSE = '0';
+
+ final public static function fromBool(bool $bool): self
+ {
+ return $bool ? self::TRUE : self::FALSE;
+ }
+}
diff --git a/src/Evaluator/Evaluator.php b/src/Evaluator/Evaluator.php
index 4d1797a..e9672ec 100644
--- a/src/Evaluator/Evaluator.php
+++ b/src/Evaluator/Evaluator.php
@@ -3,18 +3,14 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Evaluator;
+use Closure;
+
final class Evaluator implements EvaluatorInterface
{
- private const LOGICAL_AND = '&';
- private const LOGICAL_OR = '|';
-
- private const BOOL_TRUE = '1';
- private const BOOL_FALSE = '0';
-
public function evaluate(string $group): bool
{
$evalGroup = $this->evalGroup();
@@ -22,7 +18,7 @@ public function evaluate(string $group): bool
do {
$group = preg_replace_callback(
- '~\(([^()]+)\)~',
+ '~\((?[^()]+)\)~',
$evalGroup,
$group,
limit: -1,
@@ -30,22 +26,23 @@ public function evaluate(string $group): bool
);
} while ($count > 0);
- return (bool) $evalGroup([1 => $group]);
+ return (bool) $evalGroup(['match' => $group]);
}
- private function evalGroup(): callable
+ private function evalGroup(): Closure
{
return function (array $group): ?int {
$result = null;
$operator = null;
$offset = 0;
- while (isset($group[1][$offset])) {
- $value = $group[1][$offset++];
+ while (isset($group['match'][$offset])) {
+ $value = $group['match'][$offset++];
+ $possibleOperator = Operator::tryFrom($value);
- if ($this->isLogical($value)) {
- $operator = $value;
- } elseif ($this->isBoolean($value)) {
+ if ($possibleOperator) {
+ $operator = $possibleOperator;
+ } elseif (Boolean::tryFrom($value)) {
$result = $this->setResult($result, (int) $value, $operator);
} else {
throw new Exception\UnknownSymbolException(sprintf('Unexpected "%s"', $value));
@@ -56,26 +53,16 @@ private function evalGroup(): callable
};
}
- private function setResult(?int $result, int $value, ?string $operator): int
+ private function setResult(?int $result, int $value, ?Operator $operator): int
{
if (!isset($result)) {
$result = $value;
- } elseif ($operator === self::LOGICAL_AND) {
+ } elseif (Operator::isAnd($operator)) {
$result &= $value;
- } elseif ($operator === self::LOGICAL_OR) {
+ } elseif (Operator::isOr($operator)) {
$result |= $value;
}
return $result;
}
-
- private function isLogical(string $value): bool
- {
- return $value === self::LOGICAL_AND || $value === self::LOGICAL_OR;
- }
-
- private function isBoolean(string $value): bool
- {
- return $value === self::BOOL_TRUE || $value === self::BOOL_FALSE;
- }
}
diff --git a/src/Evaluator/EvaluatorInterface.php b/src/Evaluator/EvaluatorInterface.php
index fc04b08..dee7ecd 100644
--- a/src/Evaluator/EvaluatorInterface.php
+++ b/src/Evaluator/EvaluatorInterface.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Evaluator;
diff --git a/src/Evaluator/Exception/UnknownSymbolException.php b/src/Evaluator/Exception/UnknownSymbolException.php
index 0737f50..85ddec5 100644
--- a/src/Evaluator/Exception/UnknownSymbolException.php
+++ b/src/Evaluator/Exception/UnknownSymbolException.php
@@ -3,10 +3,10 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Evaluator\Exception;
-class UnknownSymbolException extends \Exception
+final class UnknownSymbolException extends \Exception
{
}
diff --git a/src/Evaluator/Operator.php b/src/Evaluator/Operator.php
new file mode 100644
index 0000000..651fa30
--- /dev/null
+++ b/src/Evaluator/Operator.php
@@ -0,0 +1,24 @@
+
+ */
+namespace nicoSWD\Rule\Evaluator;
+
+enum Operator: string
+{
+ case LOGICAL_AND = '&';
+ case LOGICAL_OR = '|';
+
+ public static function isAnd(self $operator): bool
+ {
+ return $operator === self::LOGICAL_AND;
+ }
+
+ public static function isOr(self $operator): bool
+ {
+ return $operator === self::LOGICAL_OR;
+ }
+}
diff --git a/src/Expression/BaseExpression.php b/src/Expression/BaseExpression.php
index 74a269d..5cff5a4 100644
--- a/src/Expression/BaseExpression.php
+++ b/src/Expression/BaseExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/EqualExpression.php b/src/Expression/EqualExpression.php
index dbf7a84..89b2eb6 100644
--- a/src/Expression/EqualExpression.php
+++ b/src/Expression/EqualExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/EqualStrictExpression.php b/src/Expression/EqualStrictExpression.php
index a8f39e6..de98cbe 100644
--- a/src/Expression/EqualStrictExpression.php
+++ b/src/Expression/EqualStrictExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/ExpressionFactory.php b/src/Expression/ExpressionFactory.php
index 9a3ba34..c87dab4 100644
--- a/src/Expression/ExpressionFactory.php
+++ b/src/Expression/ExpressionFactory.php
@@ -3,20 +3,21 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
use nicoSWD\Rule\Parser\Exception\ParserException;
use nicoSWD\Rule\TokenStream\Token;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
-class ExpressionFactory implements ExpressionFactoryInterface
+final class ExpressionFactory implements ExpressionFactoryInterface
{
/** @throws ParserException */
- public function createFromOperator(BaseToken $operator): BaseExpression
+ public function createFromOperator(BaseToken & Operator $operator): BaseExpression
{
- return match (get_class($operator)) {
+ return match ($operator::class) {
Token\TokenEqual::class => new EqualExpression(),
Token\TokenEqualStrict::class => new EqualStrictExpression(),
Token\TokenNotEqual::class => new NotEqualExpression(),
diff --git a/src/Expression/ExpressionFactoryInterface.php b/src/Expression/ExpressionFactoryInterface.php
index 0f12bfc..488b437 100644
--- a/src/Expression/ExpressionFactoryInterface.php
+++ b/src/Expression/ExpressionFactoryInterface.php
@@ -3,13 +3,14 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
interface ExpressionFactoryInterface
{
- public function createFromOperator(BaseToken $operator): BaseExpression;
+ public function createFromOperator(BaseToken & Operator $operator): BaseExpression;
}
diff --git a/src/Expression/GreaterThanEqualExpression.php b/src/Expression/GreaterThanEqualExpression.php
index 3bffd26..5f413d9 100644
--- a/src/Expression/GreaterThanEqualExpression.php
+++ b/src/Expression/GreaterThanEqualExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/GreaterThanExpression.php b/src/Expression/GreaterThanExpression.php
index 4814872..d9dedb5 100644
--- a/src/Expression/GreaterThanExpression.php
+++ b/src/Expression/GreaterThanExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/InExpression.php b/src/Expression/InExpression.php
index 61ab5e2..837e7ce 100644
--- a/src/Expression/InExpression.php
+++ b/src/Expression/InExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/LessThanEqualExpression.php b/src/Expression/LessThanEqualExpression.php
index f76bbc9..5ca7959 100644
--- a/src/Expression/LessThanEqualExpression.php
+++ b/src/Expression/LessThanEqualExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/LessThanExpression.php b/src/Expression/LessThanExpression.php
index 8618aa7..89d9f5f 100644
--- a/src/Expression/LessThanExpression.php
+++ b/src/Expression/LessThanExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/NotEqualExpression.php b/src/Expression/NotEqualExpression.php
index 4c4b3c4..fba4703 100644
--- a/src/Expression/NotEqualExpression.php
+++ b/src/Expression/NotEqualExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/NotEqualStrictExpression.php b/src/Expression/NotEqualStrictExpression.php
index f839e7e..162f973 100644
--- a/src/Expression/NotEqualStrictExpression.php
+++ b/src/Expression/NotEqualStrictExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Expression/NotInExpression.php b/src/Expression/NotInExpression.php
index 58e8f5e..518ba9d 100644
--- a/src/Expression/NotInExpression.php
+++ b/src/Expression/NotInExpression.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Expression;
diff --git a/src/Grammar/CallableFunction.php b/src/Grammar/CallableFunction.php
index 5ac80da..4694ab8 100644
--- a/src/Grammar/CallableFunction.php
+++ b/src/Grammar/CallableFunction.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar;
@@ -11,8 +11,9 @@
abstract class CallableFunction implements CallableUserFunctionInterface
{
- public function __construct(protected ?BaseToken $token = null)
- {
+ public function __construct(
+ protected readonly ?BaseToken $token = null,
+ ) {
}
protected function parseParameter(array $parameters, int $numParam): ?BaseToken
diff --git a/src/Grammar/CallableUserFunctionInterface.php b/src/Grammar/CallableUserFunctionInterface.php
index e3f1bd3..55ef2a4 100644
--- a/src/Grammar/CallableUserFunctionInterface.php
+++ b/src/Grammar/CallableUserFunctionInterface.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar;
diff --git a/src/Grammar/Definition.php b/src/Grammar/Definition.php
new file mode 100644
index 0000000..324922a
--- /dev/null
+++ b/src/Grammar/Definition.php
@@ -0,0 +1,20 @@
+
+ */
+namespace nicoSWD\Rule\Grammar;
+
+use nicoSWD\Rule\TokenStream\Token\Token;
+
+final readonly class Definition
+{
+ public function __construct(
+ public Token $token,
+ public string $regex,
+ public int $priority,
+ ) {
+ }
+}
diff --git a/src/Grammar/Grammar.php b/src/Grammar/Grammar.php
index 63a9572..1ce1820 100644
--- a/src/Grammar/Grammar.php
+++ b/src/Grammar/Grammar.php
@@ -3,24 +3,58 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar;
+use SplPriorityQueue;
+
abstract class Grammar
{
- /** @return array> */
+ private string $compiledRegex = '';
+ /** @var Definition[] */
+ private array $tokens = [];
+
+ /** @return Definition[] */
abstract public function getDefinition(): array;
- /** @return array */
- public function getInternalFunctions(): array
+ /** @return InternalFunction[] */
+ abstract public function getInternalFunctions(): array;
+
+ /** @return InternalMethod[] */
+ abstract public function getInternalMethods(): array;
+
+ public function buildRegex(): string
+ {
+ if (!$this->compiledRegex) {
+ $this->registerTokens();
+ $regex = [];
+
+ foreach ($this->getQueue() as $token) {
+ $regex[] = "(?<{$token->token->value}>{$token->regex})";
+ }
+
+ $this->compiledRegex = '~(' . implode('|', $regex) . ')~As';
+ }
+
+ return $this->compiledRegex;
+ }
+
+ private function getQueue(): SplPriorityQueue
{
- return [];
+ $queue = new SplPriorityQueue();
+
+ foreach ($this->tokens as $token) {
+ $queue->insert($token, $token->priority);
+ }
+
+ return $queue;
}
- /** @return array */
- public function getInternalMethods(): array
+ private function registerTokens(): void
{
- return [];
+ foreach ($this->getDefinition() as $definition) {
+ $this->tokens[$definition->token->value] = $definition;
+ }
}
}
diff --git a/src/Grammar/InternalFunction.php b/src/Grammar/InternalFunction.php
new file mode 100644
index 0000000..fbfdf58
--- /dev/null
+++ b/src/Grammar/InternalFunction.php
@@ -0,0 +1,17 @@
+
+ */
+namespace nicoSWD\Rule\Grammar;
+
+final readonly class InternalFunction
+{
+ public function __construct(
+ public string $name,
+ public string $class,
+ ) {
+ }
+}
diff --git a/src/Grammar/InternalMethod.php b/src/Grammar/InternalMethod.php
new file mode 100644
index 0000000..8bec86d
--- /dev/null
+++ b/src/Grammar/InternalMethod.php
@@ -0,0 +1,17 @@
+
+ */
+namespace nicoSWD\Rule\Grammar;
+
+final readonly class InternalMethod
+{
+ public function __construct(
+ public string $name,
+ public string $class,
+ ) {
+ }
+}
diff --git a/src/Grammar/JavaScript/Functions/ParseFloat.php b/src/Grammar/JavaScript/Functions/ParseFloat.php
index c9238bc..e627879 100644
--- a/src/Grammar/JavaScript/Functions/ParseFloat.php
+++ b/src/Grammar/JavaScript/Functions/ParseFloat.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Functions;
diff --git a/src/Grammar/JavaScript/Functions/ParseInt.php b/src/Grammar/JavaScript/Functions/ParseInt.php
index 08edf11..b693162 100644
--- a/src/Grammar/JavaScript/Functions/ParseInt.php
+++ b/src/Grammar/JavaScript/Functions/ParseInt.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Functions;
diff --git a/src/Grammar/JavaScript/JavaScript.php b/src/Grammar/JavaScript/JavaScript.php
index 6314217..84e84aa 100644
--- a/src/Grammar/JavaScript/JavaScript.php
+++ b/src/Grammar/JavaScript/JavaScript.php
@@ -3,11 +3,14 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript;
+use nicoSWD\Rule\Grammar\Definition;
use nicoSWD\Rule\Grammar\Grammar;
+use nicoSWD\Rule\Grammar\InternalFunction;
+use nicoSWD\Rule\Grammar\InternalMethod;
use nicoSWD\Rule\TokenStream\Token\Token;
final class JavaScript extends Grammar
@@ -15,63 +18,63 @@ final class JavaScript extends Grammar
public function getDefinition(): array
{
return [
- [Token::AND, '&&', 145],
- [Token::OR, '\|\|', 140],
- [Token::NOT_EQUAL_STRICT, '!==', 135],
- [Token::NOT_EQUAL, '<>|!=', 130],
- [Token::EQUAL_STRICT, '===', 125],
- [Token::EQUAL, '==', 120],
- [Token::IN, '\bin\b', 115],
- [Token::NOT_IN, '\bnot\s+in\b', 116],
- [Token::BOOL_TRUE, '\btrue\b', 110],
- [Token::BOOL_FALSE, '\bfalse\b', 111],
- [Token::NULL, '\bnull\b', 105],
- [Token::METHOD, '\.\s*[a-zA-Z_]\w*\s*\(', 100],
- [Token::FUNCTION, '[a-zA-Z_]\w*\s*\(', 95],
- [Token::FLOAT, '-?\d+(?:\.\d+)', 90],
- [Token::INTEGER, '-?\d+', 85],
- [Token::ENCAPSED_STRING, '"[^"]*"|\'[^\']*\'', 80],
- [Token::SMALLER_EQUAL, '<=', 75],
- [Token::GREATER_EQUAL, '>=', 70],
- [Token::SMALLER, '<', 65],
- [Token::GREATER, '>', 60],
- [Token::OPENING_PARENTHESIS, '\(', 55],
- [Token::CLOSING_PARENTHESIS, '\)', 50],
- [Token::OPENING_ARRAY, '\[', 45],
- [Token::CLOSING_ARRAY, '\]', 40],
- [Token::COMMA, ',', 35],
- [Token::REGEX, '/[^/\*].*/[igm]{0,3}', 30],
- [Token::COMMENT, '//[^\r\n]*|/\*.*?\*/', 25],
- [Token::NEWLINE, '\r?\n', 20],
- [Token::SPACE, '\s+', 15],
- [Token::VARIABLE, '[a-zA-Z_]\w*', 10],
- [Token::UNKNOWN, '.', 5],
+ new Definition(Token::AND, '&&', 145),
+ new Definition(Token::OR, '\|\|', 140),
+ new Definition(Token::NOT_EQUAL_STRICT, '!==', 135),
+ new Definition(Token::NOT_EQUAL, '<>|!=', 130),
+ new Definition(Token::EQUAL_STRICT, '===', 125),
+ new Definition(Token::EQUAL, '==', 120),
+ new Definition(Token::IN, '\bin\b', 115),
+ new Definition(Token::NOT_IN, '\bnot\s+in\b', 116),
+ new Definition(Token::BOOL_TRUE, '\btrue\b', 110),
+ new Definition(Token::BOOL_FALSE, '\bfalse\b', 111),
+ new Definition(Token::NULL, '\bnull\b', 105),
+ new Definition(Token::METHOD, '\.\s*[a-zA-Z_]\w*\s*\(', 100),
+ new Definition(Token::FUNCTION, '[a-zA-Z_]\w*\s*\(', 95),
+ new Definition(Token::FLOAT, '-?\d+(?:\.\d+)', 90),
+ new Definition(Token::INTEGER, '-?\d+', 85),
+ new Definition(Token::ENCAPSED_STRING, '"[^"]*"|\'[^\']*\'', 80),
+ new Definition(Token::SMALLER_EQUAL, '<=', 75),
+ new Definition(Token::GREATER_EQUAL, '>=', 70),
+ new Definition(Token::SMALLER, '<', 65),
+ new Definition(Token::GREATER, '>', 60),
+ new Definition(Token::OPENING_PARENTHESIS, '\(', 55),
+ new Definition(Token::CLOSING_PARENTHESIS, '\)', 50),
+ new Definition(Token::OPENING_ARRAY, '\[', 45),
+ new Definition(Token::CLOSING_ARRAY, '\]', 40),
+ new Definition(Token::COMMA, ',', 35),
+ new Definition(Token::REGEX, '/[^/\*].*/[igm]{0,3}', 30),
+ new Definition(Token::COMMENT, '//[^\r\n]*|/\*.*?\*/', 25),
+ new Definition(Token::NEWLINE, '\r?\n', 20),
+ new Definition(Token::SPACE, '\s+', 15),
+ new Definition(Token::VARIABLE, '[a-zA-Z_]\w*', 10),
+ new Definition(Token::UNKNOWN, '.', 5),
];
}
public function getInternalFunctions(): array
{
return [
- 'parseInt' => Functions\ParseInt::class,
- 'parseFloat' => Functions\ParseFloat::class,
+ new InternalFunction('parseInt', Functions\ParseInt::class),
+ new InternalFunction('parseFloat', Functions\ParseFloat::class),
];
}
public function getInternalMethods(): array
{
return [
- 'charAt' => Methods\CharAt::class,
- 'concat' => Methods\Concat::class,
- 'indexOf' => Methods\IndexOf::class,
- 'join' => Methods\Join::class,
- 'replace' => Methods\Replace::class,
- 'split' => Methods\Split::class,
- 'substr' => Methods\Substr::class,
- 'test' => Methods\Test::class,
- 'toLowerCase' => Methods\ToLowerCase::class,
- 'toUpperCase' => Methods\ToUpperCase::class,
- 'startsWith' => Methods\StartsWith::class,
- 'endsWith' => Methods\EndsWith::class,
+ new InternalMethod('charAt', Methods\CharAt::class),
+ new InternalMethod('concat', Methods\Concat::class),
+ new InternalMethod('indexOf', Methods\IndexOf::class),
+ new InternalMethod('join', Methods\Join::class),
+ new InternalMethod('replace', Methods\Replace::class),
+ new InternalMethod('split', Methods\Split::class),
+ new InternalMethod('substr', Methods\Substr::class),
+ new InternalMethod('test', Methods\Test::class),
+ new InternalMethod('toLowerCase', Methods\ToLowerCase::class),
+ new InternalMethod('toUpperCase', Methods\ToUpperCase::class),
+ new InternalMethod('startsWith', Methods\StartsWith::class),
+ new InternalMethod('endsWith', Methods\EndsWith::class),
];
}
}
diff --git a/src/Grammar/JavaScript/Methods/CharAt.php b/src/Grammar/JavaScript/Methods/CharAt.php
index 2276caa..ee0063b 100644
--- a/src/Grammar/JavaScript/Methods/CharAt.php
+++ b/src/Grammar/JavaScript/Methods/CharAt.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
@@ -27,11 +27,7 @@ public function call(?BaseToken ...$parameters): BaseToken
$offset = $offset->getValue();
}
- if (!isset($tokenValue[$offset])) {
- $char = '';
- } else {
- $char = $tokenValue[$offset];
- }
+ $char = $tokenValue[$offset] ?? '';
return new TokenString($char);
}
diff --git a/src/Grammar/JavaScript/Methods/Concat.php b/src/Grammar/JavaScript/Methods/Concat.php
index d009a17..5d9678f 100644
--- a/src/Grammar/JavaScript/Methods/Concat.php
+++ b/src/Grammar/JavaScript/Methods/Concat.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/EndsWith.php b/src/Grammar/JavaScript/Methods/EndsWith.php
index ed22fd1..eddab8f 100644
--- a/src/Grammar/JavaScript/Methods/EndsWith.php
+++ b/src/Grammar/JavaScript/Methods/EndsWith.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/IndexOf.php b/src/Grammar/JavaScript/Methods/IndexOf.php
index d70366b..695e20d 100644
--- a/src/Grammar/JavaScript/Methods/IndexOf.php
+++ b/src/Grammar/JavaScript/Methods/IndexOf.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/Join.php b/src/Grammar/JavaScript/Methods/Join.php
index 0ce5f33..348c9ad 100644
--- a/src/Grammar/JavaScript/Methods/Join.php
+++ b/src/Grammar/JavaScript/Methods/Join.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/Replace.php b/src/Grammar/JavaScript/Methods/Replace.php
index ca6b683..209aea5 100644
--- a/src/Grammar/JavaScript/Methods/Replace.php
+++ b/src/Grammar/JavaScript/Methods/Replace.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/Split.php b/src/Grammar/JavaScript/Methods/Split.php
index 279e70e..c255049 100644
--- a/src/Grammar/JavaScript/Methods/Split.php
+++ b/src/Grammar/JavaScript/Methods/Split.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/StartsWith.php b/src/Grammar/JavaScript/Methods/StartsWith.php
index 980d7e2..de47339 100644
--- a/src/Grammar/JavaScript/Methods/StartsWith.php
+++ b/src/Grammar/JavaScript/Methods/StartsWith.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/Substr.php b/src/Grammar/JavaScript/Methods/Substr.php
index 14b2722..2a4fe73 100644
--- a/src/Grammar/JavaScript/Methods/Substr.php
+++ b/src/Grammar/JavaScript/Methods/Substr.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
@@ -15,14 +15,8 @@ final class Substr extends CallableFunction
{
public function call(?BaseToken ...$parameters): BaseToken
{
- $params = [];
$start = $this->parseParameter($parameters, numParam: 0);
-
- if (!$start) {
- $params[] = 0;
- } else {
- $params[] = (int) $start->getValue();
- }
+ $params = [(int) $start?->getValue()];
$offset = $this->parseParameter($parameters, numParam: 1);
@@ -32,6 +26,6 @@ public function call(?BaseToken ...$parameters): BaseToken
$value = substr($this->token->getValue(), ...$params);
- return new TokenString((string) $value);
+ return new TokenString($value);
}
}
diff --git a/src/Grammar/JavaScript/Methods/Test.php b/src/Grammar/JavaScript/Methods/Test.php
index 1701e77..52bcf0b 100644
--- a/src/Grammar/JavaScript/Methods/Test.php
+++ b/src/Grammar/JavaScript/Methods/Test.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
@@ -19,7 +19,7 @@ final class Test extends CallableFunction
public function call(?BaseToken ...$parameters): BaseToken
{
if (!$this->token instanceof TokenRegex) {
- throw new ParserException('undefined is not a function');
+ throw new ParserException('test() is not a function');
}
$string = $this->parseParameter($parameters, numParam: 0);
@@ -27,11 +27,11 @@ public function call(?BaseToken ...$parameters): BaseToken
if (!$string) {
$bool = false;
} else {
- // Remove "g" modifier as is does not exist in PHP
+ // Remove "g" modifier as it does not exist in PHP
// It's also irrelevant in .test() but allowed in JS here
$pattern = preg_replace_callback(
'~/[igm]{0,3}$~',
- fn (array $modifiers) => str_replace('g', '', $modifiers[0]),
+ static fn (array $modifiers): string => str_replace('g', '', $modifiers[0]),
$this->token->getValue()
);
diff --git a/src/Grammar/JavaScript/Methods/ToLowerCase.php b/src/Grammar/JavaScript/Methods/ToLowerCase.php
index 14b259e..8b61f71 100644
--- a/src/Grammar/JavaScript/Methods/ToLowerCase.php
+++ b/src/Grammar/JavaScript/Methods/ToLowerCase.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Grammar/JavaScript/Methods/ToUpperCase.php b/src/Grammar/JavaScript/Methods/ToUpperCase.php
index dd3eea9..fba4b76 100644
--- a/src/Grammar/JavaScript/Methods/ToUpperCase.php
+++ b/src/Grammar/JavaScript/Methods/ToUpperCase.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Grammar\JavaScript\Methods;
diff --git a/src/Highlighter/Exception/InvalidGroupException.php b/src/Highlighter/Exception/InvalidGroupException.php
deleted file mode 100644
index a06295d..0000000
--- a/src/Highlighter/Exception/InvalidGroupException.php
+++ /dev/null
@@ -1,12 +0,0 @@
-
- */
-namespace nicoSWD\Rule\Highlighter\Exception;
-
-class InvalidGroupException extends \Exception
-{
-}
diff --git a/src/Highlighter/Highlighter.php b/src/Highlighter/Highlighter.php
index f1bd01a..b90d28f 100644
--- a/src/Highlighter/Highlighter.php
+++ b/src/Highlighter/Highlighter.php
@@ -3,46 +3,29 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Highlighter;
-use ArrayIterator;
+use Iterator;
use nicoSWD\Rule\Tokenizer\TokenizerInterface;
+use nicoSWD\Rule\TokenStream\Token\BaseToken;
use nicoSWD\Rule\TokenStream\Token\TokenType;
+use SplObjectStorage;
final class Highlighter
{
- /** @var string[] */
- private array $styles = [
- TokenType::COMMENT => 'color: #948a8a; font-style: italic;',
- TokenType::LOGICAL => 'color: #c72d2d;',
- TokenType::OPERATOR => 'color: #000;',
- TokenType::PARENTHESIS => 'color: #000;',
- TokenType::SPACE => '',
- TokenType::UNKNOWN => '',
- TokenType::VALUE => 'color: #e36700; font-style: italic;',
- TokenType::VARIABLE => 'color: #007694; font-weight: 900;',
- TokenType::METHOD => 'color: #000',
- TokenType::SQUARE_BRACKET => '',
- TokenType::COMMA => '',
- TokenType::FUNCTION => '',
- TokenType::INT_VALUE => '',
- ];
+ private SplObjectStorage $styles;
- public function __construct(private TokenizerInterface $tokenizer)
- {
+ public function __construct(
+ private readonly TokenizerInterface $tokenizer,
+ ) {
+ $this->styles = $this->defaultStyles();
}
- public function setStyle(int $group, string $style): void
+ public function setStyle(TokenType $group, string $style): void
{
- if (!isset($this->styles[$group])) {
- throw new Exception\InvalidGroupException(
- 'Invalid group'
- );
- }
-
- $this->styles[$group] = (string) $style;
+ $this->styles[$group] = $style;
}
public function highlightString(string $string): string
@@ -50,14 +33,16 @@ public function highlightString(string $string): string
return $this->highlightTokens($this->tokenizer->tokenize($string));
}
- public function highlightTokens(ArrayIterator $tokens): string
+ public function highlightTokens(Iterator $tokens): string
{
$string = '';
foreach ($tokens as $token) {
- if ($style = $this->styles[$token->getType()]) {
- $value = htmlentities($token->getOriginalValue(), ENT_QUOTES, 'utf-8');
- $string .= '' . $value . '';
+ /** @var BaseToken $token */
+ $tokenType = $token->getType();
+
+ if (isset($this->styles[$tokenType])) {
+ $string .= '' . $this->encode($token) . '';
} else {
$string .= $token->getOriginalValue();
}
@@ -65,4 +50,23 @@ public function highlightTokens(ArrayIterator $tokens): string
return '' . $string . '
';
}
+
+ private function encode(BaseToken $token): string
+ {
+ return htmlentities($token->getOriginalValue(), ENT_QUOTES, 'utf-8');
+ }
+
+ private function defaultStyles(): SplObjectStorage
+ {
+ $styles = new SplObjectStorage();
+ $styles[TokenType::COMMENT] = 'color: #948a8a; font-style: italic;';
+ $styles[TokenType::LOGICAL] = 'color: #c72d2d;';
+ $styles[TokenType::OPERATOR] = 'color: #000;';
+ $styles[TokenType::PARENTHESIS] = 'color: #000;';
+ $styles[TokenType::VALUE] = 'color: #e36700; font-style: italic;';
+ $styles[TokenType::VARIABLE] = 'color: #007694; font-weight: 900;';
+ $styles[TokenType::METHOD] = 'color: #000';
+
+ return $styles;
+ }
}
diff --git a/src/Parser/EvaluatableExpression.php b/src/Parser/EvaluatableExpression.php
new file mode 100644
index 0000000..49e35da
--- /dev/null
+++ b/src/Parser/EvaluatableExpression.php
@@ -0,0 +1,69 @@
+
+ */
+namespace nicoSWD\Rule\Parser;
+
+use nicoSWD\Rule\Expression\BaseExpression;
+use nicoSWD\Rule\Expression\ExpressionFactoryInterface;
+use nicoSWD\Rule\TokenStream\Token\BaseToken;
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class EvaluatableExpression
+{
+ public (BaseToken & Operator) | null $operator = null;
+ public array $values = [];
+
+ public function __construct(
+ private readonly ExpressionFactoryInterface $expressionFactory,
+ ) {
+ }
+
+ /** @throws Exception\ParserException */
+ public function evaluate(): bool
+ {
+ $result = $this->expression()->evaluate(...$this->values);
+ $this->clear();
+
+ return $result;
+ }
+
+ public function isComplete(): bool
+ {
+ return $this->hasOperator() && $this->hasBothValues();
+ }
+
+ public function addValue(mixed $value): void
+ {
+ $this->values[] = $value;
+ }
+
+ public function hasBothValues(): bool
+ {
+ return count($this->values) === 2;
+ }
+
+ public function hasNoValues(): bool
+ {
+ return count($this->values) === 0;
+ }
+
+ public function hasOperator(): bool
+ {
+ return $this->operator !== null;
+ }
+
+ private function clear(): void
+ {
+ $this->operator = null;
+ $this->values = [];
+ }
+
+ private function expression(): BaseExpression
+ {
+ return $this->expressionFactory->createFromOperator($this->operator);
+ }
+}
diff --git a/src/Parser/EvaluatableExpressionFactory.php b/src/Parser/EvaluatableExpressionFactory.php
new file mode 100644
index 0000000..9aa8458
--- /dev/null
+++ b/src/Parser/EvaluatableExpressionFactory.php
@@ -0,0 +1,20 @@
+
+ */
+namespace nicoSWD\Rule\Parser;
+
+use nicoSWD\Rule\Expression\ExpressionFactory;
+
+final class EvaluatableExpressionFactory
+{
+ public function create(): EvaluatableExpression
+ {
+ return new EvaluatableExpression(
+ new ExpressionFactory()
+ );
+ }
+}
diff --git a/src/Parser/Exception/ParserException.php b/src/Parser/Exception/ParserException.php
index 84a909a..f70e37a 100644
--- a/src/Parser/Exception/ParserException.php
+++ b/src/Parser/Exception/ParserException.php
@@ -3,13 +3,14 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Parser\Exception;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
-class ParserException extends \Exception
+final class ParserException extends \Exception
{
public static function unexpectedToken(BaseToken $token): self
{
@@ -61,15 +62,10 @@ public static function unsupportedType(string $type): self
return new self(sprintf('Unsupported PHP type: "%s"', $type));
}
- public static function unknownOperator(BaseToken $token): self
+ public static function unknownOperator(BaseToken & Operator $token): self
{
return new self(
sprintf('Unexpected operator %s at position %d', $token->getOriginalValue(), $token->getOffset())
);
}
-
- public static function unknownTokenName(string $tokenName): self
- {
- return new self("Unknown token $tokenName");
- }
}
diff --git a/src/Parser/Parser.php b/src/Parser/Parser.php
index f572781..0fe5d37 100644
--- a/src/Parser/Parser.php
+++ b/src/Parser/Parser.php
@@ -3,118 +3,94 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Parser;
use Closure;
use nicoSWD\Rule\Compiler\CompilerFactoryInterface;
use nicoSWD\Rule\Compiler\CompilerInterface;
-use nicoSWD\Rule\Expression\ExpressionFactoryInterface;
-use nicoSWD\Rule\TokenStream\AST;
+use nicoSWD\Rule\TokenStream\TokenStream;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
use nicoSWD\Rule\TokenStream\Token\TokenType;
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
-class Parser
+final readonly class Parser
{
- private ?BaseToken $operator;
- private array $values = [];
-
public function __construct(
- private AST $ast,
- private ExpressionFactoryInterface $expressionFactory,
- private CompilerFactoryInterface $compilerFactory
+ private TokenStream $tokenStream,
+ private EvaluatableExpressionFactory $expressionFactory,
+ private CompilerFactoryInterface $compilerFactory,
) {
}
+ /** @throws Exception\ParserException */
public function parse(string $rule): string
{
$compiler = $this->compilerFactory->create();
- $this->resetState();
+ $expression = $this->expressionFactory->create();
- foreach ($this->ast->getStream($rule) as $token) {
- $handler = $this->getHandlerForType($token->getType());
- $handler($token, $compiler);
+ foreach ($this->tokenStream->getStream($rule) as $token) {
+ $handler = $this->getHandlerForToken($token, $expression);
+ $handler($compiler);
- if ($this->expressionCanBeEvaluated()) {
- $this->evaluateExpression($compiler);
+ if ($expression->isComplete()) {
+ $compiler->addBoolean($expression->evaluate());
}
}
return $compiler->getCompiledRule();
}
- private function getHandlerForType(int $tokenType): Closure
+ private function getHandlerForToken(BaseToken $token, EvaluatableExpression $expression): Closure
{
- return match ($tokenType) {
- TokenType::VALUE, TokenType::INT_VALUE => $this->handleValueToken(),
- TokenType::OPERATOR => $this->handleOperatorToken(),
- TokenType::LOGICAL => $this->handleLogicalToken(),
- TokenType::PARENTHESIS => $this->handleParenthesisToken(),
+ return match ($token->getType()) {
+ TokenType::VALUE => $this->handleValueToken($token, $expression),
+ TokenType::OPERATOR => $this->handleOperatorToken($token, $expression),
+ TokenType::LOGICAL => $this->handleLogicalToken($token),
+ TokenType::PARENTHESIS => $this->handleParenthesisToken($token),
TokenType::COMMENT, TokenType::SPACE => $this->handleDummyToken(),
- default => $this->handleUnknownToken(),
+ default => $this->handleUnknownToken($token),
};
}
- private function evaluateExpression(CompilerInterface $compiler): void
- {
- $expression = $this->expressionFactory->createFromOperator($this->operator);
-
- $compiler->addBoolean(
- $expression->evaluate(...$this->values)
- );
-
- $this->resetState();
- }
-
- private function expressionCanBeEvaluated(): bool
+ private function handleValueToken(BaseToken $token, EvaluatableExpression $expression): Closure
{
- return count($this->values) === 2;
+ return static fn () => $expression->addValue($token->getValue());
}
- private function handleValueToken(): Closure
+ private function handleLogicalToken(BaseToken $token): Closure
{
- return fn (BaseToken $token) => $this->values[] = $token->getValue();
+ return static fn (CompilerInterface $compiler) => $compiler->addLogical($token);
}
- private function handleLogicalToken(): Closure
+ private function handleParenthesisToken(BaseToken $token): Closure
{
- return fn (BaseToken $token, CompilerInterface $compiler) => $compiler->addLogical($token);
+ return static fn (CompilerInterface $compiler) => $compiler->addParentheses($token);
}
- private function handleParenthesisToken(): Closure
+ private function handleUnknownToken(BaseToken $token): Closure
{
- return fn (BaseToken $token, CompilerInterface $compiler) => $compiler->addParentheses($token);
+ return static fn () => throw Exception\ParserException::unknownToken($token);
}
- private function handleUnknownToken(): Closure
+ private function handleOperatorToken(BaseToken & Operator $token, EvaluatableExpression $expression): Closure
{
- return fn (BaseToken $token) => throw Exception\ParserException::unknownToken($token);
- }
-
- private function handleOperatorToken(): Closure
- {
- return function (BaseToken $token): void {
- if (isset($this->operator)) {
+ return static function () use ($token, $expression): void {
+ if ($expression->hasOperator()) {
throw Exception\ParserException::unexpectedToken($token);
- } elseif (empty($this->values)) {
+ } elseif ($expression->hasNoValues()) {
throw Exception\ParserException::incompleteExpression($token);
}
- $this->operator = $token;
+ $expression->operator = $token;
};
}
private function handleDummyToken(): Closure
{
- return function (): void {
+ return static function (): void {
// Do nothing
};
}
-
- private function resetState(): void
- {
- $this->operator = null;
- $this->values = [];
- }
}
diff --git a/src/Rule.php b/src/Rule.php
index b860482..3d3b8e0 100644
--- a/src/Rule.php
+++ b/src/Rule.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule;
@@ -12,8 +12,8 @@
class Rule
{
+ private readonly Parser\Parser $parser;
private string $rule;
- private Parser\Parser $parser;
private string $parsedRule = '';
private string $error = '';
private static object $container;
@@ -28,6 +28,7 @@ public function __construct(string $rule, array $variables = [])
$this->rule = $rule;
}
+ /** @throws Parser\Exception\ParserException */
public function isTrue(): bool
{
/** @var EvaluatorInterface $evaluator */
@@ -39,6 +40,7 @@ public function isTrue(): bool
);
}
+ /** @throws Parser\Exception\ParserException */
public function isFalse(): bool
{
return !$this->isTrue();
diff --git a/src/TokenStream/AST.php b/src/TokenStream/AST.php
deleted file mode 100644
index 41b72d0..0000000
--- a/src/TokenStream/AST.php
+++ /dev/null
@@ -1,132 +0,0 @@
-
- */
-namespace nicoSWD\Rule\TokenStream;
-
-use Closure;
-use InvalidArgumentException;
-use nicoSWD\Rule\Grammar\CallableUserFunctionInterface;
-use nicoSWD\Rule\Parser\Exception\ParserException;
-use nicoSWD\Rule\TokenStream\Exception\UndefinedVariableException;
-use nicoSWD\Rule\TokenStream\Token\BaseToken;
-use nicoSWD\Rule\TokenStream\Token\TokenFactory;
-use nicoSWD\Rule\Tokenizer\TokenizerInterface;
-use nicoSWD\Rule\TokenStream\Token\TokenObject;
-
-class AST
-{
- private array $functions = [];
- private array $methods = [];
- private array $variables = [];
-
- public function __construct(
- private TokenizerInterface $tokenizer,
- private TokenFactory $tokenFactory,
- private TokenStreamFactory $tokenStreamFactory,
- private CallableUserMethodFactoryInterface $userMethodFactory
- ) {
- }
-
- public function getStream(string $rule): TokenStream
- {
- return $this->tokenStreamFactory->create($this->tokenizer->tokenize($rule), $this);
- }
-
- /**
- * @throws Exception\UndefinedMethodException
- * @throws Exception\ForbiddenMethodException
- */
- public function getMethod(string $methodName, BaseToken $token): CallableUserFunctionInterface
- {
- if ($token instanceof TokenObject) {
- return $this->getCallableUserMethod($token, $methodName);
- }
-
- if (empty($this->methods)) {
- $this->registerMethods();
- }
-
- if (!isset($this->methods[$methodName])) {
- throw new Exception\UndefinedMethodException();
- }
-
- return new $this->methods[$methodName]($token);
- }
-
- public function setVariables(array $variables): void
- {
- $this->variables = $variables;
- }
-
- /**
- * @throws UndefinedVariableException
- * @throws ParserException
- */
- public function getVariable(string $variableName): BaseToken
- {
- if (!$this->variableExists($variableName)) {
- throw new UndefinedVariableException($variableName);
- }
-
- return $this->tokenFactory->createFromPHPType($this->variables[$variableName]);
- }
-
- public function variableExists(string $variableName): bool
- {
- return array_key_exists($variableName, $this->variables);
- }
-
- /** @throws Exception\UndefinedFunctionException */
- public function getFunction(string $functionName): Closure
- {
- if (empty($this->functions)) {
- $this->registerFunctions();
- }
-
- if (!isset($this->functions[$functionName])) {
- throw new Exception\UndefinedFunctionException($functionName);
- }
-
- return $this->functions[$functionName];
- }
-
- private function registerMethods(): void
- {
- $this->methods = $this->tokenizer->getGrammar()->getInternalMethods();
- }
-
- private function registerFunctionClass(string $functionName, string $className): void
- {
- $this->functions[$functionName] = function (...$args) use ($className) {
- $function = new $className();
-
- if (!$function instanceof CallableUserFunctionInterface) {
- throw new InvalidArgumentException(
- sprintf(
- "%s must be an instance of %s",
- $className,
- CallableUserFunctionInterface::class
- )
- );
- }
-
- return $function->call(...$args);
- };
- }
-
- private function registerFunctions(): void
- {
- foreach ($this->tokenizer->getGrammar()->getInternalFunctions() as $functionName => $className) {
- $this->registerFunctionClass($functionName, $className);
- }
- }
-
- private function getCallableUserMethod(BaseToken $token, string $methodName): CallableUserFunctionInterface
- {
- return $this->userMethodFactory->create($token, $this->tokenFactory, $methodName);
- }
-}
diff --git a/src/TokenStream/CallableUserMethod.php b/src/TokenStream/CallableUserMethod.php
index 27c14a1..a59d5ff 100644
--- a/src/TokenStream/CallableUserMethod.php
+++ b/src/TokenStream/CallableUserMethod.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream;
@@ -16,8 +16,9 @@ final class CallableUserMethod implements CallableUserFunctionInterface
{
private const MAGIC_METHOD_PREFIX = '__';
- private TokenFactory $tokenFactory;
- private Closure $callable;
+ private readonly TokenFactory $tokenFactory;
+ private readonly Closure $callable;
+
private array $methodPrefixes = ['', 'get', 'is', 'get_', 'is_'];
/**
@@ -32,10 +33,10 @@ public function __construct(BaseToken $token, TokenFactory $tokenFactory, string
public function call(?BaseToken ...$param): BaseToken
{
- $callableCopy = $this->callable;
+ $callable = $this->callable;
return $this->tokenFactory->createFromPHPType(
- $callableCopy(...$param)
+ $callable(...$param)
);
}
@@ -48,12 +49,12 @@ private function getCallable(BaseToken $token, string $methodName): Closure
$object = $token->getValue();
if (property_exists($object, $methodName)) {
- return fn () => $object->{$methodName};
+ return static fn (): mixed => $object->{$methodName};
}
$method = $this->findCallableMethod($object, $methodName);
- return fn (?BaseToken ...$params) => $method(
+ return fn (?BaseToken ...$params): mixed => $method(
...$this->getTokenValues($params)
);
}
@@ -80,13 +81,7 @@ private function findCallableMethod(object $object, string $methodName): callabl
private function getTokenValues(array $params): array
{
- $values = [];
-
- foreach ($params as $token) {
- $values[] = $token->getValue();
- }
-
- return $values;
+ return array_map(static fn (BaseToken $token): mixed => $token->getValue(), $params);
}
/** @throws Exception\ForbiddenMethodException */
diff --git a/src/TokenStream/CallableUserMethodFactory.php b/src/TokenStream/CallableUserMethodFactory.php
index cae71bb..3a18863 100644
--- a/src/TokenStream/CallableUserMethodFactory.php
+++ b/src/TokenStream/CallableUserMethodFactory.php
@@ -3,16 +3,20 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream;
+use nicoSWD\Rule\Grammar\CallableUserFunctionInterface;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
use nicoSWD\Rule\TokenStream\Token\TokenFactory;
final class CallableUserMethodFactory implements CallableUserMethodFactoryInterface
{
- public function create(BaseToken $token, TokenFactory $tokenFactory, string $methodName): CallableUserMethod
+ /**
+ * {@inheritDoc}
+ */
+ public function create(BaseToken $token, TokenFactory $tokenFactory, string $methodName): CallableUserFunctionInterface
{
return new CallableUserMethod($token, $tokenFactory, $methodName);
}
diff --git a/src/TokenStream/CallableUserMethodFactoryInterface.php b/src/TokenStream/CallableUserMethodFactoryInterface.php
index 2601617..efb85de 100644
--- a/src/TokenStream/CallableUserMethodFactoryInterface.php
+++ b/src/TokenStream/CallableUserMethodFactoryInterface.php
@@ -3,14 +3,19 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream;
+use nicoSWD\Rule\Grammar\CallableUserFunctionInterface;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
use nicoSWD\Rule\TokenStream\Token\TokenFactory;
interface CallableUserMethodFactoryInterface
{
- public function create(BaseToken $token, TokenFactory $tokenFactory, string $methodName): CallableUserMethod;
+ /**
+ * @throws Exception\ForbiddenMethodException
+ * @throws Exception\UndefinedMethodException
+ */
+ public function create(BaseToken $token, TokenFactory $tokenFactory, string $methodName): CallableUserFunctionInterface;
}
diff --git a/src/TokenStream/Exception/ForbiddenMethodException.php b/src/TokenStream/Exception/ForbiddenMethodException.php
index 8742ed5..315930e 100644
--- a/src/TokenStream/Exception/ForbiddenMethodException.php
+++ b/src/TokenStream/Exception/ForbiddenMethodException.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Exception;
diff --git a/src/TokenStream/Exception/UndefinedFunctionException.php b/src/TokenStream/Exception/UndefinedFunctionException.php
index 5f9c317..a4115d7 100644
--- a/src/TokenStream/Exception/UndefinedFunctionException.php
+++ b/src/TokenStream/Exception/UndefinedFunctionException.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Exception;
diff --git a/src/TokenStream/Exception/UndefinedMethodException.php b/src/TokenStream/Exception/UndefinedMethodException.php
index 5a99291..4f27202 100644
--- a/src/TokenStream/Exception/UndefinedMethodException.php
+++ b/src/TokenStream/Exception/UndefinedMethodException.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Exception;
diff --git a/src/TokenStream/Exception/UndefinedVariableException.php b/src/TokenStream/Exception/UndefinedVariableException.php
index 41c07dc..adefc6c 100644
--- a/src/TokenStream/Exception/UndefinedVariableException.php
+++ b/src/TokenStream/Exception/UndefinedVariableException.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Exception;
diff --git a/src/TokenStream/Node/BaseNode.php b/src/TokenStream/Node/BaseNode.php
index c9748e8..4724f3e 100644
--- a/src/TokenStream/Node/BaseNode.php
+++ b/src/TokenStream/Node/BaseNode.php
@@ -3,27 +3,28 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Node;
use Closure;
use nicoSWD\Rule\Grammar\CallableUserFunctionInterface;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
+use nicoSWD\Rule\TokenStream\Token\Type\Method;
+use nicoSWD\Rule\TokenStream\Token\Type\Whitespace;
use nicoSWD\Rule\TokenStream\TokenCollection;
use nicoSWD\Rule\Parser\Exception\ParserException;
-use nicoSWD\Rule\TokenStream\TokenStream;
+use nicoSWD\Rule\TokenStream\TokenIterator;
use nicoSWD\Rule\TokenStream\Token\TokenType;
abstract class BaseNode
{
- protected TokenStream $tokenStream;
- private string $methodName = '';
+ private string $methodName;
private int $methodOffset = 0;
- public function __construct(TokenStream $tokenStream)
- {
- $this->tokenStream = $tokenStream;
+ public function __construct(
+ protected readonly TokenIterator $tokenStream,
+ ) {
}
/** @throws ParserException */
@@ -43,12 +44,12 @@ protected function hasMethodCall(): bool
if (!$token) {
break;
- } elseif ($token->isMethod()) {
+ } elseif ($token instanceof Method) {
$this->methodName = $token->getValue();
$this->methodOffset = $stack->key();
$hasMethod = true;
break;
- } elseif (!$token->isWhitespace()) {
+ } elseif (!$token instanceof Whitespace) {
break;
}
}
@@ -100,7 +101,7 @@ protected function getCurrentNode(): BaseToken
}
/** @throws ParserException */
- private function getCommaSeparatedValues(int $stopAt): TokenCollection
+ private function getCommaSeparatedValues(TokenType $stopAt): TokenCollection
{
$items = new TokenCollection();
$commaExpected = false;
@@ -108,14 +109,14 @@ private function getCommaSeparatedValues(int $stopAt): TokenCollection
do {
$token = $this->getNextToken();
- if ($token->isValue()) {
+ if (TokenType::isValue($token)) {
if ($commaExpected) {
throw ParserException::unexpectedToken($token);
}
$commaExpected = true;
$items->attach($token);
- } elseif ($token->isComma()) {
+ } elseif ($token->isOfType(TokenType::COMMA)) {
if (!$commaExpected) {
throw ParserException::unexpectedComma($token);
}
@@ -123,7 +124,7 @@ private function getCommaSeparatedValues(int $stopAt): TokenCollection
$commaExpected = false;
} elseif ($token->isOfType($stopAt)) {
break;
- } elseif (!$token->isWhitespace()) {
+ } elseif (!$token->canBeIgnored()) {
throw ParserException::unexpectedToken($token);
}
} while (true);
diff --git a/src/TokenStream/Node/NodeArray.php b/src/TokenStream/Node/NodeArray.php
index 02d598e..bb419a9 100644
--- a/src/TokenStream/Node/NodeArray.php
+++ b/src/TokenStream/Node/NodeArray.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Node;
diff --git a/src/TokenStream/Node/NodeFunction.php b/src/TokenStream/Node/NodeFunction.php
index 1d2bbe8..8eba994 100644
--- a/src/TokenStream/Node/NodeFunction.php
+++ b/src/TokenStream/Node/NodeFunction.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Node;
diff --git a/src/TokenStream/Node/NodeString.php b/src/TokenStream/Node/NodeString.php
index 62b6758..9cf630c 100644
--- a/src/TokenStream/Node/NodeString.php
+++ b/src/TokenStream/Node/NodeString.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Node;
diff --git a/src/TokenStream/Node/NodeVariable.php b/src/TokenStream/Node/NodeVariable.php
index 5e23341..7b9600a 100644
--- a/src/TokenStream/Node/NodeVariable.php
+++ b/src/TokenStream/Node/NodeVariable.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Node;
diff --git a/src/TokenStream/Token/BaseToken.php b/src/TokenStream/Token/BaseToken.php
index 4456fff..f7c2491 100644
--- a/src/TokenStream/Token/BaseToken.php
+++ b/src/TokenStream/Token/BaseToken.php
@@ -3,20 +3,20 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
use nicoSWD\Rule\Parser\Exception\ParserException;
-use nicoSWD\Rule\TokenStream\TokenStream;
+use nicoSWD\Rule\TokenStream\TokenIterator;
abstract class BaseToken
{
- abstract public function getType(): int;
+ abstract public function getType(): TokenType;
public function __construct(
- private mixed $value,
- private int $offset = 0
+ private readonly mixed $value,
+ private readonly int $offset = 0,
) {
}
@@ -36,48 +36,20 @@ public function getOffset(): int
}
/** @throws ParserException */
- public function createNode(TokenStream $tokenStream): self
+ public function createNode(TokenIterator $tokenStream): self
{
return $this;
}
- public function isOfType(int $type): bool
+ public function isOfType(TokenType $type): bool
{
- return ($this->getType() | $type) === $type;
+ return $this->getType() === $type;
}
- public function isValue(): bool
+ public function canBeIgnored(): bool
{
- return $this->isOfType(TokenType::VALUE | TokenType::INT_VALUE);
- }
-
- public function isWhitespace(): bool
- {
- return $this->isOfType(TokenType::SPACE | TokenType::COMMENT);
- }
-
- public function isMethod(): bool
- {
- return $this->isOfType(TokenType::METHOD);
- }
-
- public function isComma(): bool
- {
- return $this->isOfType(TokenType::COMMA);
- }
-
- public function isOperator(): bool
- {
- return $this->isOfType(TokenType::OPERATOR);
- }
-
- public function isLogical(): bool
- {
- return $this->isOfType(TokenType::LOGICAL);
- }
-
- public function isParenthesis(): bool
- {
- return $this->isOfType(TokenType::PARENTHESIS);
+ return
+ $this->isOfType(TokenType::SPACE) ||
+ $this->isOfType(TokenType::COMMENT);
}
}
diff --git a/src/TokenStream/Token/Token.php b/src/TokenStream/Token/Token.php
index 8112716..95dbb2b 100644
--- a/src/TokenStream/Token/Token.php
+++ b/src/TokenStream/Token/Token.php
@@ -3,41 +3,41 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-class Token
+enum Token: string
{
- public const AND = 'And';
- public const OR = 'Or';
- public const NOT_EQUAL_STRICT = 'NotEqualStrict';
- public const NOT_EQUAL = 'NotEqual';
- public const EQUAL_STRICT = 'EqualStrict';
- public const EQUAL = 'Equal';
- public const IN = 'In';
- public const NOT_IN = 'NotIn';
- public const BOOL_TRUE = 'True';
- public const BOOL_FALSE = 'False';
- public const NULL = 'Null';
- public const METHOD = 'Method';
- public const FUNCTION = 'Function';
- public const VARIABLE = 'Variable';
- public const FLOAT = 'Float';
- public const INTEGER = 'Integer';
- public const ENCAPSED_STRING = 'EncapsedString';
- public const SMALLER_EQUAL = 'SmallerEqual';
- public const GREATER_EQUAL = 'GreaterEqual';
- public const SMALLER = 'Smaller';
- public const GREATER = 'Greater';
- public const OPENING_PARENTHESIS = 'OpeningParentheses';
- public const CLOSING_PARENTHESIS = 'ClosingParentheses';
- public const OPENING_ARRAY = 'OpeningArray';
- public const CLOSING_ARRAY = 'ClosingArray';
- public const COMMA = 'Comma';
- public const REGEX = 'Regex';
- public const COMMENT = 'Comment';
- public const NEWLINE = 'Newline';
- public const SPACE = 'Space';
- public const UNKNOWN = 'Unknown';
+ case AND = 'And';
+ case OR = 'Or';
+ case NOT_EQUAL_STRICT = 'NotEqualStrict';
+ case NOT_EQUAL = 'NotEqual';
+ case EQUAL_STRICT = 'EqualStrict';
+ case EQUAL = 'Equal';
+ case IN = 'In';
+ case NOT_IN = 'NotIn';
+ case BOOL_TRUE = 'True';
+ case BOOL_FALSE = 'False';
+ case NULL = 'Null';
+ case METHOD = 'Method';
+ case FUNCTION = 'Function';
+ case VARIABLE = 'Variable';
+ case FLOAT = 'Float';
+ case INTEGER = 'Integer';
+ case ENCAPSED_STRING = 'EncapsedString';
+ case SMALLER_EQUAL = 'SmallerEqual';
+ case GREATER_EQUAL = 'GreaterEqual';
+ case SMALLER = 'Smaller';
+ case GREATER = 'Greater';
+ case OPENING_PARENTHESIS = 'OpeningParentheses';
+ case CLOSING_PARENTHESIS = 'ClosingParentheses';
+ case OPENING_ARRAY = 'OpeningArray';
+ case CLOSING_ARRAY = 'ClosingArray';
+ case COMMA = 'Comma';
+ case REGEX = 'Regex';
+ case COMMENT = 'Comment';
+ case NEWLINE = 'Newline';
+ case SPACE = 'Space';
+ case UNKNOWN = 'Unknown';
}
diff --git a/src/TokenStream/Token/TokenAnd.php b/src/TokenStream/Token/TokenAnd.php
index fc6f7dd..8930c80 100644
--- a/src/TokenStream/Token/TokenAnd.php
+++ b/src/TokenStream/Token/TokenAnd.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenAnd extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Logical;
+
+final class TokenAnd extends BaseToken implements Logical
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::LOGICAL;
}
diff --git a/src/TokenStream/Token/TokenArray.php b/src/TokenStream/Token/TokenArray.php
index 1201b06..e85fe5f 100644
--- a/src/TokenStream/Token/TokenArray.php
+++ b/src/TokenStream/Token/TokenArray.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenArray extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+
+final class TokenArray extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VALUE;
}
diff --git a/src/TokenStream/Token/TokenBool.php b/src/TokenStream/Token/TokenBool.php
index 1e35584..cb84ed6 100644
--- a/src/TokenStream/Token/TokenBool.php
+++ b/src/TokenStream/Token/TokenBool.php
@@ -3,11 +3,13 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-abstract class TokenBool extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+
+abstract class TokenBool extends BaseToken implements Value
{
public static function fromBool(bool $bool): TokenBool
{
@@ -17,7 +19,7 @@ public static function fromBool(bool $bool): TokenBool
};
}
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VALUE;
}
diff --git a/src/TokenStream/Token/TokenBoolFalse.php b/src/TokenStream/Token/TokenBoolFalse.php
index 7451660..3c3ccc4 100644
--- a/src/TokenStream/Token/TokenBoolFalse.php
+++ b/src/TokenStream/Token/TokenBoolFalse.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
diff --git a/src/TokenStream/Token/TokenBoolTrue.php b/src/TokenStream/Token/TokenBoolTrue.php
index d6f9965..e6cbf38 100644
--- a/src/TokenStream/Token/TokenBoolTrue.php
+++ b/src/TokenStream/Token/TokenBoolTrue.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
diff --git a/src/TokenStream/Token/TokenClosingArray.php b/src/TokenStream/Token/TokenClosingArray.php
index 3bae87f..ff0d105 100644
--- a/src/TokenStream/Token/TokenClosingArray.php
+++ b/src/TokenStream/Token/TokenClosingArray.php
@@ -3,13 +3,13 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
final class TokenClosingArray extends BaseToken
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::SQUARE_BRACKET;
}
diff --git a/src/TokenStream/Token/TokenClosingParenthesis.php b/src/TokenStream/Token/TokenClosingParenthesis.php
index c77e898..9ee93f4 100644
--- a/src/TokenStream/Token/TokenClosingParenthesis.php
+++ b/src/TokenStream/Token/TokenClosingParenthesis.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenClosingParenthesis extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Parenthesis;
+
+final class TokenClosingParenthesis extends BaseToken implements Parenthesis
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::PARENTHESIS;
}
diff --git a/src/TokenStream/Token/TokenComma.php b/src/TokenStream/Token/TokenComma.php
index ff39217..fc1ce81 100644
--- a/src/TokenStream/Token/TokenComma.php
+++ b/src/TokenStream/Token/TokenComma.php
@@ -3,13 +3,13 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
final class TokenComma extends BaseToken
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::COMMA;
}
diff --git a/src/TokenStream/Token/TokenComment.php b/src/TokenStream/Token/TokenComment.php
index e48c7ff..1866e56 100644
--- a/src/TokenStream/Token/TokenComment.php
+++ b/src/TokenStream/Token/TokenComment.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenComment extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Whitespace;
+
+final class TokenComment extends BaseToken implements Whitespace
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::COMMENT;
}
diff --git a/src/TokenStream/Token/TokenEncapsedString.php b/src/TokenStream/Token/TokenEncapsedString.php
index 738858c..962072d 100644
--- a/src/TokenStream/Token/TokenEncapsedString.php
+++ b/src/TokenStream/Token/TokenEncapsedString.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
diff --git a/src/TokenStream/Token/TokenEqual.php b/src/TokenStream/Token/TokenEqual.php
index 3a2fb64..712da78 100644
--- a/src/TokenStream/Token/TokenEqual.php
+++ b/src/TokenStream/Token/TokenEqual.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenEqual extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenEqual extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenEqualStrict.php b/src/TokenStream/Token/TokenEqualStrict.php
index b60e244..5f6c687 100644
--- a/src/TokenStream/Token/TokenEqualStrict.php
+++ b/src/TokenStream/Token/TokenEqualStrict.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenEqualStrict extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenEqualStrict extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenFactory.php b/src/TokenStream/Token/TokenFactory.php
index 4b7a1be..80e16b9 100644
--- a/src/TokenStream/Token/TokenFactory.php
+++ b/src/TokenStream/Token/TokenFactory.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
@@ -23,46 +23,46 @@ public function createFromPHPType(mixed $value): BaseToken
'double' => new TokenFloat($value),
'object' => new TokenObject($value),
'array' => $this->buildTokenCollection($value),
- default => throw ParserException::unsupportedType(gettype($value))
+ default => throw ParserException::unsupportedType(gettype($value)),
};
}
- /** @throws ParserException */
- public function createFromTokenName(string $tokenName): string
+ public function createFromToken(Token $token, array $matches, int $offset): BaseToken
{
- return match ($tokenName) {
- Token::AND => TokenAnd::class,
- Token::OR => TokenOr::class,
- Token::NOT_EQUAL_STRICT => TokenNotEqualStrict::class,
- Token::NOT_EQUAL => TokenNotEqual::class,
- Token::EQUAL_STRICT => TokenEqualStrict::class,
- Token::EQUAL => TokenEqual::class,
- Token::IN => TokenIn::class,
- Token::NOT_IN => TokenNotIn::class,
- Token::BOOL_TRUE => TokenBoolTrue::class,
- Token::BOOL_FALSE => TokenBoolFalse::class,
- Token::NULL => TokenNull::class,
- Token::METHOD => TokenMethod::class,
- Token::FUNCTION => TokenFunction::class,
- Token::VARIABLE => TokenVariable::class,
- Token::FLOAT => TokenFloat::class,
- Token::INTEGER => TokenInteger::class,
- Token::ENCAPSED_STRING => TokenEncapsedString::class,
- Token::SMALLER_EQUAL => TokenSmallerEqual::class,
- Token::GREATER_EQUAL => TokenGreaterEqual::class,
- Token::SMALLER => TokenSmaller::class,
- Token::GREATER => TokenGreater::class,
- Token::OPENING_PARENTHESIS => TokenOpeningParenthesis::class,
- Token::CLOSING_PARENTHESIS => TokenClosingParenthesis::class,
- Token::OPENING_ARRAY => TokenOpeningArray::class,
- Token::CLOSING_ARRAY => TokenClosingArray::class,
- Token::COMMA => TokenComma::class,
- Token::REGEX => TokenRegex::class,
- Token::COMMENT => TokenComment::class,
- Token::NEWLINE => TokenNewline::class,
- Token::SPACE => TokenSpace::class,
- Token::UNKNOWN => TokenUnknown::class,
- default => throw ParserException::unknownTokenName($tokenName)
+ $args = [$matches[$token->value], $offset];
+
+ return match ($token) {
+ Token::AND => new TokenAnd(...$args),
+ Token::OR => new TokenOr(...$args),
+ Token::NOT_EQUAL_STRICT => new TokenNotEqualStrict(...$args),
+ Token::NOT_EQUAL => new TokenNotEqual(...$args),
+ Token::EQUAL_STRICT => new TokenEqualStrict(...$args),
+ Token::EQUAL => new TokenEqual(...$args),
+ Token::IN => new TokenIn(...$args),
+ Token::NOT_IN => new TokenNotIn(...$args),
+ Token::BOOL_TRUE => new TokenBoolTrue(...$args),
+ Token::BOOL_FALSE => new TokenBoolFalse(...$args),
+ Token::NULL => new TokenNull(...$args),
+ Token::METHOD => new TokenMethod(...$args),
+ Token::FUNCTION => new TokenFunction(...$args),
+ Token::VARIABLE => new TokenVariable(...$args),
+ Token::FLOAT => new TokenFloat(...$args),
+ Token::INTEGER => new TokenInteger(...$args),
+ Token::ENCAPSED_STRING => new TokenEncapsedString(...$args),
+ Token::SMALLER_EQUAL => new TokenSmallerEqual(...$args),
+ Token::GREATER_EQUAL => new TokenGreaterEqual(...$args),
+ Token::SMALLER => new TokenSmaller(...$args),
+ Token::GREATER => new TokenGreater(...$args),
+ Token::OPENING_PARENTHESIS => new TokenOpeningParenthesis(...$args),
+ Token::CLOSING_PARENTHESIS => new TokenClosingParenthesis(...$args),
+ Token::OPENING_ARRAY => new TokenOpeningArray(...$args),
+ Token::CLOSING_ARRAY => new TokenClosingArray(...$args),
+ Token::COMMA => new TokenComma(...$args),
+ Token::REGEX => new TokenRegex(...$args),
+ Token::COMMENT => new TokenComment(...$args),
+ Token::NEWLINE => new TokenNewline(...$args),
+ Token::SPACE => new TokenSpace(...$args),
+ Token::UNKNOWN => new TokenUnknown(...$args),
};
}
diff --git a/src/TokenStream/Token/TokenFloat.php b/src/TokenStream/Token/TokenFloat.php
index 018c92b..eba6bd0 100644
--- a/src/TokenStream/Token/TokenFloat.php
+++ b/src/TokenStream/Token/TokenFloat.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenFloat extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+
+final class TokenFloat extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VALUE;
}
diff --git a/src/TokenStream/Token/TokenFunction.php b/src/TokenStream/Token/TokenFunction.php
index c93fed1..7d27e80 100644
--- a/src/TokenStream/Token/TokenFunction.php
+++ b/src/TokenStream/Token/TokenFunction.php
@@ -3,21 +3,21 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
use nicoSWD\Rule\TokenStream\Node\NodeFunction;
-use nicoSWD\Rule\TokenStream\TokenStream;
+use nicoSWD\Rule\TokenStream\TokenIterator;
final class TokenFunction extends BaseToken
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::FUNCTION;
}
- public function createNode(TokenStream $tokenStream): BaseToken
+ public function createNode(TokenIterator $tokenStream): BaseToken
{
return (new NodeFunction($tokenStream))->getNode();
}
diff --git a/src/TokenStream/Token/TokenGreater.php b/src/TokenStream/Token/TokenGreater.php
index a306b88..07920bb 100644
--- a/src/TokenStream/Token/TokenGreater.php
+++ b/src/TokenStream/Token/TokenGreater.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenGreater extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenGreater extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenGreaterEqual.php b/src/TokenStream/Token/TokenGreaterEqual.php
index faed030..4e01558 100644
--- a/src/TokenStream/Token/TokenGreaterEqual.php
+++ b/src/TokenStream/Token/TokenGreaterEqual.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenGreaterEqual extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenGreaterEqual extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenIn.php b/src/TokenStream/Token/TokenIn.php
index 88334b9..43a2f34 100644
--- a/src/TokenStream/Token/TokenIn.php
+++ b/src/TokenStream/Token/TokenIn.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenIn extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenIn extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenInteger.php b/src/TokenStream/Token/TokenInteger.php
index 45c950e..3f1f281 100644
--- a/src/TokenStream/Token/TokenInteger.php
+++ b/src/TokenStream/Token/TokenInteger.php
@@ -3,15 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenInteger extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+
+final class TokenInteger extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
- return TokenType::INT_VALUE;
+ return TokenType::VALUE;
}
public function getValue(): int
diff --git a/src/TokenStream/Token/TokenMethod.php b/src/TokenStream/Token/TokenMethod.php
index 18c0684..945fe27 100644
--- a/src/TokenStream/Token/TokenMethod.php
+++ b/src/TokenStream/Token/TokenMethod.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenMethod extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Method;
+
+final class TokenMethod extends BaseToken implements Method
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::METHOD;
}
diff --git a/src/TokenStream/Token/TokenNewline.php b/src/TokenStream/Token/TokenNewline.php
index 955ba39..71db1ed 100644
--- a/src/TokenStream/Token/TokenNewline.php
+++ b/src/TokenStream/Token/TokenNewline.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenNewline extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Whitespace;
+
+final class TokenNewline extends BaseToken implements Whitespace
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::SPACE;
}
diff --git a/src/TokenStream/Token/TokenNotEqual.php b/src/TokenStream/Token/TokenNotEqual.php
index 163a1b9..2ec6f8e 100644
--- a/src/TokenStream/Token/TokenNotEqual.php
+++ b/src/TokenStream/Token/TokenNotEqual.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenNotEqual extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenNotEqual extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenNotEqualStrict.php b/src/TokenStream/Token/TokenNotEqualStrict.php
index e913d18..1949e7c 100644
--- a/src/TokenStream/Token/TokenNotEqualStrict.php
+++ b/src/TokenStream/Token/TokenNotEqualStrict.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenNotEqualStrict extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenNotEqualStrict extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenNotIn.php b/src/TokenStream/Token/TokenNotIn.php
index 79a213a..813abef 100644
--- a/src/TokenStream/Token/TokenNotIn.php
+++ b/src/TokenStream/Token/TokenNotIn.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenNotIn extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenNotIn extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenNull.php b/src/TokenStream/Token/TokenNull.php
index 452719c..b8f4dba 100644
--- a/src/TokenStream/Token/TokenNull.php
+++ b/src/TokenStream/Token/TokenNull.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenNull extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+
+final class TokenNull extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VALUE;
}
diff --git a/src/TokenStream/Token/TokenObject.php b/src/TokenStream/Token/TokenObject.php
index c6c3e0a..619c72c 100644
--- a/src/TokenStream/Token/TokenObject.php
+++ b/src/TokenStream/Token/TokenObject.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenObject extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+
+final class TokenObject extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VALUE;
}
diff --git a/src/TokenStream/Token/TokenOpeningArray.php b/src/TokenStream/Token/TokenOpeningArray.php
index b2d5275..991b2a7 100644
--- a/src/TokenStream/Token/TokenOpeningArray.php
+++ b/src/TokenStream/Token/TokenOpeningArray.php
@@ -3,21 +3,21 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
use nicoSWD\Rule\TokenStream\Node\NodeArray;
-use nicoSWD\Rule\TokenStream\TokenStream;
+use nicoSWD\Rule\TokenStream\TokenIterator;
final class TokenOpeningArray extends BaseToken
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::SQUARE_BRACKET;
}
- public function createNode(TokenStream $tokenStream): BaseToken
+ public function createNode(TokenIterator $tokenStream): BaseToken
{
return (new NodeArray($tokenStream))->getNode();
}
diff --git a/src/TokenStream/Token/TokenOpeningParenthesis.php b/src/TokenStream/Token/TokenOpeningParenthesis.php
index a3d4058..f180b46 100644
--- a/src/TokenStream/Token/TokenOpeningParenthesis.php
+++ b/src/TokenStream/Token/TokenOpeningParenthesis.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenOpeningParenthesis extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Parenthesis;
+
+final class TokenOpeningParenthesis extends BaseToken implements Parenthesis
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::PARENTHESIS;
}
diff --git a/src/TokenStream/Token/TokenOr.php b/src/TokenStream/Token/TokenOr.php
index b4dcfdc..8d2c446 100644
--- a/src/TokenStream/Token/TokenOr.php
+++ b/src/TokenStream/Token/TokenOr.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenOr extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Logical;
+
+final class TokenOr extends BaseToken implements Logical
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::LOGICAL;
}
diff --git a/src/TokenStream/Token/TokenRegex.php b/src/TokenStream/Token/TokenRegex.php
index ad93008..c8e2f7c 100644
--- a/src/TokenStream/Token/TokenRegex.php
+++ b/src/TokenStream/Token/TokenRegex.php
@@ -3,21 +3,22 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
use nicoSWD\Rule\TokenStream\Node\NodeString;
-use nicoSWD\Rule\TokenStream\TokenStream;
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+use nicoSWD\Rule\TokenStream\TokenIterator;
-final class TokenRegex extends BaseToken
+final class TokenRegex extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VALUE;
}
- public function createNode(TokenStream $tokenStream): BaseToken
+ public function createNode(TokenIterator $tokenStream): BaseToken
{
return (new NodeString($tokenStream))->getNode();
}
diff --git a/src/TokenStream/Token/TokenSmaller.php b/src/TokenStream/Token/TokenSmaller.php
index 91b7617..9be3dee 100644
--- a/src/TokenStream/Token/TokenSmaller.php
+++ b/src/TokenStream/Token/TokenSmaller.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenSmaller extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenSmaller extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenSmallerEqual.php b/src/TokenStream/Token/TokenSmallerEqual.php
index 045aac7..cf79a31 100644
--- a/src/TokenStream/Token/TokenSmallerEqual.php
+++ b/src/TokenStream/Token/TokenSmallerEqual.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenSmallerEqual extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Operator;
+
+final class TokenSmallerEqual extends BaseToken implements Operator
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::OPERATOR;
}
diff --git a/src/TokenStream/Token/TokenSpace.php b/src/TokenStream/Token/TokenSpace.php
index 170b17b..6e2279c 100644
--- a/src/TokenStream/Token/TokenSpace.php
+++ b/src/TokenStream/Token/TokenSpace.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-final class TokenSpace extends BaseToken
+use nicoSWD\Rule\TokenStream\Token\Type\Whitespace;
+
+final class TokenSpace extends BaseToken implements Whitespace
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::SPACE;
}
diff --git a/src/TokenStream/Token/TokenString.php b/src/TokenStream/Token/TokenString.php
index c320852..cc0459f 100644
--- a/src/TokenStream/Token/TokenString.php
+++ b/src/TokenStream/Token/TokenString.php
@@ -3,21 +3,22 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
use nicoSWD\Rule\TokenStream\Node\NodeString;
-use nicoSWD\Rule\TokenStream\TokenStream;
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+use nicoSWD\Rule\TokenStream\TokenIterator;
-class TokenString extends BaseToken
+class TokenString extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VALUE;
}
- public function createNode(TokenStream $tokenStream): BaseToken
+ public function createNode(TokenIterator $tokenStream): BaseToken
{
return (new NodeString($tokenStream))->getNode();
}
diff --git a/src/TokenStream/Token/TokenType.php b/src/TokenStream/Token/TokenType.php
index 76c79e0..3f58cf5 100644
--- a/src/TokenStream/Token/TokenType.php
+++ b/src/TokenStream/Token/TokenType.php
@@ -3,23 +3,27 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
-class TokenType
+enum TokenType
{
- public const OPERATOR = 1;
- public const INT_VALUE = 2;
- public const VALUE = 4;
- public const LOGICAL = 8;
- public const VARIABLE = 16;
- public const COMMENT = 32;
- public const SPACE = 64;
- public const UNKNOWN = 128;
- public const PARENTHESIS = 256;
- public const SQUARE_BRACKET = 512;
- public const COMMA = 1024;
- public const METHOD = 2048;
- public const FUNCTION = 4098;
+ case OPERATOR;
+ case VALUE;
+ case LOGICAL;
+ case VARIABLE;
+ case COMMENT;
+ case SPACE;
+ case UNKNOWN;
+ case PARENTHESIS;
+ case SQUARE_BRACKET;
+ case COMMA;
+ case METHOD;
+ case FUNCTION;
+
+ public static function isValue(BaseToken $token): bool
+ {
+ return $token->getType() === self::VALUE;
+ }
}
diff --git a/src/TokenStream/Token/TokenUnknown.php b/src/TokenStream/Token/TokenUnknown.php
index f2747b5..367ad21 100644
--- a/src/TokenStream/Token/TokenUnknown.php
+++ b/src/TokenStream/Token/TokenUnknown.php
@@ -3,13 +3,13 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
final class TokenUnknown extends BaseToken
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::UNKNOWN;
}
diff --git a/src/TokenStream/Token/TokenVariable.php b/src/TokenStream/Token/TokenVariable.php
index 6a6b0f1..f390a38 100644
--- a/src/TokenStream/Token/TokenVariable.php
+++ b/src/TokenStream/Token/TokenVariable.php
@@ -3,21 +3,22 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream\Token;
use nicoSWD\Rule\TokenStream\Node\NodeVariable;
-use nicoSWD\Rule\TokenStream\TokenStream;
+use nicoSWD\Rule\TokenStream\Token\Type\Value;
+use nicoSWD\Rule\TokenStream\TokenIterator;
-final class TokenVariable extends BaseToken
+final class TokenVariable extends BaseToken implements Value
{
- public function getType(): int
+ public function getType(): TokenType
{
return TokenType::VARIABLE;
}
- public function createNode(TokenStream $tokenStream): BaseToken
+ public function createNode(TokenIterator $tokenStream): BaseToken
{
return (new NodeVariable($tokenStream))->getNode();
}
diff --git a/src/TokenStream/Token/Type/Logical.php b/src/TokenStream/Token/Type/Logical.php
new file mode 100644
index 0000000..aa49492
--- /dev/null
+++ b/src/TokenStream/Token/Type/Logical.php
@@ -0,0 +1,12 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream\Token\Type;
+
+interface Logical
+{
+}
diff --git a/src/TokenStream/Token/Type/Method.php b/src/TokenStream/Token/Type/Method.php
new file mode 100644
index 0000000..dabe45a
--- /dev/null
+++ b/src/TokenStream/Token/Type/Method.php
@@ -0,0 +1,12 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream\Token\Type;
+
+interface Method
+{
+}
diff --git a/src/TokenStream/Token/Type/Operator.php b/src/TokenStream/Token/Type/Operator.php
new file mode 100644
index 0000000..ca1667f
--- /dev/null
+++ b/src/TokenStream/Token/Type/Operator.php
@@ -0,0 +1,12 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream\Token\Type;
+
+interface Operator
+{
+}
diff --git a/src/TokenStream/Token/Type/Parenthesis.php b/src/TokenStream/Token/Type/Parenthesis.php
new file mode 100644
index 0000000..865a064
--- /dev/null
+++ b/src/TokenStream/Token/Type/Parenthesis.php
@@ -0,0 +1,12 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream\Token\Type;
+
+interface Parenthesis
+{
+}
diff --git a/src/TokenStream/Token/Type/Value.php b/src/TokenStream/Token/Type/Value.php
new file mode 100644
index 0000000..54d7888
--- /dev/null
+++ b/src/TokenStream/Token/Type/Value.php
@@ -0,0 +1,12 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream\Token\Type;
+
+interface Value
+{
+}
diff --git a/src/TokenStream/Token/Type/Whitespace.php b/src/TokenStream/Token/Type/Whitespace.php
new file mode 100644
index 0000000..64bb32a
--- /dev/null
+++ b/src/TokenStream/Token/Type/Whitespace.php
@@ -0,0 +1,12 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream\Token\Type;
+
+interface Whitespace
+{
+}
diff --git a/src/TokenStream/TokenCollection.php b/src/TokenStream/TokenCollection.php
index 4fe6d56..1ba867e 100644
--- a/src/TokenStream/TokenCollection.php
+++ b/src/TokenStream/TokenCollection.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream;
diff --git a/src/TokenStream/TokenIterator.php b/src/TokenStream/TokenIterator.php
new file mode 100644
index 0000000..71e5f60
--- /dev/null
+++ b/src/TokenStream/TokenIterator.php
@@ -0,0 +1,92 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream;
+
+use Closure;
+use Iterator;
+use nicoSWD\Rule\Parser\Exception\ParserException;
+use nicoSWD\Rule\Grammar\CallableUserFunctionInterface;
+use nicoSWD\Rule\TokenStream\Token\BaseToken;
+
+readonly class TokenIterator implements Iterator
+{
+ public function __construct(
+ private Iterator $stack,
+ private TokenStream $tokenStream,
+ ) {
+ }
+
+ public function next(): void
+ {
+ $this->stack->next();
+ }
+
+ public function valid(): bool
+ {
+ return $this->stack->valid();
+ }
+
+ /** @throws ParserException */
+ public function current(): BaseToken
+ {
+ return $this->getCurrentToken()->createNode($this);
+ }
+
+ public function key(): int
+ {
+ return $this->stack->key();
+ }
+
+ public function rewind(): void
+ {
+ $this->stack->rewind();
+ }
+
+ /** @return Iterator */
+ public function getStack(): Iterator
+ {
+ return $this->stack;
+ }
+
+ private function getCurrentToken(): BaseToken
+ {
+ return $this->stack->current();
+ }
+
+ /** @throws ParserException */
+ public function getVariable(string $variableName): BaseToken
+ {
+ try {
+ return $this->tokenStream->getVariable($variableName);
+ } catch (Exception\UndefinedVariableException) {
+ throw ParserException::undefinedVariable($variableName, $this->getCurrentToken());
+ }
+ }
+
+ /** @throws ParserException */
+ public function getFunction(string $functionName): Closure
+ {
+ try {
+ return $this->tokenStream->getFunction($functionName);
+ } catch (Exception\UndefinedFunctionException) {
+ throw ParserException::undefinedFunction($functionName, $this->getCurrentToken());
+ }
+ }
+
+ /** @throws ParserException */
+ public function getMethod(string $methodName, BaseToken $token): CallableUserFunctionInterface
+ {
+ try {
+ return $this->tokenStream->getMethod($methodName, $token);
+ } catch (Exception\UndefinedMethodException) {
+ throw ParserException::undefinedMethod($methodName, $this->getCurrentToken());
+ } catch (Exception\ForbiddenMethodException) {
+ throw ParserException::forbiddenMethod($methodName, $this->getCurrentToken());
+ }
+ }
+}
diff --git a/src/TokenStream/TokenIteratorFactory.php b/src/TokenStream/TokenIteratorFactory.php
new file mode 100644
index 0000000..18c6dc8
--- /dev/null
+++ b/src/TokenStream/TokenIteratorFactory.php
@@ -0,0 +1,18 @@
+
+ */
+namespace nicoSWD\Rule\TokenStream;
+
+use Iterator;
+
+final class TokenIteratorFactory
+{
+ public function create(Iterator $stack, TokenStream $tokenStream): TokenIterator
+ {
+ return new TokenIterator($stack, $tokenStream);
+ }
+}
diff --git a/src/TokenStream/TokenStream.php b/src/TokenStream/TokenStream.php
index 14ba919..d00dcca 100644
--- a/src/TokenStream/TokenStream.php
+++ b/src/TokenStream/TokenStream.php
@@ -3,90 +3,136 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\TokenStream;
-use ArrayIterator;
use Closure;
-use nicoSWD\Rule\Parser\Exception\ParserException;
+use InvalidArgumentException;
use nicoSWD\Rule\Grammar\CallableUserFunctionInterface;
+use nicoSWD\Rule\Parser\Exception\ParserException;
+use nicoSWD\Rule\TokenStream\Exception\UndefinedVariableException;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
+use nicoSWD\Rule\TokenStream\Token\TokenFactory;
+use nicoSWD\Rule\Tokenizer\TokenizerInterface;
+use nicoSWD\Rule\TokenStream\Token\TokenObject;
-class TokenStream extends ArrayIterator
+class TokenStream
{
+ private array $functions = [];
+ private array $methods = [];
+ private array $variables = [];
+
public function __construct(
- private ArrayIterator $stack,
- private AST $ast
+ private readonly TokenizerInterface $tokenizer,
+ private readonly TokenFactory $tokenFactory,
+ private readonly TokenIteratorFactory $tokenIteratorFactory,
+ private readonly CallableUserMethodFactoryInterface $userMethodFactory,
) {
}
- public function next(): void
+ public function getStream(string $rule): TokenIterator
{
- $this->stack->next();
+ return $this->tokenIteratorFactory->create($this->tokenizer->tokenize($rule), $this);
}
- public function valid(): bool
+ /**
+ * @throws Exception\UndefinedMethodException
+ * @throws Exception\ForbiddenMethodException
+ */
+ public function getMethod(string $methodName, BaseToken $token): CallableUserFunctionInterface
{
- return $this->stack->valid();
+ if ($token instanceof TokenObject) {
+ return $this->getCallableUserMethod($token, $methodName);
+ }
+
+ if (empty($this->methods)) {
+ $this->registerMethods();
+ }
+
+ if (!isset($this->methods[$methodName])) {
+ throw new Exception\UndefinedMethodException();
+ }
+
+ return new $this->methods[$methodName]($token);
}
- /** @throws ParserException */
- public function current(): BaseToken
+ public function setVariables(array $variables): void
{
- return $this->getCurrentToken()->createNode($this);
+ $this->variables = $variables;
}
- public function key(): int
+ /**
+ * @throws UndefinedVariableException
+ * @throws ParserException
+ */
+ public function getVariable(string $variableName): BaseToken
{
- return $this->stack->key();
+ if (!$this->variableExists($variableName)) {
+ throw new UndefinedVariableException($variableName);
+ }
+
+ return $this->tokenFactory->createFromPHPType($this->variables[$variableName]);
}
- public function rewind(): void
+ public function variableExists(string $variableName): bool
{
- $this->stack->rewind();
+ return array_key_exists($variableName, $this->variables);
}
- /** @return ArrayIterator */
- public function getStack(): ArrayIterator
+ /** @throws Exception\UndefinedFunctionException */
+ public function getFunction(string $functionName): Closure
{
- return $this->stack;
+ if (empty($this->functions)) {
+ $this->registerFunctions();
+ }
+
+ if (!isset($this->functions[$functionName])) {
+ throw new Exception\UndefinedFunctionException($functionName);
+ }
+
+ return $this->functions[$functionName];
}
- private function getCurrentToken(): BaseToken
+ private function registerMethods(): void
{
- return $this->stack->current();
+ foreach ($this->tokenizer->grammar->getInternalMethods() as $internalMethod) {
+ $this->methods[$internalMethod->name] = $internalMethod->class;
+ }
}
- /** @throws ParserException */
- public function getVariable(string $variableName): BaseToken
+ private function registerFunctions(): void
{
- try {
- return $this->ast->getVariable($variableName);
- } catch (Exception\UndefinedVariableException) {
- throw ParserException::undefinedVariable($variableName, $this->getCurrentToken());
+ foreach ($this->tokenizer->grammar->getInternalFunctions() as $function) {
+ $this->registerFunctionClass($function->name, $function->class);
}
}
- /** @throws ParserException */
- public function getFunction(string $functionName): Closure
+ private function registerFunctionClass(string $functionName, string $className): void
{
- try {
- return $this->ast->getFunction($functionName);
- } catch (Exception\UndefinedFunctionException) {
- throw ParserException::undefinedFunction($functionName, $this->getCurrentToken());
- }
+ $this->functions[$functionName] = function (?BaseToken ...$args) use ($className) {
+ $function = new $className();
+
+ if (!$function instanceof CallableUserFunctionInterface) {
+ throw new InvalidArgumentException(
+ sprintf(
+ '%s must be an instance of %s',
+ $className,
+ CallableUserFunctionInterface::class
+ )
+ );
+ }
+
+ return $function->call(...$args);
+ };
}
- /** @throws ParserException */
- public function getMethod(string $methodName, BaseToken $token): CallableUserFunctionInterface
+ /**
+ * @throws Exception\ForbiddenMethodException
+ * @throws Exception\UndefinedMethodException
+ */
+ private function getCallableUserMethod(BaseToken $token, string $methodName): CallableUserFunctionInterface
{
- try {
- return $this->ast->getMethod($methodName, $token);
- } catch (Exception\UndefinedMethodException) {
- throw ParserException::undefinedMethod($methodName, $this->getCurrentToken());
- } catch (Exception\ForbiddenMethodException) {
- throw ParserException::forbiddenMethod($methodName, $this->getCurrentToken());
- }
+ return $this->userMethodFactory->create($token, $this->tokenFactory, $methodName);
}
}
diff --git a/src/TokenStream/TokenStreamFactory.php b/src/TokenStream/TokenStreamFactory.php
deleted file mode 100644
index 1a1db0b..0000000
--- a/src/TokenStream/TokenStreamFactory.php
+++ /dev/null
@@ -1,18 +0,0 @@
-
- */
-namespace nicoSWD\Rule\TokenStream;
-
-use ArrayIterator;
-
-class TokenStreamFactory
-{
- public function create(ArrayIterator $stack, AST $ast): TokenStream
- {
- return new TokenStream($stack, $ast);
- }
-}
diff --git a/src/Tokenizer/Tokenizer.php b/src/Tokenizer/Tokenizer.php
index 702394c..fe2af69 100644
--- a/src/Tokenizer/Tokenizer.php
+++ b/src/Tokenizer/Tokenizer.php
@@ -3,97 +3,47 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Tokenizer;
use ArrayIterator;
+use Iterator;
use nicoSWD\Rule\Grammar\Grammar;
+use nicoSWD\Rule\TokenStream\Token\Token;
use nicoSWD\Rule\TokenStream\Token\TokenFactory;
-use SplPriorityQueue;
-final class Tokenizer implements TokenizerInterface
+final class Tokenizer extends TokenizerInterface
{
- private array $tokens = [];
- private string $compiledRegex = '';
-
public function __construct(
- private Grammar $grammar,
- private TokenFactory $tokenFactory
+ public Grammar $grammar,
+ private readonly TokenFactory $tokenFactory,
) {
- foreach ($grammar->getDefinition() as [$class, $regex, $priority]) {
- $this->registerToken($class, $regex, $priority);
- }
}
- public function tokenize(string $string): ArrayIterator
+ public function tokenize(string $string): Iterator
{
- $regex = $this->getRegex();
+ $regex = $this->grammar->buildRegex();
$stack = [];
$offset = 0;
- while (preg_match($regex, $string, $matches, 0, $offset)) {
+ while (preg_match($regex, $string, $matches, offset: $offset)) {
$token = $this->getMatchedToken($matches);
- $className = $this->tokenFactory->createFromTokenName($token);
-
- $stack[] = new $className($matches[$token], $offset);
+ $stack[] = $this->tokenFactory->createFromToken($token, $matches, $offset);
$offset += strlen($matches[0]);
}
return new ArrayIterator($stack);
}
- public function getGrammar(): Grammar
- {
- return $this->grammar;
- }
-
- private function registerToken(string $class, string $regex, int $priority): void
- {
- $this->tokens[$class] = new class($class, $regex, $priority) {
- public function __construct(
- public string $class,
- public string $regex,
- public int $priority
- ) {
- }
- };
- }
-
- private function getMatchedToken(array $matches): string
+ private function getMatchedToken(array $matches): Token
{
foreach ($matches as $key => $value) {
if ($value !== '' && !is_int($key)) {
- return $key;
- }
- }
-
- return 'Unknown';
- }
-
- private function getRegex(): string
- {
- if (!$this->compiledRegex) {
- $regex = [];
-
- foreach ($this->getQueue() as $token) {
- $regex[] = "(?<$token->class>$token->regex)";
+ return Token::from($key);
}
-
- $this->compiledRegex = '~(' . implode('|', $regex) . ')~As';
- }
-
- return $this->compiledRegex;
- }
-
- private function getQueue(): SplPriorityQueue
- {
- $queue = new SplPriorityQueue();
-
- foreach ($this->tokens as $class) {
- $queue->insert($class, $class->priority);
}
- return $queue;
+ return Token::UNKNOWN;
}
}
diff --git a/src/Tokenizer/TokenizerInterface.php b/src/Tokenizer/TokenizerInterface.php
index e49b05d..c53f5da 100644
--- a/src/Tokenizer/TokenizerInterface.php
+++ b/src/Tokenizer/TokenizerInterface.php
@@ -1,20 +1,23 @@
-
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\Tokenizer;
-use ArrayIterator;
+use Iterator;
use nicoSWD\Rule\Grammar\Grammar;
use nicoSWD\Rule\TokenStream\Token\BaseToken;
-interface TokenizerInterface
+abstract class TokenizerInterface
{
- /** @return ArrayIterator */
- public function tokenize(string $string): ArrayIterator;
+ public Grammar $grammar;
- public function getGrammar(): Grammar;
+ /**
+ * @param string $string
+ * @return Iterator
+ */
+ abstract public function tokenize(string $string): Iterator;
}
diff --git a/src/container.php b/src/container.php
index c356af5..7bf78c7 100644
--- a/src/container.php
+++ b/src/container.php
@@ -3,27 +3,27 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule;
use nicoSWD\Rule\Grammar\JavaScript\JavaScript;
-use nicoSWD\Rule\TokenStream\AST;
+use nicoSWD\Rule\Parser\EvaluatableExpressionFactory;
+use nicoSWD\Rule\TokenStream\TokenStream;
use nicoSWD\Rule\Compiler\CompilerFactory;
use nicoSWD\Rule\Evaluator\Evaluator;
use nicoSWD\Rule\Evaluator\EvaluatorInterface;
-use nicoSWD\Rule\Expression\ExpressionFactory;
use nicoSWD\Rule\Tokenizer\Tokenizer;
use nicoSWD\Rule\TokenStream\Token\TokenFactory;
-use nicoSWD\Rule\TokenStream\TokenStreamFactory;
+use nicoSWD\Rule\TokenStream\TokenIteratorFactory;
use nicoSWD\Rule\TokenStream\CallableUserMethodFactory;
return new class {
- private static TokenStreamFactory $tokenStreamFactory;
+ private static TokenIteratorFactory $tokenStreamFactory;
private static TokenFactory $tokenFactory;
private static CompilerFactory $compiler;
private static JavaScript $javaScript;
- private static ExpressionFactory $expressionFactory;
+ private static EvaluatableExpressionFactory $expressionFactory;
private static CallableUserMethodFactory $userMethodFactory;
private static Tokenizer $tokenizer;
private static Evaluator $evaluator;
@@ -64,12 +64,12 @@ private static function compiler(): CompilerFactory
return self::$compiler;
}
- private static function ast(array $variables): AST
+ private static function ast(array $variables): TokenStream
{
- $ast = new AST(self::tokenizer(), self::tokenFactory(), self::tokenStreamFactory(), self::userMethodFactory());
- $ast->setVariables($variables);
+ $tokenStream = new TokenStream(self::tokenizer(), self::tokenFactory(), self::tokenStreamFactory(), self::userMethodFactory());
+ $tokenStream->setVariables($variables);
- return $ast;
+ return $tokenStream;
}
private static function tokenizer(): Tokenizer
@@ -90,19 +90,19 @@ private static function javascript(): JavaScript
return self::$javaScript;
}
- private static function tokenStreamFactory(): TokenStreamFactory
+ private static function tokenStreamFactory(): TokenIteratorFactory
{
if (!isset(self::$tokenStreamFactory)) {
- self::$tokenStreamFactory = new TokenStreamFactory();
+ self::$tokenStreamFactory = new TokenIteratorFactory();
}
return self::$tokenStreamFactory;
}
- private static function expressionFactory(): ExpressionFactory
+ private static function expressionFactory(): EvaluatableExpressionFactory
{
if (!isset(self::$expressionFactory)) {
- self::$expressionFactory = new ExpressionFactory();
+ self::$expressionFactory = new EvaluatableExpressionFactory();
}
return self::$expressionFactory;
diff --git a/tests/integration/AbstractTestBase.php b/tests/integration/AbstractTestBase.php
index 30d07a7..74cc63c 100755
--- a/tests/integration/AbstractTestBase.php
+++ b/tests/integration/AbstractTestBase.php
@@ -3,7 +3,7 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration;
diff --git a/tests/integration/HighlighterTest.php b/tests/integration/HighlighterTest.php
index 3f44e1a..c996899 100755
--- a/tests/integration/HighlighterTest.php
+++ b/tests/integration/HighlighterTest.php
@@ -3,17 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration;
-use Exception;
use nicoSWD\Rule;
use nicoSWD\Rule\Grammar\JavaScript\JavaScript;
use nicoSWD\Rule\Highlighter\Highlighter;
use nicoSWD\Rule\Tokenizer\Tokenizer;
use nicoSWD\Rule\TokenStream\Token\TokenFactory;
use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\Attributes\Test;
final class HighlighterTest extends TestCase
{
@@ -24,7 +24,7 @@ protected function setUp(): void
$this->highlighter = new Highlighter(new Tokenizer(new JavaScript(), new TokenFactory()));
}
- /** @test */
+ #[Test]
public function givenAStyleForATokenGroupItShouldBeUsed(): void
{
$this->highlighter->setStyle(
@@ -36,16 +36,4 @@ public function givenAStyleForATokenGroupItShouldBeUsed(): void
$this->assertStringContainsString('[', $code);
}
-
- /** @test */
- public function invalidGroupThrowsException(): void
- {
- $this->expectException(Exception::class);
- $this->expectExceptionMessage('Invalid group');
-
- $this->highlighter->setStyle(
- 99,
- 'color: test-color;'
- );
- }
}
diff --git a/tests/integration/ObjectTest.php b/tests/integration/ObjectTest.php
index f4c7cb1..0fef937 100755
--- a/tests/integration/ObjectTest.php
+++ b/tests/integration/ObjectTest.php
@@ -3,16 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration;
use nicoSWD\Rule\Parser\Exception\ParserException;
use nicoSWD\Rule\Rule;
+use PHPUnit\Framework\Attributes\Test;
final class ObjectTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function givenAnObjectHasMethodsWhenPublicTheyShouldBeAccessible(): void
{
$myObj = new class {
@@ -40,7 +41,7 @@ public function cat()
$this->assertTrue($this->evaluate('my_obj.test2().cat() === "meow"', $variables));
}
- /** @test */
+ #[Test]
public function givenAnObjectHasPropertiesWhenPublicTheyShouldBeAccessible(): void
{
$myObj = new class {
@@ -54,7 +55,7 @@ public function givenAnObjectHasPropertiesWhenPublicTheyShouldBeAccessible(): vo
$this->assertTrue($this->evaluate('my_obj.test() === "my string"', $variables));
}
- /** @test */
+ #[Test]
public function publicMethodsShouldBeAccessibleMagicallyViaGet(): void
{
$myObj = new class {
@@ -71,7 +72,7 @@ public function getString()
$this->assertTrue($this->evaluate('my_obj.string() === "some string"', $variables));
}
- /** @test */
+ #[Test]
public function publicMethodsShouldBeAccessibleMagicallyViaIs(): void
{
$myObj = new class {
@@ -93,7 +94,7 @@ public function yes()
$this->assertTrue($this->evaluate('my_obj.string(my_obj.yes()) === "yes"', $variables));
}
- /** @test */
+ #[Test]
public function givenAnObjectWhenMagicMethodCallIsAvailableItShouldBeAccessible(): void
{
$myObj = new class {
@@ -129,7 +130,7 @@ public function givenAnObjectWhenMagicMethodsAreCalledDirectlyItShouldThrowAnExc
$this->evaluate("my_obj.{$magicMethod}()", $variables);
}
- /** @test */
+ #[Test]
public function undefinedMethodsShouldThrowAnError(): void
{
$myObj = new class() {
@@ -145,7 +146,7 @@ public function undefinedMethodsShouldThrowAnError(): void
$this->assertSame('Undefined method "nope" at position 6', $rule->getError());
}
- /** @test */
+ #[Test]
public function givenAnObjectWithMagicMethodGetWhenPropertyDoesNotExistItShouldNotBeCalled(): void
{
$myObj = new class {
diff --git a/tests/integration/ParserTest.php b/tests/integration/ParserTest.php
index 609678e..f6eca61 100755
--- a/tests/integration/ParserTest.php
+++ b/tests/integration/ParserTest.php
@@ -3,13 +3,15 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration;
+use PHPUnit\Framework\Attributes\Test;
+
final class ParserTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function multipleAnds(): void
{
$rule = 'foo=="MA" && bar=="EGP" && baz>50000';
@@ -37,7 +39,7 @@ public function multipleAnds(): void
]));
}
- /** @test */
+ #[Test]
public function mixedOrsAndAnds(): void
{
$rule = '
@@ -53,14 +55,14 @@ public function mixedOrsAndAnds(): void
]));
}
- /** @test */
+ #[Test]
public function emptyOrIncompleteRuleReturnsFalse(): void
{
$rule = '';
$this->assertFalse($this->evaluate($rule));
}
- /** @test */
+ #[Test]
public function freakingLongRule(): void
{
$rule = '
@@ -87,7 +89,7 @@ public function freakingLongRule(): void
]));
}
- /** @test */
+ #[Test]
public function negativeComparison(): void
{
$rule = '
@@ -107,7 +109,7 @@ public function negativeComparison(): void
]));
}
- /** @test */
+ #[Test]
public function spacesBetweenStuff(): void
{
$rule = 'foo != 3
@@ -120,7 +122,7 @@ public function spacesBetweenStuff(): void
$this->assertTrue($this->evaluate($rule, ['foo' => '-1']));
}
- /** @test */
+ #[Test]
public function singleLineCommentDoesNotKillTheRest(): void
{
$rule = ' 2 > 3
diff --git a/tests/integration/RuleTest.php b/tests/integration/RuleTest.php
index 29f741d..156d1ba 100755
--- a/tests/integration/RuleTest.php
+++ b/tests/integration/RuleTest.php
@@ -3,16 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration;
use nicoSWD\Rule;
use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\Attributes\Test;
final class RuleTest extends TestCase
{
- /** @test */
+ #[Test]
public function basicRuleWithCommentsEvaluatesCorrectly(): void
{
$string = '
@@ -39,7 +40,7 @@ public function basicRuleWithCommentsEvaluatesCorrectly(): void
$this->assertTrue(!$rule->isFalse());
}
- /** @test */
+ #[Test]
public function isValidReturnsFalseOnInvalidSyntax(): void
{
$ruleStr = '(2 == 2) && (1 < 3 && 3 > 2 (1 == 1))';
@@ -50,7 +51,7 @@ public function isValidReturnsFalseOnInvalidSyntax(): void
$this->assertSame('Unexpected "(" at position 28', $rule->getError());
}
- /** @test */
+ #[Test]
public function isValidReturnsTrueOnValidSyntax(): void
{
$ruleStr = '(2 == 2) && (1 < 3 && 3 > 2 || (1 == 1))';
@@ -61,7 +62,7 @@ public function isValidReturnsTrueOnValidSyntax(): void
$this->assertEmpty($rule->getError());
$this->assertTrue($rule->isTrue());
}
- /** @test */
+ #[Test]
public function basicInRule(): void
{
$ruleStr = '4 in [4, 6, 7]';
@@ -81,7 +82,7 @@ public function basicInRule(): void
$this->assertFalse($rule->isTrue());
}
- /** @test */
+ #[Test]
public function basicNotInRule(): void
{
$ruleStr = '5 not
diff --git a/tests/integration/SyntaxErrorTest.php b/tests/integration/SyntaxErrorTest.php
index 62b8572..f4fae9f 100755
--- a/tests/integration/SyntaxErrorTest.php
+++ b/tests/integration/SyntaxErrorTest.php
@@ -3,18 +3,19 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration;
use nicoSWD\Rule\Rule;
+use PHPUnit\Framework\Attributes\Test;
/**
* @SuppressWarnings(PHPMD.TooManyMethods)
*/
final class SyntaxErrorTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function emptyParenthesisThrowException(): void
{
$rule = new Rule('(totalamount != 3) ()', [
@@ -25,7 +26,7 @@ public function emptyParenthesisThrowException(): void
$this->assertSame('Unexpected "(" at position 19', $rule->getError());
}
- /** @test */
+ #[Test]
public function doubleOperatorThrowsException(): void
{
$rule = new Rule('country == == "venezuela"', ['country' => 'spain']);
@@ -34,7 +35,7 @@ public function doubleOperatorThrowsException(): void
$this->assertSame('Unexpected "==" at position 11', $rule->getError());
}
- /** @test */
+ #[Test]
public function missingLeftValueThrowsException(): void
{
$rule = new Rule('== "venezuela"');
@@ -43,7 +44,7 @@ public function missingLeftValueThrowsException(): void
$this->assertSame('Incomplete expression for token "=="', $rule->getError());
}
- /** @test */
+ #[Test]
public function missingOperatorThrowsException(): void
{
$rule = new Rule('total == -1 total > 10', ['total' => 12]);
@@ -52,7 +53,7 @@ public function missingOperatorThrowsException(): void
$this->assertSame('Missing operator', $rule->getError());
}
- /** @test */
+ #[Test]
public function missingOpeningParenthesisThrowsException(): void
{
$rule = new Rule('1 == 1)');
@@ -61,7 +62,7 @@ public function missingOpeningParenthesisThrowsException(): void
$this->assertSame('Missing opening parenthesis', $rule->getError());
}
- /** @test */
+ #[Test]
public function missingClosingParenthesisThrowsException(): void
{
$rule = new Rule('(1 == 1');
@@ -70,7 +71,7 @@ public function missingClosingParenthesisThrowsException(): void
$this->assertSame('Missing closing parenthesis', $rule->getError());
}
- /** @test */
+ #[Test]
public function misplacedMinusThrowsException(): void
{
$rule = new Rule('1 == 1 && -foo == 1', ['foo' => 1]);
@@ -79,7 +80,7 @@ public function misplacedMinusThrowsException(): void
$this->assertSame('Unknown token "-" at position 10', $rule->getError());
}
- /** @test */
+ #[Test]
public function undefinedVariableThrowsException(): void
{
$rule = new Rule(' // new line on purpose
@@ -89,7 +90,7 @@ public function undefinedVariableThrowsException(): void
$this->assertSame('Undefined variable "foo" at position 36', $rule->getError());
}
- /** @test */
+ #[Test]
public function incompleteExpressionExceptionIsThrownCorrectly(): void
{
$rule = new Rule('1 == 1 && country', ['country' => 'es']);
@@ -98,7 +99,7 @@ public function incompleteExpressionExceptionIsThrownCorrectly(): void
$this->assertSame('Incomplete condition', $rule->getError());
}
- /** @test */
+ #[Test]
public function rulesEvaluatesTrueThrowsExceptionsForUndefinedVars(): void
{
$rule = new Rule('nonono=="MA"');
@@ -107,7 +108,7 @@ public function rulesEvaluatesTrueThrowsExceptionsForUndefinedVars(): void
$this->assertSame('Undefined variable "nonono" at position 0', $rule->getError());
}
- /** @test */
+ #[Test]
public function rulesEvaluatesTrueThrowsExceptionsOnSyntaxErrors(): void
{
$rule = new Rule('country == "MA" &&', ['country' => 'es']);
@@ -116,7 +117,7 @@ public function rulesEvaluatesTrueThrowsExceptionsOnSyntaxErrors(): void
$this->assertSame('Incomplete condition', $rule->getError());
}
- /** @test */
+ #[Test]
public function multipleLogicalTokensThrowException(): void
{
$rule = new Rule('country == "MA" && &&', ['country' => 'es']);
@@ -125,7 +126,7 @@ public function multipleLogicalTokensThrowException(): void
$this->assertSame('Unexpected "&&" at position 19', $rule->getError());
}
- /** @test */
+ #[Test]
public function unknownTokenExceptionIsThrown(): void
{
$rule = new Rule('country == "MA" ^', ['country' => 'es']);
diff --git a/tests/integration/TokenizerTest.php b/tests/integration/TokenizerTest.php
index 614e031..0643342 100755
--- a/tests/integration/TokenizerTest.php
+++ b/tests/integration/TokenizerTest.php
@@ -3,14 +3,16 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration;
use nicoSWD\Rule\Grammar\JavaScript\JavaScript;
use nicoSWD\Rule\Tokenizer\Tokenizer;
+use nicoSWD\Rule\TokenStream\Token\Token;
use nicoSWD\Rule\TokenStream\Token\TokenFactory;
use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\Attributes\Test;
use ReflectionMethod;
final class TokenizerTest extends TestCase
@@ -22,17 +24,16 @@ protected function setUp(): void
$this->tokenizer = new Tokenizer(new JavaScript(), new TokenFactory());
}
- /** @test */
+ #[Test]
public function getMatchedTokenReturnsFalseOnFailure(): void
{
$reflection = new ReflectionMethod($this->tokenizer, 'getMatchedToken');
- $reflection->setAccessible(true);
$result = $reflection->invoke($this->tokenizer, []);
- $this->assertSame('Unknown', $result);
+ $this->assertSame(Token::UNKNOWN, $result);
}
- /** @test */
+ #[Test]
public function tokenPositionAndLineAreCorrect(): void
{
$tokens = $this->tokenizer->tokenize('1');
diff --git a/tests/integration/arrays/ArraysTest.php b/tests/integration/arrays/ArraysTest.php
index 4409d10..e7c8a23 100755
--- a/tests/integration/arrays/ArraysTest.php
+++ b/tests/integration/arrays/ArraysTest.php
@@ -3,16 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\arrays;
use nicoSWD\Rule\Rule;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class ArraysTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function arraysEqualUserSuppliedArrays(): void
{
$this->assertTrue($this->evaluate(
@@ -26,20 +27,20 @@ public function arraysEqualUserSuppliedArrays(): void
]));
}
- /** @test */
+ #[Test]
public function emptyArrayDoesParseCorrectly(): void
{
$this->assertTrue($this->evaluate('[] === []'));
}
- /** @test */
+ #[Test]
public function literalArrayComparison(): void
{
$this->assertTrue($this->evaluate('[123, 12] === [123, 12]'));
$this->assertFalse($this->evaluate('[123, 12] === [123, 12, 1]'));
}
- /** @test */
+ #[Test]
public function commentsAreIgnoredInArray(): void
{
$this->assertTrue($this->evaluate(
@@ -51,7 +52,7 @@ public function commentsAreIgnoredInArray(): void
));
}
- /** @test */
+ #[Test]
public function trailingCommaThrowsException(): void
{
$rule = new Rule('["foo", "bar", ] === ["foo", "bar"]');
@@ -60,7 +61,7 @@ public function trailingCommaThrowsException(): void
$this->assertSame('Unexpected "," at position 15', $rule->getError());
}
- /** @test */
+ #[Test]
public function lineIsReportedCorrectlyOnSyntaxError2(): void
{
$rule = new Rule('["foo", "bar", ,] === ["foo", "bar"]');
@@ -69,7 +70,7 @@ public function lineIsReportedCorrectlyOnSyntaxError2(): void
$this->assertSame('Unexpected "," at position 15', $rule->getError());
}
- /** @test */
+ #[Test]
public function missingCommaThrowsException(): void
{
$rule = new Rule('["foo" "bar"] === ["foo", "bar"]');
@@ -78,7 +79,7 @@ public function missingCommaThrowsException(): void
$this->assertSame('Unexpected "bar" at position 8', $rule->getError());
}
- /** @test */
+ #[Test]
public function unexpectedTokenThrowsException(): void
{
$rule = new Rule('["foo", ===] === ["foo", "bar"]');
@@ -87,7 +88,7 @@ public function unexpectedTokenThrowsException(): void
$this->assertSame('Unexpected "===" at position 8', $rule->getError());
}
- /** @test */
+ #[Test]
public function unexpectedEndOfStringThrowsException(): void
{
$rule = new Rule('["foo", "bar"');
diff --git a/tests/integration/functions/ParseFloatTest.php b/tests/integration/functions/ParseFloatTest.php
index eae6c70..4a9c396 100755
--- a/tests/integration/functions/ParseFloatTest.php
+++ b/tests/integration/functions/ParseFloatTest.php
@@ -3,40 +3,41 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\functions;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class ParseFloatTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function onStringLiteral(): void
{
$this->assertTrue($this->evaluate('parseFloat("3.1337") === 3.1337'));
}
- /** @test */
+ #[Test]
public function onStringLiteralWithSpaces(): void
{
$this->assertTrue($this->evaluate('parseFloat(" 3.1 ") === 3.1'));
}
- /** @test */
+ #[Test]
public function onStringLiteralWithNonNumericChars(): void
{
$this->assertTrue($this->evaluate('parseFloat("3.12aaa") === 3.12'));
}
- /** @test */
+ #[Test]
public function onUserDefinedVariable(): void
{
$this->assertTrue($this->evaluate('parseFloat(foo) === 3.4', ['foo' => '3.4']));
$this->assertFalse($this->evaluate('parseFloat(foo) === "3.5"', ['foo' => 3.5]));
}
- /** @test */
+ #[Test]
public function callWithoutArgsShouldReturnNaN(): void
{
$this->assertFalse($this->evaluate('parseFloat() === 1'));
diff --git a/tests/integration/functions/ParseIntTest.php b/tests/integration/functions/ParseIntTest.php
index 0c47cf4..9833ddb 100755
--- a/tests/integration/functions/ParseIntTest.php
+++ b/tests/integration/functions/ParseIntTest.php
@@ -3,40 +3,41 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\functions;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class ParseIntTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function onStringLiteral(): void
{
$this->assertTrue($this->evaluate('parseInt("3") === 3'));
}
- /** @test */
+ #[Test]
public function onStringLiteralWithSpaces(): void
{
$this->assertTrue($this->evaluate('parseInt(" 3 ") === 3'));
}
- /** @test */
+ #[Test]
public function onStringLiteralWithNonNumericChars(): void
{
$this->assertTrue($this->evaluate('parseInt("3aaa") === 3'));
}
- /** @test */
+ #[Test]
public function onUserDefinedVariable(): void
{
$this->assertTrue($this->evaluate('parseInt(foo) === 3', ['foo' => '3']));
$this->assertFalse($this->evaluate('parseInt(foo) === "3"', ['foo' => 3]));
}
- /** @test */
+ #[Test]
public function callWithoutArgsShouldReturnNan(): void
{
$this->assertFalse($this->evaluate('parseInt() === 1'));
diff --git a/tests/integration/functions/SyntaxErrorTest.php b/tests/integration/functions/SyntaxErrorTest.php
index 95fb7c0..6649b15 100755
--- a/tests/integration/functions/SyntaxErrorTest.php
+++ b/tests/integration/functions/SyntaxErrorTest.php
@@ -3,16 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\functions;
use nicoSWD\Rule\Rule;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class SyntaxErrorTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function undefinedFunctionThrowsException(): void
{
$rule = new Rule('nope() === true');
@@ -21,7 +22,7 @@ public function undefinedFunctionThrowsException(): void
$this->assertSame('nope is not defined at position 0', $rule->getError());
}
- /** @test */
+ #[Test]
public function incorrectSpellingThrowsException(): void
{
$rule = new Rule('/* fail */ paRSeInt("2") === 2');
diff --git a/tests/integration/methods/CharAtTest.php b/tests/integration/methods/CharAtTest.php
index 95e6a69..e8b3738 100755
--- a/tests/integration/methods/CharAtTest.php
+++ b/tests/integration/methods/CharAtTest.php
@@ -3,36 +3,37 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class CharAtTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function ifOmittedPositionFallsBackToZero(): void
{
$this->assertTrue($this->evaluate('foo.charAt() === "b"', ['foo' => 'bar']));
$this->assertTrue($this->evaluate('"bar".charAt() === "b"'));
}
- /** @test */
+ #[Test]
public function callWithValidPosition(): void
{
$this->assertTrue($this->evaluate('foo.charAt(1) === "a"', ['foo' => 'bar']));
$this->assertTrue($this->evaluate('"bar".charAt(2) === "r"'));
}
- /** @test */
+ #[Test]
public function invalidOffsetReturnsEmptyString(): void
{
$this->assertTrue($this->evaluate('foo.charAt(99) === ""', ['foo' => 'bar']));
$this->assertTrue($this->evaluate('"foo".charAt(99) === ""'));
}
- /** @test */
+ #[Test]
public function ifBooleansAndNullAreCastedToOneAndZero(): void
{
$this->assertTrue($this->evaluate('"foo".charAt(true) === "o"'));
diff --git a/tests/integration/methods/CombinedTest.php b/tests/integration/methods/CombinedTest.php
index f7aadd0..9ecafec 100755
--- a/tests/integration/methods/CombinedTest.php
+++ b/tests/integration/methods/CombinedTest.php
@@ -3,15 +3,16 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class CombinedTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function mixedMethodCalls(): void
{
$this->assertTrue($this->evaluate(
@@ -41,7 +42,7 @@ public function mixedMethodCalls(): void
));
}
- /** @test */
+ #[Test]
public function chainedMethodCalls(): void
{
$this->assertTrue($this->evaluate(
@@ -69,7 +70,7 @@ public function chainedMethodCalls(): void
));
}
- /** @test */
+ #[Test]
public function functionCallInsideMethod(): void
{
$this->assertTrue($this->evaluate('"abc".substr(parseInt(" 2 ")) === "c"'));
diff --git a/tests/integration/methods/ConcatTest.php b/tests/integration/methods/ConcatTest.php
index 1e0c4ac..028520b 100755
--- a/tests/integration/methods/ConcatTest.php
+++ b/tests/integration/methods/ConcatTest.php
@@ -3,15 +3,16 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class ConcatTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function allParametersAreConcatenated(): void
{
$this->assertTrue($this->evaluate('foo.concat("bar", "baz") === "foobarbaz"', ['foo' => 'foo']));
@@ -20,7 +21,7 @@ public function allParametersAreConcatenated(): void
$this->assertTrue($this->evaluate('"foo".concat("bar", 1) === "foobar1"'));
}
- /** @test */
+ #[Test]
public function arraysAreImplodedByCommaBeforeConcatenating(): void
{
$this->assertTrue($this->evaluate('"foo".concat("bar", [1, 2]) === "foobar1,2"'));
diff --git a/tests/integration/methods/EndsWithTest.php b/tests/integration/methods/EndsWithTest.php
index 1e98b21..48075de 100755
--- a/tests/integration/methods/EndsWithTest.php
+++ b/tests/integration/methods/EndsWithTest.php
@@ -3,35 +3,36 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\Parser\Exception\ParserException;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class EndsWithTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function givenAStringWhenEndsWithNeedleItShouldReturnTrue(): void
{
$this->assertTrue($this->evaluate('foo.endsWith("llo") === true', ['foo' => 'hello']));
$this->assertTrue($this->evaluate('"hello".endsWith("llo") === true'));
}
- /** @test */
+ #[Test]
public function givenAStringWhenNotEndsWithNeedleItShouldReturnFalse(): void
{
$this->assertTrue($this->evaluate('"hello".endsWith("ell") === false'));
}
- /** @test */
+ #[Test]
public function givenAStringWhenTestedWithEndsWithWithoutArgsItShouldReturnFalse(): void
{
$this->assertTrue($this->evaluate('"hello".endsWith() === false'));
}
- /** @test */
+ #[Test]
public function givenAStringWhenTestedOnNonStringValuesItShouldThrowAnException(): void
{
$this->expectException(ParserException::class);
diff --git a/tests/integration/methods/IndexOfTest.php b/tests/integration/methods/IndexOfTest.php
index 37ffe85..cad5e12 100755
--- a/tests/integration/methods/IndexOfTest.php
+++ b/tests/integration/methods/IndexOfTest.php
@@ -3,28 +3,29 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class IndexOfTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function validNeedleReturnsCorrectPosition(): void
{
$this->assertTrue($this->evaluate('foo.indexOf("a") === 1', ['foo' => 'bar']));
$this->assertTrue($this->evaluate('"bar".indexOf("b") === 0'));
}
- /** @test */
+ #[Test]
public function omittedParameterReturnsNegativeOne(): void
{
$this->assertTrue($this->evaluate('"bar".indexOf() === -1'));
}
- /** @test */
+ #[Test]
public function negativeOneIsReturnedIfNeedleNotFound(): void
{
$this->assertTrue($this->evaluate('"bar".indexOf("foo") === -1'));
diff --git a/tests/integration/methods/JoinTest.php b/tests/integration/methods/JoinTest.php
index 8363ccb..898b9e2 100755
--- a/tests/integration/methods/JoinTest.php
+++ b/tests/integration/methods/JoinTest.php
@@ -3,29 +3,30 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class JoinTest extends AbstractTestBase
{
protected array $array = ['foo' => ['foo', 'bar']];
- /** @test */
+ #[Test]
public function ifOmittedDelimiterFallsBackToDefault(): void
{
$this->assertTrue($this->evaluate('foo.join() === "foo,bar"', $this->array));
}
- /** @test */
+ #[Test]
public function literalStringDelimiter(): void
{
$this->assertTrue($this->evaluate('foo.join("|") === "foo|bar"', $this->array));
}
- /** @test */
+ #[Test]
public function variableValueAsDelimiter(): void
{
$this->assertTrue($this->evaluate(
@@ -34,20 +35,20 @@ public function variableValueAsDelimiter(): void
));
}
- /** @test */
+ #[Test]
public function callOnStringLiteralArray(): void
{
$this->assertTrue($this->evaluate('[1, 2, 3].join("|") === "1|2|3"'));
$this->assertTrue($this->evaluate('[1, 2, 3] . join("|") === "1|2|3"'));
}
- /** @test */
+ #[Test]
public function variableInArrayIsJoined(): void
{
$this->assertTrue($this->evaluate('[1, 2, foo].join("|") === "1|2|3"', ['foo' => 3]));
}
- /** @test */
+ #[Test]
public function joinOnEmptyArray(): void
{
$this->assertTrue($this->evaluate('[].join("|") === ""'));
diff --git a/tests/integration/methods/ReplaceTest.php b/tests/integration/methods/ReplaceTest.php
index cbe1ee0..6720618 100755
--- a/tests/integration/methods/ReplaceTest.php
+++ b/tests/integration/methods/ReplaceTest.php
@@ -3,40 +3,41 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class ReplaceTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function validNeedleReturnsCorrectPosition(): void
{
$this->assertTrue($this->evaluate('foo.replace("a", "A") === "bAr"', ['foo' => 'bar']));
$this->assertTrue($this->evaluate('"bar".replace("r", "R") === "baR"'));
}
- /** @test */
+ #[Test]
public function omittedParametersDoNotReplaceAnything(): void
{
$this->assertTrue($this->evaluate('"bar".replace() === "bar"'));
}
- /** @test */
+ #[Test]
public function omittedSecondParameterReplacesWithUndefined(): void
{
$this->assertTrue($this->evaluate('"bar".replace("r") === "baundefined"'));
}
- /** @test */
+ #[Test]
public function replaceWithRegularExpression(): void
{
$this->assertTrue($this->evaluate('"arbar".replace(/ar$/, "") === "arb"'));
}
- /** @test */
+ #[Test]
public function regularExpressionWithGModifier(): void
{
$this->assertTrue($this->evaluate('"foofoo".replace(/foo/, "") === "foo"'));
diff --git a/tests/integration/methods/SplitTest.php b/tests/integration/methods/SplitTest.php
index c3bf4cd..92c7915 100755
--- a/tests/integration/methods/SplitTest.php
+++ b/tests/integration/methods/SplitTest.php
@@ -3,31 +3,32 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class SplitTest extends AbstractTestBase
{
protected array $var = ['foo' => 'bar,baz,foo'];
- /** @test */
+ #[Test]
public function ifOmittedSeparatorFallsBackToDefault(): void
{
$this->assertTrue($this->evaluate('foo.split() === ["bar,baz,foo"]', $this->var));
$this->assertTrue($this->evaluate('["bar,baz,foo"] === foo.split()', $this->var));
}
- /** @test */
+ #[Test]
public function splittingLiteralStringAndVariableString(): void
{
$this->assertTrue($this->evaluate('foo.split(",") === ["bar", "baz", "foo"]', $this->var));
$this->assertTrue($this->evaluate('"bar,baz,foo".split(",") === ["bar", "baz", "foo"]'));
}
- /** @test */
+ #[Test]
public function booleansAndNullDoNotSplitAnywhere(): void
{
$this->assertTrue($this->evaluate('"foo".split(true) === ["foo"]'));
@@ -35,7 +36,7 @@ public function booleansAndNullDoNotSplitAnywhere(): void
$this->assertTrue($this->evaluate('"foo".split(null) === ["foo"]'));
}
- /** @test */
+ #[Test]
public function splitDelimiterAsVariable(): void
{
$this->assertTrue($this->evaluate(
@@ -44,7 +45,7 @@ public function splitDelimiterAsVariable(): void
));
}
- /** @test */
+ #[Test]
public function splitDelimiterAsVariableWithMethodCall(): void
{
$this->assertTrue($this->evaluate(
@@ -56,19 +57,19 @@ public function splitDelimiterAsVariableWithMethodCall(): void
));
}
- /** @test */
+ #[Test]
public function splitWithRegularExpression(): void
{
$this->assertTrue($this->evaluate('"foo bar".split(/\s+/) === ["foo", "bar"]'));
}
- /** @test */
+ #[Test]
public function splitWithRegexAndLimit(): void
{
$this->assertTrue($this->evaluate('"foo bar baz".split(/\s+/, 2) === ["foo", "bar baz"]'));
}
- /** @test */
+ #[Test]
public function splitWithLimit(): void
{
$this->assertTrue($this->evaluate('"foo bar baz".split(" ", 2) === ["foo", "bar baz"]'));
diff --git a/tests/integration/methods/StartsWithTest.php b/tests/integration/methods/StartsWithTest.php
index 793eb52..e7651eb 100755
--- a/tests/integration/methods/StartsWithTest.php
+++ b/tests/integration/methods/StartsWithTest.php
@@ -3,30 +3,31 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\Parser\Exception\ParserException;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class StartsWithTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function givenAStringWhenStartsWithNeedleItShouldReturnTrue(): void
{
$this->assertTrue($this->evaluate('"bar".startsWith("ba") === true'));
$this->assertTrue($this->evaluate('foo.startsWith("ar", 1) === true', ['foo' => 'bar']));
}
- /** @test */
+ #[Test]
public function givenAStringWhenNotStartsWithNeedleItShouldReturnTrue(): void
{
$this->assertTrue($this->evaluate('"bar".startsWith("a") === false'));
$this->assertTrue($this->evaluate('foo.startsWith("x") === false', ['foo' => 'bar']));
}
- /** @test */
+ #[Test]
public function givenAStringWhenTestedOnNonStringValuesItShouldThrowAnException(): void
{
$this->expectException(ParserException::class);
diff --git a/tests/integration/methods/SubstrTest.php b/tests/integration/methods/SubstrTest.php
index 053dc6d..2dfcc0c 100755
--- a/tests/integration/methods/SubstrTest.php
+++ b/tests/integration/methods/SubstrTest.php
@@ -3,34 +3,35 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class SubstrTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function substrReturnsCorrectPartOfString(): void
{
$this->assertTrue($this->evaluate('foo.substr(1, 2) === "ar"', ['foo' => 'bar']));
$this->assertTrue($this->evaluate('"bar".substr(0, 1) === "b"'));
}
- /** @test */
+ #[Test]
public function outOfBoundsOffsetReturnsEmptyString(): void
{
$this->assertTrue($this->evaluate('"bar".substr(100) === ""'));
}
- /** @test */
+ #[Test]
public function omittedParametersReturnsSameString(): void
{
$this->assertTrue($this->evaluate('"bar".substr() === "bar"'));
}
- /** @test */
+ #[Test]
public function negativeOffsetReturnsEndOfString(): void
{
$this->assertTrue($this->evaluate('"bar".substr(-1) === "r"'));
diff --git a/tests/integration/methods/SyntaxErrorTest.php b/tests/integration/methods/SyntaxErrorTest.php
index 6af16a9..ce9cf0a 100755
--- a/tests/integration/methods/SyntaxErrorTest.php
+++ b/tests/integration/methods/SyntaxErrorTest.php
@@ -3,16 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\Rule;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class SyntaxErrorTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function missingCommaInArgumentsThrowsException(): void
{
$rule = new Rule('"foo".charAt(1 2 ) === "b"');
@@ -21,7 +22,7 @@ public function missingCommaInArgumentsThrowsException(): void
$this->assertSame('Unexpected "2" at position 15', $rule->getError());
}
- /** @test */
+ #[Test]
public function missingValueInArgumentsThrowsException(): void
{
$rule = new Rule('"foo".charAt(1 , ) === "b"');
@@ -30,7 +31,7 @@ public function missingValueInArgumentsThrowsException(): void
$this->assertSame('Unexpected "," at position 17', $rule->getError());
}
- /** @test */
+ #[Test]
public function missingValueBetweenCommasInArgumentsThrowsException(): void
{
$rule = new Rule('"foo".charAt(1 , , ) === "b"');
@@ -39,7 +40,7 @@ public function missingValueBetweenCommasInArgumentsThrowsException(): void
$this->assertSame('Unexpected "," at position 17', $rule->getError());
}
- /** @test */
+ #[Test]
public function unexpectedTokenInArgumentsThrowsException(): void
{
$rule = new Rule('"foo".charAt(1 , < , ) === "b"');
@@ -48,7 +49,7 @@ public function unexpectedTokenInArgumentsThrowsException(): void
$this->assertSame('Unexpected "<" at position 17', $rule->getError());
}
- /** @test */
+ #[Test]
public function unexpectedEndOfStringThrowsException(): void
{
$rule = new Rule('"foo".charAt(1 , ');
@@ -57,7 +58,7 @@ public function unexpectedEndOfStringThrowsException(): void
$this->assertSame('Unexpected end of string', $rule->getError());
}
- /** @test */
+ #[Test]
public function undefinedMethodThrowsException(): void
{
$rule = new Rule('/^foo$/.teddst("foo") === true');
@@ -66,7 +67,7 @@ public function undefinedMethodThrowsException(): void
$this->assertSame('Undefined method "teddst" at position 7', $rule->getError());
}
- /** @test */
+ #[Test]
public function incorrectSpellingThrowsException(): void
{
$rule = new Rule('"foo".ChARat(1) === "o"');
@@ -75,7 +76,7 @@ public function incorrectSpellingThrowsException(): void
$this->assertSame('Undefined method "ChARat" at position 5', $rule->getError());
}
- /** @test */
+ #[Test]
public function callOnNonArray(): void
{
$rule = new Rule('"foo".join("|") === ""');
@@ -84,12 +85,12 @@ public function callOnNonArray(): void
$this->assertSame('foo.join is not a function', $rule->getError());
}
- /** @test */
+ #[Test]
public function exceptionIsThrownOnTypeError(): void
{
$rule = new Rule('"foo".test("foo") === false');
$this->assertFalse($rule->isValid());
- $this->assertSame('undefined is not a function', $rule->getError());
+ $this->assertSame('test() is not a function', $rule->getError());
}
}
diff --git a/tests/integration/methods/TestTest.php b/tests/integration/methods/TestTest.php
index dd905c2..8466863 100755
--- a/tests/integration/methods/TestTest.php
+++ b/tests/integration/methods/TestTest.php
@@ -3,29 +3,30 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class TestTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function basicRegularExpression(): void
{
$this->assertTrue($this->evaluate('/^foo$/.test("foo") === true'));
$this->assertTrue($this->evaluate('/^foo$/.test(foo) === true', ['foo' => 'foo']));
}
- /** @test */
+ #[Test]
public function arrayIsConvertedToString(): void
{
$this->assertTrue($this->evaluate('/^foo$/.test(["foo"]) === true'));
$this->assertTrue($this->evaluate('/1/.test([[[1]]]) === true'));
}
- /** @test */
+ #[Test]
public function modifiers(): void
{
$this->assertTrue($this->evaluate('/^foo$/i.test("FOO") === true'));
@@ -34,7 +35,7 @@ public function modifiers(): void
$this->assertFalse($this->evaluate('/^foo$/.test("' . "\n\n" .'foo") === true'));
}
- /** @test */
+ #[Test]
public function gModifierIsIgnored(): void
{
$this->assertTrue($this->evaluate('/^foo$/gi.test("foo") === true'), 'gi');
@@ -42,7 +43,7 @@ public function gModifierIsIgnored(): void
$this->assertTrue($this->evaluate('/^foo$/g.test("foo") === true'), '"g" modifier alone');
}
- /** @test */
+ #[Test]
public function booleansAndNullsAsSubject(): void
{
$this->assertTrue($this->evaluate('/^foo$/.test(true) === false'));
@@ -51,7 +52,7 @@ public function booleansAndNullsAsSubject(): void
$this->assertTrue($this->evaluate('/^true/.test(true) === false'));
}
- /** @test */
+ #[Test]
public function withOmittedParameters(): void
{
$this->assertTrue($this->evaluate('/^foo$/.test() === false'));
diff --git a/tests/integration/methods/ToUpperCaseTest.php b/tests/integration/methods/ToUpperCaseTest.php
index f17cf2c..ef17cf7 100755
--- a/tests/integration/methods/ToUpperCaseTest.php
+++ b/tests/integration/methods/ToUpperCaseTest.php
@@ -3,16 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart
*/
namespace nicoSWD\Rule\tests\integration\methods;
use nicoSWD\Rule\Rule;
use nicoSWD\Rule\tests\integration\AbstractTestBase;
+use PHPUnit\Framework\Attributes\Test;
final class ToUpperCaseTest extends AbstractTestBase
{
- /** @test */
+ #[Test]
public function spacesBetweenVariableAndMethodWork(): void
{
$this->assertTrue($this->evaluate('foo . toUpperCase() === "BAR"', ['foo' => 'bar']));
@@ -24,20 +25,20 @@ public function spacesBetweenVariableAndMethodWork(): void
));
}
- /** @test */
+ #[Test]
public function ifCallOnStringLiteralsWorks(): void
{
$this->assertTrue($this->evaluate('"bar".toUpperCase() === "BAR"'));
$this->assertTrue($this->evaluate('"bar" . toUpperCase() === "BAR"'));
}
- /** @test */
+ #[Test]
public function ifMethodCanBeCalledOnVariablesHoldingIntegers(): void
{
$this->assertTrue($this->evaluate('foo.toUpperCase() === "1"', ['foo' => 1]));
}
- /** @test */
+ #[Test]
public function callOnIntegersThrowsException(): void
{
$rule = new Rule('1.toUpperCase() === "1"', ['foo' => 1]);
diff --git a/tests/integration/operators/OperatorsTest.php b/tests/integration/operators/OperatorsTest.php
index 226bc2a..18cb9a7 100755
--- a/tests/integration/operators/OperatorsTest.php
+++ b/tests/integration/operators/OperatorsTest.php
@@ -3,16 +3,17 @@
/**
* @license http://opensource.org/licenses/mit-license.php MIT
* @link https://github.com/nicoSWD
- * @author Nicolas Oelgart
+ * @author Nicolas Oelgart