1use erg_common::error::ErrorDisplay;
2use erg_common::error::ErrorKind;
3use erg_common::traits::{ExitStatus, New, Runnable};
4use erg_common::Str;
5use erg_common::{config::ErgConfig, traits::BlockKind};
6
7use crate::ast::AST;
8use crate::desugar::Desugarer;
9use crate::error::{CompleteArtifact, IncompleteArtifact, ParserRunnerError, ParserRunnerErrors};
10use crate::parse::ParserRunner;
11
12pub trait ASTBuildable: New {
13 fn build_ast(
14 &mut self,
15 src: String,
16 ) -> Result<
17 CompleteArtifact<AST, ParserRunnerErrors>,
18 IncompleteArtifact<AST, ParserRunnerErrors>,
19 >;
20}
21
22#[derive(Debug, Default)]
24pub struct ASTBuilder {
25 runner: ParserRunner,
26}
27
28impl New for ASTBuilder {
29 #[inline]
30 fn new(cfg: ErgConfig) -> Self {
31 Self {
32 runner: ParserRunner::new(cfg),
33 }
34 }
35}
36
37impl Runnable for ASTBuilder {
38 type Err = ParserRunnerError;
39 type Errs = ParserRunnerErrors;
40 const NAME: &'static str = "Erg AST builder";
41
42 #[inline]
43 fn cfg(&self) -> &ErgConfig {
44 self.runner.cfg()
45 }
46 #[inline]
47 fn cfg_mut(&mut self) -> &mut ErgConfig {
48 self.runner.cfg_mut()
49 }
50
51 #[inline]
52 fn finish(&mut self) {}
53
54 #[inline]
55 fn initialize(&mut self) {}
56
57 #[inline]
58 fn clear(&mut self) {}
59
60 fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
61 let src = self.cfg_mut().input.read();
62 let artifact = self.build(src).map_err(|iart| iart.errors)?;
63 println!("{}", artifact.ast);
64 Ok(ExitStatus::OK)
65 }
66
67 fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> {
68 let artifact = self.build(src).map_err(|iart| iart.errors)?;
69 Ok(format!("{}", artifact.ast))
70 }
71
72 fn expect_block(&self, src: &str) -> BlockKind {
73 let mut parser = ParserRunner::new(self.cfg().clone());
74 match parser.eval(src.to_string()) {
75 Err(errs) => {
76 let kind = errs
77 .iter()
78 .filter(|e| e.core().kind == ErrorKind::ExpectNextLine)
79 .map(|e| {
80 let msg = e.core().sub_messages.last().unwrap();
81 msg.get_msg().first().unwrap().to_owned()
83 })
84 .next();
85 if let Some(kind) = kind {
86 return BlockKind::from(kind.as_str());
87 }
88 if errs
89 .iter()
90 .any(|err| err.core.main_message.contains("\"\"\""))
91 {
92 return BlockKind::MultiLineStr;
93 }
94 BlockKind::Error
95 }
96 Ok(_) => {
97 if src.contains("Class") {
98 return BlockKind::ClassDef;
99 }
100 BlockKind::None
101 }
102 }
103 }
104}
105
106impl ASTBuildable for ASTBuilder {
107 fn build_ast(
108 &mut self,
109 src: String,
110 ) -> Result<
111 CompleteArtifact<AST, ParserRunnerErrors>,
112 IncompleteArtifact<AST, ParserRunnerErrors>,
113 > {
114 self.build(src)
115 }
116}
117
118impl ASTBuilder {
119 #[inline]
120 pub fn new(cfg: ErgConfig) -> Self {
121 New::new(cfg)
122 }
123
124 pub fn build(
125 &mut self,
126 src: String,
127 ) -> Result<
128 CompleteArtifact<AST, ParserRunnerErrors>,
129 IncompleteArtifact<AST, ParserRunnerErrors>,
130 > {
131 let name = Str::from(self.runner.cfg().input.filename());
132 let mut desugarer = Desugarer::new();
133 let artifact = self.runner.parse(src).map_err(|iart| {
134 iart.map_mod(|module| {
135 let module = desugarer.desugar(module);
136 AST::new(name.clone(), module)
137 })
138 })?;
139 let module = desugarer.desugar(artifact.ast);
140 let ast = AST::new(name, module);
141 Ok(CompleteArtifact::new(
142 ast,
143 ParserRunnerErrors::convert(self.input(), artifact.warns),
144 ))
145 }
146
147 pub fn build_without_desugaring(
148 &mut self,
149 src: String,
150 ) -> Result<
151 CompleteArtifact<AST, ParserRunnerErrors>,
152 IncompleteArtifact<AST, ParserRunnerErrors>,
153 > {
154 let name = Str::from(self.runner.cfg().input.filename());
155 let artifact = self
156 .runner
157 .parse(src)
158 .map_err(|iart| iart.map_mod(|module| AST::new(name.clone(), module)))?;
159 let ast = AST::new(name, artifact.ast);
160 Ok(CompleteArtifact::new(
161 ast,
162 ParserRunnerErrors::convert(self.input(), artifact.warns),
163 ))
164 }
165}