wikimedia/wikipeg
Wikipeg is a PHP port of PEG.js, the parser generator for parsing expression grammars. Write a grammar and it compiles it into a fast, standalone PHP parser with no runtime dependencies, making custom language and syntax parsers easy to build and maintain in PHP projects.
Architecture fit
Wikipeg is a PEG (Parsing Expression Grammar) parser generator written in PHP, a port of Ian Piumarta's peg/leg. It sits at the build-time layer of an application rather than the runtime layer: you author .peg grammar files, run the CLI compiler, and it emits standalone PHP parser classes that you then commit or autoload. For a Laravel codebase this means it does not integrate with the framework's service container, facades, config system, or Eloquent at all — it is a pure library plus a console entry point. That is actually a clean architectural boundary: the generated parser is a plain PHP class, so it can be wrapped in a Laravel service provider or a dedicated app/Parsing namespace with minimal coupling. The realistic use case is narrow: you have a domain-specific language (DSL), template syntax, query language, config format, or markup dialect that regex and Laravel's Str helpers cannot responsibly handle. The package's provenance matters here — it is the parser generator behind Parsoid's wikitext grammar, which is a strong credibility signal for correctness on complex, ambiguous grammars. It is a poor fit if the actual requirement is JSON/YAML/CSV parsing (use symfony/* components) or HTML sanitization (use an existing sanitizer).
Integration feasibility Composer installation is straightforward — the package is a standard PSR-4 PHP library with a CLI binary, MIT licensed, no exotic extensions or native compilation. Two integration shapes exist:
wikimedia/wikipeg to require-dev, keep grammar sources in resources/grammars/, generate parser classes into app/Generated/ (or similar), commit the output, and expose a Composer script or Artisan command to regenerate. CI fails if generated output drifts from grammar source.require and generate at deploy time. This is riskier — it puts a compiler in the production image and makes deploys dependent on generation succeeding.Shape 1 is the correct default for Laravel. The generated code is plain PHP with no runtime dependency on wikipeg itself, which means the compiled parser carries zero operational footprint.
Technical risk Several concrete risks stand out:
gerrit.wikimedia.org/g/wikipeg. Issues and pull requests on GitHub are not the contribution path. As a TPM you must assume: no inbound PR-based bug fixes, no GitHub issue triage, and a contributor workflow (Gerrit/Gitiles) your team is not set up for. Any patch you need, you own locally as a fork or a patches/ entry via cweagans/composer-patches.readonly, PHP 8.3/8.4 deprecations). A PHP minor upgrade could produce deprecation noise in generated files that you cannot cleanly patch upstream. Plan to pin PHP versions and validate generation output in CI on every runtime upgrade.Key questions
Stack fit Wikipeg fits Laravel as a compiler toolchain, not a framework component. The clean layout:
resources/grammars/*.peg — grammar sources, reviewed like code.app/Parsing/Generated/*.php — emitted parser classes, committed, excluded from coverage and static analysis baselines (or included with a baseline).app/Parsing/<Domain>Parser.php — a thin hand-written wrapper that owns the public API (parse(string $input): AstNode), translates wikipeg's generic parse tree or visitor callbacks into your domain AST, and throws domain-specific exceptions.ParserGenerateCommand Artisan command or a composer generate-parsers script that shells out to the wikipeg CLI.This keeps wikipeg at the edge of the system. Nothing else in the application should use Wikimedia\WikiPEG\... — only the generate command and the wrapper. Enforce that with a PHPStan/PHPat architectural rule.
Migration path Treat this as greenfield rather than migration: wikipeg should be introduced for a new grammar-backed capability, or to replace an existing regex/fragile parser behind an unchanged interface. The migration sequence:
.peg grammar against that corpus, iteratively, with the generator in CI.Because the generated parser is a plain class, rollback is a config flip, not a deploy.
Compatibility
composer why-not / composer prohibits). Do this early — a constraint conflict with an existing Laravel-adjacent dependency is a common dead end.bin, so vendor/bin/).Sequencing
Maintenance
The steady-state maintenance burden is concentrated in two places. First, the grammar itself — grammars accumulate edge cases and are easy to break subtly, so every grammar change needs a regression corpus and a diff review. Second, the toolchain — the generate command and CI drift check become build-critical infrastructure; if they break, no one can modify the parser. Budget a named owner. Because the GitHub repo is a mirror, upstream fixes require monitoring the Gerrit/Gitiles feed or the Parsoid repository's dependency bumps rather than watching a GitHub releases page. Recommend pinning an exact version in composer.json (no ^) and bumping deliberately, with the generated-output diff reviewed as part of the bump PR.
Support There is effectively no external support channel. No Laravel community precedent, negligible GitHub issue activity, and the official contribution path is Gerrit — which most PHP teams are not fluent in. Internal support is the only support: one or two engineers who understand PEG semantics and can debug parse failures. This is a bus-factor risk and should be documented as such. The upside is that the dependency surface is small and the generated code is readable PHP, so a competent engineer can always read the output.
Scaling
Parsing is CPU-bound and synchronous. A PEG parser is generally linear-ish in input size but ordered choice means poorly ordered rules can be catastrophically slow on pathological inputs — this is the classic failure mode and it must be tested with adversarial inputs, not just happy-path fixtures. In a Laravel request path, treat parsing as something you bound: enforce a maximum input size, set an execution time budget (e.g., set_time_limit guard in a queued job), and push large documents to a queue worker rather than parsing inline in a web request. Memory is typically fine for moderate documents but grows with document size and backtracking depth; load-test with the largest real inputs, not synthetic averages. Horizontal scaling is trivial — the parser is stateless and per-process, so it scales with your existing PHP-FPM/queue workers. No new infrastructure.
Failure modes
composer-patches and a scheduled review of that patch list.Ramp-up Expect two to four weeks before a competent PHP engineer is productive in wikipeg — roughly one week to internalize PEG semantics and the tool's visitor API, and another one to three weeks to author a non-trivial grammar against a real corpus. This is the largest hidden cost in the assessment and should be scheduled explicitly rather than absorbed as "learning on the job." Mitigate by scoping the first grammar deliberately small (a single well-bounded format, not the full domain language) so the team earns the toolchain and the debugging instincts on a low-stakes surface before committing to anything load-bearing. Given the low ecosystem adoption and mirror-only distribution, the recommendation is to proceed only if the parsing problem is genuinely non-trivial and the team can commit a named owner plus a fork-and-patch posture; otherwise a hand-written recursive-descent parser is likely cheaper to own over a multi-year horizon.
How can I help you explore Laravel packages today?