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}