pest_tree/
lib.rs

1//! An easy and simple way to convert your dynamic [pest] trees into an AST built from structs and enums.
2//!
3//! This crate is centered around the [`pest_tree_derive::PestTree`] derive macro.
4//! The macro uses the `pest_tree` attribute macro to help derive the trait
5//! [`pest_tree_derive::PestTree`] for the relevant struct/enum.
6#![allow(
7    dead_code,
8    irrefutable_let_patterns,
9    unused_variables,
10    unused_imports,
11    unused
12)]
13#![warn(missing_docs)]
14#![warn(clippy::missing_docs_in_private_items)]
15
16use std::{fmt::Display, marker::PhantomData, rc::Rc};
17pub mod errors;
18pub use ariadne;
19pub use errors::*;
20pub mod auto;
21pub use auto::*;
22pub mod validator;
23use std::rc;
24pub use validator::*;
25
26/// Contains information about the original source file/string.
27///
28/// This struct is often passed around in an [`std::rc::Rc`] and is used to show [`TreeError`] sources.
29///
30/// ```ignore
31/// // to initialize ctx
32/// use pest_tree::ParsingContext;
33/// use std::rc::Rc;
34/// let ctx = Rc::new(ParsingContext {
35///     filename: "mystatement.lang".to_string(),
36///     contents: "let a = 3;".to_string()
37/// });
38/// ```
39/// `ctx` can then be passed into [`PestTree::with_pair`].
40#[derive(Debug, Clone)]
41pub struct ParsingContext {
42    /// Filename. This will be shown on top of errors.
43    pub filename: String,
44    /// Contents of the file being parsed. The [`TreeError`]s formed require this for proper pretty printing.
45    pub contents: String,
46}
47impl ParsingContext {
48    /// Initialize a [`ParsingContext`] from [`str`]s.
49    pub fn new_file(filename: &str, contents: &str) -> Self {
50        Self {
51            filename: filename.to_string(),
52            contents: contents.to_string(),
53        }
54    }
55}
56
57/// Implemented for types that can be parsed from [`pest::iterators::Pair`].
58///
59/// Contains the function [`PestTree::with_pair`], which a [`pest::iterators::Pair`] to be converted and a
60/// [`Rc<ParsingContext>`] that specifies the original source. This trait is normally implemented by the
61/// [`pest_tree_derive::PestTree`] derive macro, but you can also implement it yourself.
62pub trait PestTree<R: pest::RuleType> {
63    /// Convert a [`pest::iterators::Pair`] to the implementor.
64    ///
65    /// A context is also specified so that error reporting via [`ariadne`] is possible.
66    /// Returns `Result<T, TreeError>`. [`TreeError`] can be pretty printed.
67    ///
68    /// ```ignore
69    /// let parsed_iter = PestParser::parse(Rule::a, ctx.contents.clone()).unwrap();
70    /// // ::parse returns a Pairs. This Pairs only contains 1 Pair, which we will be using.
71    /// let pair = parsed_iter.next().unwrap();
72    /// // struct A implements PestTree
73    /// // ctx was defined earlier
74    /// let a: A = A::from_pair(pair, ctx.clone()).unwrap();
75    /// // now the pair has been parsed into `a`.
76    /// ```
77    fn with_pair(
78        pair: pest::iterators::Pair<'_, R>,
79        context: Rc<ParsingContext>,
80    ) -> Result<Self, TreeError<R>>
81    where
82        Self: Sized;
83}