1#[doc(hidden)]
4pub extern crate log;
5#[doc(hidden)]
6pub extern crate pest;
7extern crate void;
8
9#[doc(inline)]
10pub use void::Void;
11
12use {
13 pest::{
14 iterators::{Pair, Pairs},
15 RuleType,
16 },
17 std::marker::PhantomData,
18};
19
20#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
22pub enum ConversionError<FatalError> {
23 NoMatch,
25 Malformed(FatalError),
27 Extraneous { current_node: &'static str },
29}
30
31use std::fmt;
32
33impl<FatalError> fmt::Display for ConversionError<FatalError>
34where
35 FatalError: fmt::Display,
36{
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 match self {
39 ConversionError::NoMatch => write!(f, "Rule did not match, failed to convert node"),
40 ConversionError::Malformed(fatalerror) => write!(f, "Malformed node: {fatalerror}"),
41 ConversionError::Extraneous { current_node, .. } => {
42 write!(f, "when converting {current_node}, found extraneous tokens")
43 }
44 }
45 }
46}
47
48use std::error;
49
50impl<FatalError> error::Error for ConversionError<FatalError>
51where
52 FatalError: error::Error + 'static,
53{
54 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
55 match self {
56 ConversionError::NoMatch => None,
57 ConversionError::Extraneous { .. } => None,
58 ConversionError::Malformed(ref fatalerror) => Some(fatalerror),
59 }
60 }
61}
62
63pub trait FromPest<'pest>: Sized {
65 type Rule: RuleType;
67 type FatalError;
69 fn from_pest(
77 pest: &mut Pairs<'pest, Self::Rule>,
78 ) -> Result<Self, ConversionError<Self::FatalError>>;
79}
80
81impl<'pest, Rule: RuleType, T: FromPest<'pest, Rule = Rule>> FromPest<'pest> for PhantomData<T> {
83 type Rule = Rule;
84 type FatalError = T::FatalError;
85 fn from_pest(pest: &mut Pairs<'pest, Rule>) -> Result<Self, ConversionError<T::FatalError>> {
86 T::from_pest(pest).map(|_| PhantomData)
87 }
88}
89
90impl<'pest, Rule: RuleType, T: FromPest<'pest, Rule = Rule>> FromPest<'pest> for Box<T> {
92 type Rule = Rule;
93 type FatalError = T::FatalError;
94 fn from_pest(pest: &mut Pairs<'pest, Rule>) -> Result<Self, ConversionError<T::FatalError>> {
95 T::from_pest(pest).map(Box::new)
96 }
97}
98
99impl<'pest, Rule: RuleType, T: FromPest<'pest, Rule = Rule>> FromPest<'pest> for Option<T> {
101 type Rule = Rule;
102 type FatalError = T::FatalError;
103 fn from_pest(pest: &mut Pairs<'pest, Rule>) -> Result<Self, ConversionError<T::FatalError>> {
104 match T::from_pest(pest) {
105 Err(ConversionError::NoMatch) => Ok(None),
106 result => result.map(Some),
107 }
108 }
109}
110
111impl<'pest, Rule: RuleType, T: FromPest<'pest, Rule = Rule>> FromPest<'pest> for Vec<T> {
113 type Rule = Rule;
114 type FatalError = T::FatalError;
115 fn from_pest(pest: &mut Pairs<'pest, Rule>) -> Result<Self, ConversionError<T::FatalError>> {
116 let mut acc = vec![];
117 loop {
118 match T::from_pest(pest) {
119 Ok(t) => acc.push(t),
120 Err(ConversionError::NoMatch) => break,
121 Err(error) => return Err(error),
122 }
123 }
124 Ok(acc)
125 }
126}
127
128impl<'pest, Rule: RuleType> FromPest<'pest> for Pair<'pest, Rule> {
130 type Rule = Rule;
131 type FatalError = Void;
132 fn from_pest(pest: &mut Pairs<'pest, Rule>) -> Result<Self, ConversionError<Void>> {
133 pest.next().ok_or(ConversionError::NoMatch)
134 }
135}
136
137macro_rules! impl_for_tuple {
138 () => {};
139 ($ty1:ident $($ty:ident)*) => {
140 impl<'pest, $ty1, $($ty,)* Rule: RuleType, FatalError> FromPest<'pest> for ($ty1, $($ty),*)
141 where
142 $ty1: FromPest<'pest, Rule=Rule, FatalError=FatalError>,
143 $($ty: FromPest<'pest, Rule=Rule, FatalError=FatalError>,)*
144 {
145 type Rule = Rule;
146 type FatalError = FatalError;
147 fn from_pest(pest: &mut Pairs<'pest, Rule>)
148 -> Result<Self, ConversionError<FatalError>>
149 {
150 let mut clone = pest.clone();
151 let this = (
152 $ty1::from_pest(&mut clone)?,
153 $($ty::from_pest(&mut clone)?),*
154 );
155 *pest = clone;
156 Ok(this)
157 }
158 }
159 impl_for_tuple!($($ty)*);
160 };
161}
162
163impl_for_tuple!(A B C D);