Skip to main content

php_rs_parser/
lib.rs

1//! Fast, fault-tolerant PHP parser that produces a fully typed AST.
2//!
3//! This crate parses PHP source code (PHP 8.0–8.5) into a [`php_ast::Program`]
4//! tree, recovering from syntax errors so that downstream tools always receive
5//! a complete AST.
6//!
7//! # Quick start
8//!
9//! ```
10//! let arena = bumpalo::Bump::new();
11//! let result = php_rs_parser::parse(&arena, "<?php echo 'hello';");
12//! assert!(result.errors.is_empty());
13//! ```
14//!
15//! # Version-aware parsing
16//!
17//! Use [`parse_versioned`] to target a specific PHP version. Syntax that
18//! requires a higher version is still parsed into the AST, but a
19//! [`diagnostics::ParseError::VersionTooLow`] diagnostic is emitted.
20//!
21//! ```
22//! let arena = bumpalo::Bump::new();
23//! let result = php_rs_parser::parse_versioned(
24//!     &arena,
25//!     "<?php enum Status { case Active; }",
26//!     php_rs_parser::PhpVersion::Php80,
27//! );
28//! assert!(!result.errors.is_empty()); // enums require PHP 8.1
29//! ```
30
31pub mod diagnostics;
32pub(crate) mod expr;
33pub mod instrument;
34pub(crate) mod interpolation;
35pub(crate) mod parser;
36pub mod phpdoc;
37pub(crate) mod precedence;
38pub(crate) mod stmt;
39pub mod version;
40
41use diagnostics::ParseError;
42use php_ast::{Comment, Program};
43pub use version::PhpVersion;
44
45/// The result of parsing a PHP source string.
46pub struct ParseResult<'arena, 'src> {
47    /// The parsed AST. Always produced, even when errors are present.
48    pub program: Program<'arena, 'src>,
49    /// All comments found in the source, in source order.
50    /// Comments are not attached to AST nodes; callers can map them by span.
51    pub comments: Vec<Comment<'src>>,
52    /// Parse errors and diagnostics. Empty on a successful parse.
53    pub errors: Vec<ParseError>,
54}
55
56/// Parse PHP `source` using the latest supported PHP version (currently 8.5).
57///
58/// The `arena` is used for all AST allocations, giving callers control over
59/// memory lifetime. The returned [`ParseResult`] borrows from both the arena
60/// and the source string.
61pub fn parse<'arena, 'src>(
62    arena: &'arena bumpalo::Bump,
63    source: &'src str,
64) -> ParseResult<'arena, 'src> {
65    let mut parser = parser::Parser::new(arena, source);
66    let program = parser.parse_program();
67    ParseResult {
68        program,
69        comments: parser.take_comments(),
70        errors: parser.into_errors(),
71    }
72}
73
74/// Parse `source` targeting the given PHP `version`.
75///
76/// Syntax that requires a higher version than `version` is still parsed and
77/// included in the AST, but a [`diagnostics::ParseError::VersionTooLow`] error
78/// is also emitted so callers can report it to the user.
79pub fn parse_versioned<'arena, 'src>(
80    arena: &'arena bumpalo::Bump,
81    source: &'src str,
82    version: PhpVersion,
83) -> ParseResult<'arena, 'src> {
84    let mut parser = parser::Parser::with_version(arena, source, version);
85    let program = parser.parse_program();
86    ParseResult {
87        program,
88        comments: parser.take_comments(),
89        errors: parser.into_errors(),
90    }
91}