dada_parser/
module_body.rs1use dada_ir_ast::{
2 ast::{
3 AstAggregate, AstFunction, AstItem, AstMainFunction, AstModule, AstPath, AstStatement,
4 AstUse, SpanVec,
5 },
6 diagnostic::Diagnostic,
7 span::Spanned,
8};
9
10use crate::tokenizer::operator;
11
12use super::{Expected, Parse, ParseFail, Parser, miscellaneous::OrOptParse, tokenizer::Keyword};
13
14impl<'db> Parse<'db> for AstModule<'db> {
15 type Output = Self;
16
17 fn opt_parse(
18 db: &'db dyn crate::Db,
19 parser: &mut Parser<'_, 'db>,
20 ) -> Result<Option<Self>, ParseFail<'db>> {
21 let name = parser.last_span().source_file(db).module_name(db);
23
24 let mut items: Vec<AstItem<'db>> = vec![];
26 let mut statements = vec![];
27 let start_span = parser.peek_span();
28 while parser.peek().is_some() {
29 if statements.is_empty() {
30 match AstItem::opt_parse(db, parser) {
31 Ok(Some(v)) => {
32 items.push(v);
33 continue;
34 }
35
36 Err(e) => {
37 parser.push_diagnostic(e.into_diagnostic(db));
38 continue;
39 }
40
41 Ok(None) => {}
42 }
43 }
44
45 match AstStatement::opt_parse(db, parser) {
46 Ok(Some(s)) => {
47 statements.push(s);
48 continue;
49 }
50
51 Err(e) => {
52 parser.push_diagnostic(e.into_diagnostic(db));
53 continue;
54 }
55
56 Ok(None) => {}
57 }
58
59 parser.eat_next_token().unwrap();
60 parser.push_diagnostic(Diagnostic::error(
61 db,
62 parser.last_span(),
63 "expected a statement or a module-level item",
64 ));
65 }
66
67 if let Some(first) = statements.first()
69 && let Some(last) = statements.last()
70 {
71 let span = first.span(db).to(db, last.span(db));
72 let main_fn = AstMainFunction::new(
73 db,
74 SpanVec {
75 span,
76 values: statements,
77 },
78 );
79 items.push(main_fn.into());
80 }
81
82 Ok(Some(AstModule::new(
83 db,
84 name,
85 SpanVec {
86 span: start_span.to(db, parser.last_span()),
87 values: items,
88 },
89 )))
90 }
91
92 fn expected() -> Expected {
93 panic!("infallible")
94 }
95}
96
97impl<'db> Parse<'db> for AstItem<'db> {
98 type Output = Self;
99
100 fn opt_parse(
101 db: &'db dyn crate::Db,
102 parser: &mut Parser<'_, 'db>,
103 ) -> Result<Option<Self>, ParseFail<'db>> {
104 AstAggregate::opt_parse(db, parser)
105 .or_opt_parse::<Self, AstUse<'db>>(db, parser)
106 .or_opt_parse::<Self, AstFunction<'db>>(db, parser)
107 }
108
109 fn expected() -> Expected {
110 panic!("module-level item (class, function, use)")
111 }
112}
113
114impl<'db> Parse<'db> for AstUse<'db> {
116 type Output = Self;
117
118 fn opt_parse(
119 db: &'db dyn crate::Db,
120 parser: &mut Parser<'_, 'db>,
121 ) -> Result<Option<Self>, ParseFail<'db>> {
122 let Ok(start) = parser.eat_keyword(Keyword::Use) else {
123 return Ok(None);
124 };
125
126 let crate_name = parser.eat_id()?;
127 let _dot = parser.eat_op(operator::DOT)?;
128 let path = AstPath::eat(db, parser)?;
129
130 let as_id = if parser.eat_keyword(Keyword::As).is_ok() {
131 Some(parser.eat_id()?)
132 } else {
133 None
134 };
135
136 Ok(Some(AstUse::new(
137 db,
138 start.to(db, parser.last_span()),
139 crate_name,
140 path,
141 as_id,
142 )))
143 }
144
145 fn expected() -> Expected {
146 Expected::Keyword(Keyword::Use)
147 }
148}