This guide helps you upgrade RegexParser between versions. For detailed changes, see CHANGELOG.md.
Before:
// config/regex.php
return [
'rules' => [
'suspiciousAsciiRange' => true,
'duplicateCharacterClass' => true,
],
'redosMode' => 'theoretical',
'redosThreshold' => 'high',
'redosNoJit' => false,
'optimizations' => [
'digits' => true,
'word' => true,
'ranges' => true,
'canonicalizeCharClasses' => true,
],
'minSavings' => 10,
];After:
// config/regex.php
return [
'checks' => [
'lint' => [
'suspiciousAsciiRange' => true,
'duplicateCharacterClass' => true,
],
'redos' => [
'mode' => 'theoretical', // 'theoretical' or 'confirmed'
'threshold' => 'high', // 'safe', 'low', 'medium', 'high', 'critical'
'noJit' => false,
],
'optimization' => [
'digits' => true,
'word' => true,
'ranges' => true,
'canonicalizeCharClasses' => true,
'minSavings' => 10,
],
],
];Migration Steps:
- Move
rules.*→checks.lint.* - Move
redosMode→checks.redos.mode - Move
redosThreshold→checks.redos.threshold - Move
redosNoJit→checks.redos.noJit - Move
optimizations.*→checks.optimization.* - Move
minSavings→checks.optimization.minSavings
Before:
{
"scripts": {
"regex:lint": "bin/regex lint --rules=suspiciousAsciiRange,duplicateCharacterClass"
}
}After:
{
"scripts": {
"regex:lint": "bin/regex lint --checks.lint.suspiciousAsciiRange --checks.lint.duplicateCharacterClass"
}
}Before:
parameters:
regexParser:
rules:
suspiciousAsciiRange: true
redosMode: theoretical
redosThreshold: highAfter:
parameters:
regexParser:
checks:
lint:
suspiciousAsciiRange: true
redos:
mode: theoretical
threshold: highThe following features are deprecated and will be removed in 2.0.0:
- ✗
rulesconfig key (usechecks.lint) - ✗
redosModeconfig key (usechecks.redos.mode) - ✗
redosThresholdconfig key (usechecks.redos.threshold) - ✗
redosNoJitconfig key (usechecks.redos.noJit) - ✗
optimizationsconfig key (usechecks.optimization) - ✗
minSavingsconfig key (usechecks.optimization.minSavings)
All lint checks are now organized under checks namespace for better organization:
$regex = Regex::create();
$result = $regex->lint($pattern, [
'checks' => [
'lint' => [
'suspiciousAsciiRange' => true,
'duplicateCharacterClass' => true,
'uselessRange' => true,
'zeroQuantifier' => true,
'redundantQuantifier' => true,
'emptyAlternative' => true,
'duplicateDisjunction' => true,
'uselessBackreference' => true,
'optimalQuantifierConcatenation' => true,
],
'redos' => [
'mode' => 'confirmed', // NEW: Run actual tests
'threshold' => ReDoSSeverity::MEDIUM,
'maxTestStrings' => 1000,
'noJit' => false,
],
'optimization' => [
'digits' => true,
'word' => true,
'ranges' => true,
'canonicalizeCharClasses' => true,
'autoPossessify' => true,
'allowAlternationFactorization' => false,
'minQuantifierCount' => 4,
'minSavings' => 10,
'verifyWithAutomata' => true, // NEW: Verify equivalence
],
],
]);New verifyWithAutomata option ensures optimized patterns are mathematically equivalent:
$regex = Regex::create();
$result = $regex->optimize($pattern, [
'verifyWithAutomata' => true, // NEW: Guarantee equivalence
]);
if ($result->optimizedPattern !== $pattern) {
echo "Optimized safely: {$result->optimizedPattern}\n";
} else {
echo "Pattern already optimal or cannot guarantee equivalence\n";
}Use this checklist to ensure your upgrade is complete:
- Replace all
rules.*config withchecks.lint.* - Replace
redosModewithchecks.redos.mode - Replace
redosThresholdwithchecks.redos.threshold - Replace
redosNoJitwithchecks.redos.noJit - Move
optimizations.*tochecks.optimization.* - Move
minSavingstochecks.optimization.minSavings - Update PHPStan configuration (if used)
- Update composer scripts (if using custom flags)
- Test your regex patterns after upgrade
- Run
bin/regex linton your codebase - Review ReDoS warnings with new
confirmedmode if needed
After upgrading, run these commands to verify everything works:
# 1. Verify linting works with new config
bin/regex lint src/ --config=config/regex.php
# 2. Test ReDoS detection with new mode
bin/regex analyze '/(a+)+$/' --checks.redos.mode=confirmed
# 3. Verify optimization with automata verification
bin/regex optimize '/[0-9]{3}-[0-9]{3}-[0-9]{4}/' --checks.optimization.verifyWithAutomata
# 4. Run full test suite
composer phpunitBefore:
use RegexParser\Transpiler\RegexTranspiler;
$transpiler = new RegexTranspiler($regex);
$result = $transpiler->transpile('/\d+/', 'javascript');After:
use RegexParser\Regex;
$regex = Regex::create();
$result = $regex->transpile('/\d+/', 'javascript');
// Or with options
use RegexParser\Transpiler\TranspileOptions;
$options = new TranspileOptions(
targetLanguage: 'javascript',
ensureBackwardCompatibility: true,
);
$result = $regex->transpile('/\d+/', $options);Migration Steps:
- Replace
new RegexTranspiler($regex)withRegex::create() - Call
$regex->transpile()instead of$transpiler->transpile() - Use
TranspileOptionsfor advanced configurations
Before:
use RegexParser\Automata\Solver\RegexSolver;
$solver = new RegexSolver($regex);
$result = $solver->equivalent($pattern1, $pattern2);After:
use RegexParser\Automata\RegexLanguageSolver;
$language = RegexLanguageSolver::create();
$result = $language->equivalent($pattern1, $pattern2, new SolverOptions());Migration Steps:
- Replace
RegexSolverwithRegexLanguageSolver - Use static factory method
RegexLanguageSolver::create() - Pass
SolverOptionsfor fine-tuning
Automata solver now supports /u flag patterns with proper Unicode handling:
$language = RegexLanguageSolver::create();
$result = $language->subset('/[α-ω]+/u', '/[a-zA-Z]+/');
// Correctly handles Unicode code pointsNew command to export AST as DOT/Mermaid diagrams:
# Export as DOT format (Graphviz)
bin/regex graph '/\d{4}-\d{2}/' --format=dot
# Export as Mermaid format
bin/regex graph '/\d{4}-\d{2}/' --format=mermaid
# Save to file
bin/regex graph '/\d{4}-\d{2}/' --format=mermaid > diagram.mmdNone. This is a feature release.
New Symfony bundle commands:
# Analyze Symfony routes for conflicts
php bin/console regex:routes
# Analyze Symfony security config
php bin/console regex:security
# Run all bridge analyzers
php bin/console regex:analyzeBefore:
use RegexParser\ReDoS\ReDoSSeverity;
$result = $regex->redos($pattern, 'high'); // stringAfter:
use RegexParser\ReDoS\ReDoSSeverity;
$result = $regex->redos($pattern, ReDoSSeverity::HIGH); // enumMigration Steps:
- Replace string thresholds with enum values:
'safe'→ReDoSSeverity::SAFE'low'→ReDoSSeverity::LOW'medium'→ReDoSSeverity::MEDIUM'high'→ReDoSSeverity::HIGH'critical'→ReDoSSeverity::CRITICAL
- Update type hints to use
ReDoSSeveritytype
Before:
$issues = $linter->lint($pattern);
foreach ($issues as $issue) {
echo "{$issue['type']}: {$issue['message']}\n";
}After:
use RegexParser\Lint\LintIssue;
$report = $linter->lint($pattern);
/** @var LintIssue $issue */
foreach ($report->issues as $issue) {
echo "{$issue->type->value}: {$issue->message}\n";
}Migration Steps:
- Access properties via object properties instead of array keys
- Use typed properties:
$issue->type,$issue->message,$issue->position - Import
LintIssuefor type hints
New command for pattern comparison:
# Check intersection
bin/regex compare '/edit/' '/[a-z]+/'
# Check subset
bin/regex compare '/edit/' '/[a-z]+/' --method=subset
# Check equivalence
bin/regex compare '/[0-9]+/' '/\d+/' --method=equivalenceIf you encounter issues during upgrade:
- Check Troubleshooting Guide
- Review CHANGELOG.md for detailed changes
- Search GitHub Issues
- Create new issue with your specific upgrade problem