Skip to content

Major refactor — recursive descent parser, arithmetic, unary operators, and token system overhaul

Latest

Choose a tag to compare

@nicoSWD nicoSWD released this 29 Apr 22:05
· 8 commits to master since this release
0bf4368

New Features

  • Arithmetic operations — Full support for math expressions with proper operator precedence: +, -, *, /, %. Parentheses can be used to override precedence. (2 + 3 * 4 == 14)
  • String concatenation — The + operator now performs string concatenation when either operand is a string, and numeric addition otherwise. ("hello " + "world")
  • Unary minus and logical NOT operators — Support for negation (-5), double negation (--5), and logical NOT (!false, !(1 == 2), !foo).
  • Expression result APIRule::result() returns the actual computed value of an expression (e.g., int(15) for 5 * 3), not just true/false.
  • Syntax highlighter — A built-in custom syntax highlighter with customizable styles for token types.
  • Duplicate regex modifier validation — Invalid or duplicate regex modifiers now throw an error.

Major Refactors & Improvements

  • Recursive descent parser — Replaced the old parser with a proper recursive descent parser, improving correctness and maintainability.
  • Token system simplification — Consolidated 27 token classes into a single GenericToken + TokenKind enum, drastically reducing complexity.
  • Lexer streamingLexer::tokenize() converted from array-based to generator-based streaming for better memory efficiency.
  • Eliminated TokenStream God object — Cleaned up the dependency tree by removing the monolithic TokenStream class.
  • RuleEngineBuilder — Extracted dependency wiring from the God constructor in RuleEngine into a dedicated builder.
  • Interpreter pattern in AstEvaluator — Replaced fragile match expressions with the Interpreter pattern for cleaner node evaluation.
  • Consolidated InternalFunction/InternalMethod — Merged into a single InternalCallable DTO.
  • Consolidated Token/TokenKind enums — Reduced duplication across token enums.
  • Removed dead code — Cleaned up the Expression directory, EvaluableExpression, unused TokenIterator methods, and more.
  • PSR-12 coding standard — Migrated from PSR-2 to PSR-12.

Bug Fixes

  • Division by zero — Now properly handled in the evaluator instead of causing errors.
  • String escape sequences — Fixed unescaping of escape sequences in TokenEncapsedString.
  • AST cache not used — Fixed double parsing in Rule.php where the AST cache was never utilized.
  • Infinite recursion — Fixed infinite recursion in Rule.php property hook.
  • Lexer reentrancy — Fixed mutable state / reentrancy issue in the Lexer.
  • FunctionRegistry performance — Eliminated unnecessary new instance creation on every function call.
  • TokenCollection data structure — Replaced SplObjectStorage with ArrayObject to fix wrong data structure usage.
  • Fragile method prefix fallback — Refactored fragile method prefix fallback loop in ObjectMethodCaller.
  • Double evaluation — Eliminated double evaluation in isValid()/getError().
  • Duplicated node evaluation — Fixed duplicated node evaluation logic in AstEvaluator.
  • Stack-based token inspection — Replaced fragile $afterValue boolean with stack-based token inspection.

Dependency Updates

  • Updated PHP requirement to >=8.5
  • Updated phpunit/phpunit to ^13.1
  • Updated mockery/mockery to ^1.6
  • Updated squizlabs/php_codesniffer to ^4.0