Skip to main content

Crate php_rs_parser

Crate php_rs_parser 

Source
Expand description

Fast, fault-tolerant PHP parser that produces a fully typed AST.

This crate parses PHP source code (PHP 7.4–8.5, plus PHP 8.6 partial function application) into a php_ast::Program tree, recovering from syntax errors so that downstream tools always receive a complete AST.

§Semantic-rejection responsibility

The parser is fault-tolerant: it always produces an AST and reports every error it can identify before recovering. Its semantic-rejection responsibility is defined externally:

For any input, the parser emits at least one diagnostic iff php -l would reject that input at the configured target PHP version.

Flow-sensitive checks — cross-file resolution, unused variables, dead code, type-mismatched returns — are out of scope and belong in a later semantic layer. Checks decidable from one declaration, one parameter list, one modifier set, or one declaration loop are in scope and use diagnostics::ParseError::Forbidden.

The ===php_error=== section in tests/fixtures/**/*.phpt records php -l output; the fixture runner enforces the rule above by failing CI when PHP rejects an input that the parser silently accepts.

§Quick start

let result = php_rs_parser::parse("<?php echo 'hello';");
assert!(result.errors.is_empty());

§Version-aware parsing

Use parse_with and ParseOptions to target a specific PHP version. Syntax that requires a higher version is still parsed into the AST, but a diagnostics::ParseError::VersionTooLow diagnostic is emitted.

use php_rs_parser::{ParseOptions, PhpVersion};

let result = php_rs_parser::parse_with(
    "<?php enum Status { case Active; }",
    &ParseOptions::default().version(PhpVersion::Php80),
);
assert!(!result.errors.is_empty()); // enums require PHP 8.1

§Multi-file cache

parse returns a ParseResult with no lifetime parameters — fully owned, storable in a HashMap, sendable across threads.

use std::collections::HashMap;
use std::path::PathBuf;

let mut cache: HashMap<PathBuf, php_rs_parser::ParseResult> = HashMap::new();
cache.insert(PathBuf::from("a.php"), php_rs_parser::parse("<?php echo 1;"));

§Arena API (LSP / hot-path usage)

Use parse_arena / ParserContext when you need maximum throughput and can manage the arena lifetime yourself. The returned ArenaParseResult borrows from both the arena and the source string — no allocation copying occurs.

let mut ctx = php_rs_parser::ParserContext::new();

let result = ctx.reparse("<?php echo 1;");
assert!(result.errors.is_empty());
drop(result); // must be dropped before the next reparse

let result = ctx.reparse("<?php echo 2;");
assert!(result.errors.is_empty());

Set ParseOptions::source_map to false when you never need line/column positions — it skips building the source_map::SourceMap and is slightly faster.

Re-exports§

pub use version::PhpVersion;
pub use bumpalo;

Modules§

diagnostics
Parse errors and warnings.
source_map
Byte offset to line/column mapping.
version
Target PHP version selection.

Structs§

ArenaParseResult
Arena-allocated result of parsing a PHP source string.
ParseOptions
Options for parse_with, parse_arena_with and ParserContext::with_options.
ParseResult
Lifetime-free result of parsing a PHP source string.
ParserContext
A reusable parse context that keeps a bumpalo::Bump arena alive between re-parses, resetting it (O(1)) instead of dropping and reallocating.

Functions§

parse
Parse PHP source with the default ParseOptions.
parse_arena
Parse PHP source with the default ParseOptions, returning an arena-allocated ArenaParseResult.
parse_arena_with
Parse PHP source with the given options, returning an arena-allocated ArenaParseResult.
parse_with
Parse PHP source with the given options, returning a fully-owned ParseResult.