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}