erg_parser/
build_ast.rs

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/// Summarize parsing and desugaring
23#[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                        // ExpectNextLine error must have msg otherwise it's a bug
82                        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}