goaop/dissect

A set of tools for lexical and syntactical analysis written in pure PHP

Maintainers

๐Ÿ‘ lisachenko

Package info

github.com/goaop/dissect

pkg:composer/goaop/dissect

Fund package maintenance!

lisachenko

Statistics

Installs: 112โ€‰556

Dependents: 1

Suggesters: 0

Stars: 2

4.0.1 2026-03-27 23:12 UTC

Requires

  • php: ^8.4.0

Requires (Dev)

Suggests

Provides

None

Conflicts

None

Replaces

None

MIT b37e69cebd2c4f4359371a7d98b349f3983ebcdf

parserparsingastlexing


README

A pure-PHP toolkit for building custom lexers and LALR(1) parsers โ€” fast, type-safe, and dependency-free.

๐Ÿ‘ GitHub Actions Workflow Status
๐Ÿ‘ PHPStan Badge
๐Ÿ‘ Total Downloads
๐Ÿ‘ Daily Downloads
๐Ÿ‘ PHP Version
๐Ÿ‘ GitHub License
๐Ÿ‘ Sponsor

โœจ What is Dissect?

Dissect is a pure-PHP library for lexical and syntactical analysis โ€” the foundational building blocks for any language tooling: expression evaluators, template engines, DSL interpreters, query parsers, and more.

It powers the GoAOP framework, where it parses pointcut DSL expressions into an AST for aspect-oriented programming.

Data flow

Input String
 โ”‚
 โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Lexer โ”‚ โ”€โ”€โ”€โ–ถ โ”‚ TokenStream โ”‚ โ”€โ”€โ”€โ–ถ โ”‚ LALR(1) Parser โ”‚ โ”€โ”€โ”€โ–ถ Result / AST
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
 โ–ฒ
 Grammar (rules
 + callbacks)

๐Ÿš€ Key Features

๐Ÿ”ค Flexible Lexers

Lexer Description
SimpleLexer Fluent builder API โ€” define tokens with strings or regex, mark skippable tokens
StatefulLexer Context-aware tokenization with explicit state transitions (e.g. for string interpolation)
RegexLexer Abstract base class adapted from Doctrine โ€” ultra-fast single-pass regex lexing

๐Ÿ“ LALR(1) Parser

  • Full LALR(1) grammar support โ€” handles the vast majority of real-world grammars
  • Fluent grammar API โ€” define productions and semantic actions with readable PHP closures
  • Operator precedence & associativity โ€” built-in left(), right(), nonassoc() declarations
  • Conflict resolution โ€” configurable strategies: shift-wins, longer-reduce, earlier-reduce
  • Precomputed parse tables โ€” analyze once, serialize to PHP file, load instantly in production

๐ŸŒณ AST Construction

  • CommonNode โ€” ready-to-use tree node with named children and arbitrary attributes
  • Countable & iterable โ€” traverse subtrees with standard PHP constructs

๐Ÿ›  Developer Experience

  • Zero runtime dependencies โ€” only Symfony Console as an optional CLI dep
  • PHPStan level 10 โ€” fully typed with generics, array shapes, and readonly properties
  • CLI tool โ€” dump parse tables and visualize automaton states as Graphviz graphs

๐Ÿ“ฆ Installation

composer require goaop/dissect

โšก Quick Example

use Dissect\Lexer\SimpleLexer;
use Dissect\Parser\Grammar;
use Dissect\Parser\LALR1\Parser;

// 1. Define a lexer
$lexer = new SimpleLexer();
$lexer->regex('INT', '/[0-9]+/')
 ->token('PLUS', '+')
 ->token('MINUS', '-')
 ->regex('WS', '/\s+/')
 ->skip('WS');

// 2. Define a grammar
$grammar = new Grammar();
$grammar('Expr')
 ->is('Expr', 'PLUS', 'Expr')
 ->call(fn($l, $_, $r) => $l + $r)

 ->is('Expr', 'MINUS', 'Expr')
 ->call(fn($l, $_, $r) => $l - $r)

 ->is('INT')
 ->call(fn($t) => (int) $t->getValue());

$grammar->operators('PLUS', 'MINUS')->left()->prec(1);
$grammar->start('Expr');

// 3. Parse!
$parser = new Parser($grammar);
$result = $parser->parse($lexer->lex('3 + 5 - 2')); // โ†’ 6

๐Ÿ“– Documentation

Topic Description
Lexical analysis SimpleLexer, StatefulLexer, RegexLexer, performance tips
Writing a grammar Productions, callbacks, operator precedence, conflict resolution
Building an AST CommonNode, tree traversal
Common patterns Lists, comma-separated sequences, expression grammars
CLI tool Precomputing parse tables, exporting automaton graphs

๐Ÿงช Testing & Quality

# Run tests
composer test

# Run tests with coverage
composer test-coverage

# Static analysis (PHPStan level 10)
composer phpstan

๐Ÿ™ Credits

Originally created by @jakubledl, extended by @WalterWoshid, maintained by the GoAOP team.

Give a โญ if Dissect saved you from writing a parser by hand!