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 Lexigram,
20}
21
22#[derive(Debug)]
23pub struct BuildError {
24 log: BufLog,
25 source: BuildErrorSource,
26}
27
28impl BuildError {
29 pub fn new(log: BufLog, source: BuildErrorSource) -> Self {
30 BuildError { log, source }
31 }
32
33 pub fn get_log(self) -> BufLog {
34 self.log
35 }
36}
37
38impl Display for BuildError {
39 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40 writeln!(f, "Errors have occurred in {:?}:\n{}", self.source, self.log.get_messages_str())
41 }
42}
43
44impl Error for BuildError {
45}
46
47pub trait HasBuildErrorSource {
48 const SOURCE: BuildErrorSource;
49
50 fn get_build_error_source() -> BuildErrorSource {
51 Self::SOURCE
52 }
53}
54
55pub trait BuildFrom<S>: Sized {
63 #[must_use]
65 fn build_from(source: S) -> Self;
66}
67
68pub trait BuildInto<T>: Sized {
69 #[must_use]
71 fn build_into(self) -> T;
72}
73
74impl<S, T> BuildInto<T> for S
75where
76 T: BuildFrom<S>,
77{
78 #[inline]
80 fn build_into(self) -> T { T::build_from(self) }
81}
82
83impl<S> BuildFrom<S> for S {
84 fn build_from(source: S) -> Self {
85 source
86 }
87}
88
89pub trait TryBuildFrom<T>: Sized {
92 type Error;
94
95 fn try_build_from(source: T) -> Result<Self, Self::Error>;
97}
98
99pub trait TryBuildInto<T>: Sized {
100 type Error;
102
103 fn try_build_into(self) -> Result<T, Self::Error>;
105}
106
107impl<S, T> TryBuildInto<T> for S
108where
109 T: TryBuildFrom<S>,
110{
111 type Error = T::Error;
112
113 #[inline]
114 fn try_build_into(self) -> Result<T, T::Error> { T::try_build_from(self) }
115}
116
117impl<S, T> TryBuildFrom<S> for T
118where
119 S: LogReader<Item = BufLog> + HasBuildErrorSource,
120 T: LogReader<Item = BufLog> + BuildFrom<S> + HasBuildErrorSource,
121{
122 type Error = BuildError;
123
124 fn try_build_from(source: S) -> Result<Self, Self::Error> {
125 const VERBOSE: bool = false;
126 if VERBOSE {
127 println!("try_build_from <{}> -> <{}>: source messages\n{}",
128 std::any::type_name::<S>(), std::any::type_name::<T>(),
129 source.get_log().get_messages_str());
130 }
131 if source.get_log().has_no_errors() {
132 let target = T::build_from(source);
133 if VERBOSE {
134 println!("try_build_from <{}> -> <{}>: target messages\n{}",
135 std::any::type_name::<S>(), std::any::type_name::<T>(),
136 target.get_log().get_messages_str());
137 }
138 if target.get_log().has_no_errors() {
139 Ok(target)
140 } else {
141 Err(BuildError::new(target.give_log(), S::get_build_error_source()))
142 }
143 } else {
144 Err(BuildError::new(source.give_log(), S::get_build_error_source()))
145 }
146 }
147}