1use std::error::Error;
4use std::fmt::{Display, Formatter};
5use lexigram_core::log::{BufLog, LogReader, LogStatus};
6
7#[derive(Debug)]
10pub enum BuildErrorSource {
11 RuleTreeSet,
12 Dfa,
13 DfaBuilder,
14 LexerGen,
15 Lexi,
16 ProdRuleSet,
17 ParserGen,
18 Gram,
19}
20
21#[derive(Debug)]
22pub struct BuildError {
23 log: BufLog,
24 source: BuildErrorSource,
25}
26
27impl BuildError {
28 pub fn new(log: BufLog, source: BuildErrorSource) -> Self {
29 BuildError { log, source }
30 }
31
32 pub fn get_log(self) -> BufLog {
33 self.log
34 }
35}
36
37impl Display for BuildError {
38 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
39 writeln!(f, "Errors have occurred in {:?}:\n{}", self.source, self.log.get_messages_str())
40 }
41}
42
43impl Error for BuildError {
44}
45
46pub trait HasBuildErrorSource {
47 const SOURCE: BuildErrorSource;
48
49 fn get_build_error_source() -> BuildErrorSource {
50 Self::SOURCE
51 }
52}
53
54pub trait BuildFrom<S>: Sized {
62 #[must_use]
64 fn build_from(source: S) -> Self;
65}
66
67pub trait BuildInto<T>: Sized {
68 #[must_use]
70 fn build_into(self) -> T;
71}
72
73impl<S, T> BuildInto<T> for S
74where
75 T: BuildFrom<S>,
76{
77 #[inline]
79 fn build_into(self) -> T { T::build_from(self) }
80}
81
82impl<S> BuildFrom<S> for S {
83 fn build_from(source: S) -> Self {
84 source
85 }
86}
87
88pub trait TryBuildFrom<T>: Sized {
91 type Error;
93
94 fn try_build_from(source: T) -> Result<Self, Self::Error>;
96}
97
98pub trait TryBuildInto<T>: Sized {
99 type Error;
101
102 fn try_build_into(self) -> Result<T, Self::Error>;
104}
105
106impl<S, T> TryBuildInto<T> for S
107where
108 T: TryBuildFrom<S>,
109{
110 type Error = T::Error;
111
112 #[inline]
113 fn try_build_into(self) -> Result<T, T::Error> { T::try_build_from(self) }
114}
115
116impl<S, T> TryBuildFrom<S> for T
117where
118 S: LogReader<Item = BufLog> + HasBuildErrorSource,
119 T: LogReader<Item = BufLog> + BuildFrom<S> + HasBuildErrorSource,
120{
121 type Error = BuildError;
122
123 fn try_build_from(source: S) -> Result<Self, Self::Error> {
124 const VERBOSE: bool = false;
125 if VERBOSE {
126 println!("try_build_from <{}> -> <{}>: source messages\n{}",
127 std::any::type_name::<S>(), std::any::type_name::<T>(),
128 source.get_log().get_messages_str());
129 }
130 if source.get_log().has_no_errors() {
131 let target = T::build_from(source);
132 if VERBOSE {
133 println!("try_build_from <{}> -> <{}>: target messages\n{}",
134 std::any::type_name::<S>(), std::any::type_name::<T>(),
135 target.get_log().get_messages_str());
136 }
137 if target.get_log().has_no_errors() {
138 Ok(target)
139 } else {
140 Err(BuildError::new(target.give_log(), S::get_build_error_source()))
141 }
142 } else {
143 Err(BuildError::new(source.give_log(), S::get_build_error_source()))
144 }
145 }
146}