cflp/
lib.rs

1#![doc=include_str!("../README.md")]
2#![cfg_attr(
3    docs,
4    feature(doc_auto_cfg),
5    deny(rustdoc::broken_intra_doc_links, missing_docs)
6)]
7#![cfg_attr(
8    not(docs),
9    warn(rustdoc::broken_intra_doc_links, missing_docs)
10)]
11use std::fmt::{Debug, Formatter};
12/// # Parser derive macro
13///
14/// Derive macro used for the [`Parser`] trait. See the book for how to use this macro
15pub use cflp_macros::{Parser, PartialEqRef};
16
17/// # Parser error struct
18///
19/// This is the error type returned by the [`Parser`] trait when an error is found. The types are
20/// different to allow the iterator values to contain additional data that does need to be compared
21/// such as position within a file. When this is returned it means that the `found` value is not
22/// equal to the `expected` value.
23pub struct Error<F, E> {
24	/// Value that was found in the input iterator
25	pub found: Option<F>,
26	/// Value that was expected in the input iterator
27	pub expected: E
28}
29
30impl<F: Debug, E: Debug> Debug for Error<F, E> {
31	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
32		f.debug_struct("cflp::Error")
33			.field("found", &self.found)
34			.field("expected", &self.expected)
35			.finish()
36	}
37}
38
39/// # Parser trait
40///
41/// Geneal trait for parsing a stream of input tokens. This can be derived using
42/// [`#[derive(Parser)]`](cflp_macros::Parser)
43///
44/// ## Generics
45/// * `I` - Type in input iterator. Token with class and other data
46/// * `C` - Type to compare to. Token class
47/// * `R` - Ok returned type. This will either be `Self` or [`NodeWrapper<Self, D>`]
48pub trait Parser<I, C: PartialEq<C>, R = Self> {
49	/// Parse an AST from a given input. Returns `Ok(Self)` (optionally wrapped) if the AST is
50	/// found and `Err(cflp::Error<I, C>)` if the AST was not found
51	fn parse<T: Iterator<Item=I> + Clone>(src: &mut T) -> Result<R, Error<I, C>> where Self: Sized {
52		<Self as Parser<I, C, R>>::parse_with_recursion(src, true)
53	}
54	
55	/// *THIS SHOULD NOT BE CALLED. USE [`parse`](Parser::parse) INSTEAD*
56	///
57	/// Performs [`parse`](Parser::parse) with restrictions on zero-consumption branching.
58	fn parse_with_recursion<T: Iterator<Item=I> + Clone>(src: &mut T, recurse: bool) -> Result<R, Error<I, C>> where Self: Sized;
59}
60
61/// # Node wrapper
62///
63/// This struct is used to wrap a node returned from parsing. It contains the
64/// [wrapped node](Self::node), and [starting](Self::start) and [ending](Self::end) data from
65/// the [`NodeData`] trait
66#[derive(Clone)]
67pub struct NodeWrapper<T: Sized, D: Sized + Clone + Default> {
68	/// Wrapped node
69	pub node: T,
70	/// Starting data
71	pub start: D,
72	/// Ending data
73	pub end: D
74}
75
76impl<T: Sized + Debug, D: Sized + Debug + Default + Clone> Debug for NodeWrapper<T, D> {
77	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78		write!(f, "NodeWrapper {{ node: {:?}, start: {:?}, end: {:?} }}", self.node, self.start, self.end)
79	}
80}
81
82impl<T: Sized, D: Sized + Clone + Default> NodeData<D> for NodeWrapper<T, D> {
83	#[inline] fn start(&self) -> D { self.start.clone() }
84	#[inline] fn end(&self) -> D { self.end.clone() }
85}
86
87/// # Node data
88///
89/// Access starting and ending node data for any node. Required if you want to have a wrapped parser
90pub trait NodeData<T: Sized, D: Sized = ()> {
91	/// Get the starting node data
92	fn start(&self) -> T;
93	/// Get the ending node data
94	fn end(&self) -> T;
95}