PHPackages                             yoeunes/regex-parser - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [CLI &amp; Console](/categories/cli)
4. /
5. yoeunes/regex-parser

ActiveLibrary[CLI &amp; Console](/categories/cli)

yoeunes/regex-parser
====================

A PCRE regex parser with lexer, AST builder, validation, ReDoS analysis, and syntax highlighting. Zero runtime dependencies.

v1.3.0(7mo ago)29122.7k↓24.8%33MITPHPPHP &gt;=8.2CI passing

Since Nov 17Pushed 3w ago1 watchersCompare

[ Source](https://github.com/yoeunes/regex-parser)[ Packagist](https://packagist.org/packages/yoeunes/regex-parser)[ Docs](https://github.com/yoeunes/regex-parser)[ GitHub Sponsors](https://github.com/sponsors/yoeunes)[ RSS](/packages/yoeunes-regex-parser/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (5)DependenciesVersions (79)Used By (3)

 [![RegexParser](art/banner.svg?v=1)](art/banner.svg?v=1)

 [![CI Status Badge](https://github.com/yoeunes/regex-parser/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/yoeunes/regex-parser/actions/workflows/ci.yml) [![PHPStan Level Badge](https://camo.githubusercontent.com/b6d441ad4fe8332cb16c72aa27f22cc685181dfd74ae34964afc92c6c1146b3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c2532306d61782d627269676874677265656e2e737667)](https://phpstan.org/) [![Author Badge](https://camo.githubusercontent.com/4a38d2f6b2dc78e84f180f1480fb8515999644208f31ca1fc75037e8812da2ce/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f617574686f722d40796f65756e65732d626c75652e737667)](https://www.linkedin.com/in/younes--ennaji) [![GitHub Release Badge](https://camo.githubusercontent.com/aad3649e8698d322f10f16e5c01d795711bd42ffca29bea9d1e8259f00a5dc5b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f7461672f796f65756e65732f72656765782d7061727365722e737667)](https://github.com/yoeunes/regex-parser/releases) [![License Badge](https://camo.githubusercontent.com/074b89bca64d3edc93a1db6c7e3b1636b874540ba91d66367c0e5e354c56d0ea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e737667)](https://github.com/yoeunes/regex-parser/blob/main/LICENSE) [![Packagist Downloads Badge](https://camo.githubusercontent.com/3e97dafbc8d02a01fd7eccb4ef23c12a8744b530fdfebdf4325aa3d941ac9ff6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f796f65756e65732f72656765782d7061727365722e737667)](https://packagist.org/packages/yoeunes/regex-parser) [![GitHub Stars Badge](https://camo.githubusercontent.com/8d0588f00a17c8f773dcba910174e888788c63e652f47d1560884e87f3ac8463/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f796f65756e65732f72656765782d7061727365722e737667)](https://github.com/yoeunes/regex-parser) [![Supported PHP Version Badge](https://camo.githubusercontent.com/ab1b1e2ff305e40fbb8d01d580377117ebf9ce1374f4a95432685dcc539028bf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f796f65756e65732f72656765782d7061727365722e737667)](https://packagist.org/packages/yoeunes/regex-parser)

RegexParser: Static Analysis, Linter &amp; Logic Solver
=======================================================

[](#regexparser-static-analysis-linter--logic-solver)

RegexParser is a PHP 8.2+ library that treats regular expressions as code.

Unlike simple wrappers around `preg_match`, RegexParser implements a complete **compiler pipeline** (Lexer → Parser → AST) and an **Automata-based Logic Solver** (AST → NFA → DFA).

This architecture allows for advanced static analysis:

- **Linting:** Detect redundancy, useless flags, and common mistakes.
- **Safety:** Statically detect *potential* catastrophic backtracking (ReDoS).
- **Logic:** Compare patterns via NFA/DFA (Intersection, Equivalence, Subset) for the regular subset it supports.

Built for learning, validation, and robust tooling in PHP projects.

> ⚠️ **What this is and is not.** RegexParser is a side project and a learning exercise. It is **not** a hardened security product and should not be your only line of defense. ReDoS detection is structural and conservative — treat findings as *potential* risk to investigate, not as a guarantee of safety. The parser aims for PCRE compatibility but does not cover every edge case of the PCRE engine.

If you are new to regex, start with the [Regex Tutorial](docs/tutorial/README.md). If you want a short overview, see the [Quick Start Guide](docs/QUICK_START.md).

Getting started
---------------

[](#getting-started)

```
# Install the library
composer require yoeunes/regex-parser

# Try the CLI
vendor/bin/regex explain '/\d{4}-\d{2}-\d{2}/'
```

What RegexParser provides
-------------------------

[](#what-regexparser-provides)

- 🏗️ **Deep Parsing:** Parse `/pattern/flags` into a structured, typed AST.
- 🧠 **Logic Solver:** Compare two regexes using NFA/DFA transformation (intersection, equivalence, subset). Works for patterns in the [regular subset](docs/ARCHITECTURE.md) it supports; falls back gracefully otherwise.
- 🛡️ **ReDoS Analysis:** Detect *potential* catastrophic backtracking risks structure-wise. Findings are heuristic — treat them as risk to investigate, not a guarantee.
- 🧹 **Linter:** Detect useless flags, redundant groups, and common mistakes via the CLI.
- 📖 **Explanation:** Explain patterns in plain English.
- 🔧 **Visitor API:** A flexible API for building custom regex tooling.

Philosophy &amp; Accuracy
-------------------------

[](#philosophy--accuracy)

RegexParser separates what it can guarantee from what is heuristic:

- Guaranteed: parsing, AST structure, error offsets, and syntax validation for the targeted PHP/PCRE version.
- Heuristic: ReDoS analysis is structural and conservative; treat it as potential risk unless confirmed.
- Context matters: PCRE version, JIT, and backtrack/recursion limits change practical impact.

### Tested against the real engine

[](#tested-against-the-real-engine)

Round-trip correctness (`compile(parse(x))` behaves like the original) is verified in CI by differential tests that compare RegexParser's output against PHP's native `preg_match()`:

- A fixture of **212 PCRE patterns** is checked for validity, match result, and captured groups (`OfficialPcreComplianceTest`).
- Additional behavioral tests cover named groups, lookarounds, conditionals, atomic groups, and other features (`BehavioralComplianceTest`, `AdvancedFeaturesComplianceTest`).

These tests compare against a limited set of subjects, so they catch clear regressions but are **not** a formal proof of full PCRE equivalence. There may be edge cases that the test suite does not yet cover.

Separately, the linter and ReDoS analyzer have been run over a corpus of **~960 unique patterns collected from 279 real-world PHP projects** (Symfony, Laravel, Composer, PHPUnit, …). The results are in `corpus/corpus.log` and `corpus-redos.log`. This corpus run is **not** part of the automated CI differential test — it is a snapshot used to validate that the lint and ReDoS rules produce sensible output on real code.

How to report a vulnerability responsibly
-----------------------------------------

[](#how-to-report-a-vulnerability-responsibly)

If you believe a pattern is exploitable:

1. Run confirmed mode and capture a bounded, reproducible PoC.
2. Include the pattern, input lengths, timings, JIT setting, and PCRE limits.
3. Verify impact in the real code path before filing a security issue.

See [SECURITY.md](SECURITY.md) for reporting channels.

Safer rewrites (verify behavior)
--------------------------------

[](#safer-rewrites-verify-behavior)

These techniques reduce backtracking but can change matching behavior. Always validate with tests.

```
/(a+)+$/     -> /a+$/      (semantics often preserved, but verify captures)
/(a+)+$/     -> /a++$/     (possessive, no backtracking)
/(a|aa)+/    -> /a+/       (only if alternation is redundant)
/(a|aa)+/    -> /(?>a|aa)+/ (atomic, avoids backtracking)

```

How it works
------------

[](#how-it-works)

- `Regex::parse()` splits the literal into pattern and flags.
- The lexer produces a token stream.
- The parser builds an AST (`RegexNode`).
- Visitors walk the AST to validate, explain, analyze, or transform.

For the full architecture, see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).

CLI quick tour
--------------

[](#cli-quick-tour)

```
# Parse and validate a pattern
vendor/bin/regex parse '/^hello world$/'

# Get plain English explanation
vendor/bin/regex explain '/\d{4}-\d{2}-\d{2}/'

# Check for potential ReDoS risk (theoretical by default)
vendor/bin/regex analyze '/(a+)+$/'

# Colorize pattern for better readability
vendor/bin/regex highlight '/\d+/'

# Lint your entire codebase
vendor/bin/regex lint src/
```

[![Regex Lint Output](docs/assets/regex-lint.png)](docs/assets/regex-lint.png)

PHP API at a glance
-------------------

[](#php-api-at-a-glance)

```
use RegexParser\Regex;
use RegexParser\ReDoS\ReDoSMode;

$regex = Regex::create([
    'runtime_pcre_validation' => true,
]);

// Parse a pattern into AST
$ast = $regex->parse('/^hello world$/i');

// Validate pattern syntax and semantics
$result = $regex->validate('/(?
