1use std::str::FromStr;
2
3use super::ParseContext;
4use crate::parse::annotations::parse_annotation;
5use crate::parse::definitions::parse_definition;
6use crate::parse::identifiers::{parse_identifier, parse_qualified_identifier};
7use crate::parse::parse_comment;
8use sdml_core::error::Error;
9use sdml_core::load::ModuleLoader as ModuleLoaderTrait;
10use sdml_core::model::annotations::HasAnnotations;
11use sdml_core::model::identifiers::Identifier;
12use sdml_core::model::modules::Module;
13use sdml_core::model::modules::{
14 HeaderValue, Import, ImportStatement, MemberImport, ModuleImport, ModulePath,
15};
16use sdml_core::model::HasSourceSpan;
17use sdml_core::syntax::{
18 FIELD_NAME_BASE, FIELD_NAME_BODY, FIELD_NAME_NAME, FIELD_NAME_RENAME, FIELD_NAME_SEGMENT,
19 FIELD_NAME_VERSION_INFO, FIELD_NAME_VERSION_URI, NODE_KIND_ANNOTATION, NODE_KIND_DEFINITION,
20 NODE_KIND_FROM_CLAUSE, NODE_KIND_IDENTIFIER, NODE_KIND_IMPORT_STATEMENT, NODE_KIND_IRI,
21 NODE_KIND_LINE_COMMENT, NODE_KIND_MEMBER_IMPORT, NODE_KIND_MODULE_BODY,
22 NODE_KIND_MODULE_IMPORT, NODE_KIND_MODULE_PATH_ABSOLUTE, NODE_KIND_MODULE_PATH_RELATIVE,
23 NODE_KIND_MODULE_PATH_ROOT, NODE_KIND_QUALIFIED_IDENTIFIER, NODE_KIND_QUOTED_STRING,
24};
25use tree_sitter::{Node, TreeCursor};
26use url::Url;
27
28pub(crate) fn parse_module<'a>(
33 context: &mut ParseContext<'a>,
34 cursor: &mut TreeCursor<'a>,
35) -> Result<Module, Error> {
36 let node = cursor.node();
37 rule_fn!("module", node);
38 context.check_if_error(&node, RULE_NAME)?;
39
40 let child = node_field_named!(
41 context,
42 RULE_NAME,
43 node,
44 FIELD_NAME_NAME,
45 NODE_KIND_IDENTIFIER
46 );
47 let name = parse_identifier(context, &child)?;
48 let mut module = Module::new(name).with_source_span(node.into());
49
50 if let Some(child) =
51 optional_node_field_named!(context, RULE_NAME, node, FIELD_NAME_BASE, NODE_KIND_IRI)
52 {
53 let uri = parse_uri(context, &child)?;
54 module.set_base_uri(HeaderValue::from(uri).with_source_span(child.into()));
55 }
56
57 if let Some(child) = optional_node_field_named!(
58 context,
59 RULE_NAME,
60 node,
61 FIELD_NAME_VERSION_INFO,
62 NODE_KIND_QUOTED_STRING
63 ) {
64 let info = parse_quoted_string(context, &child)?;
65 module.set_version_info(HeaderValue::from(info).with_source_span(child.into()));
66 }
67
68 if let Some(child) = optional_node_field_named!(
69 context,
70 RULE_NAME,
71 node,
72 FIELD_NAME_VERSION_URI,
73 NODE_KIND_IRI
74 ) {
75 let uri = parse_uri(context, &child)?;
76 module.set_version_uri(HeaderValue::from(uri).with_source_span(child.into()));
77 }
78
79 let child = node_field_named!(
80 context,
81 RULE_NAME,
82 node,
83 FIELD_NAME_BODY,
84 NODE_KIND_MODULE_BODY
85 );
86 parse_module_body(context, &mut module, &mut child.walk())?;
87
88 Ok(module)
89}
90
91#[inline(always)]
92fn parse_uri<'a>(context: &mut ParseContext<'a>, node: &Node<'a>) -> Result<Url, Error> {
93 let value = context.node_source(node)?;
94 Ok(Url::from_str(&value[1..(value.len() - 1)]).expect("Invalid value for IriReference"))
96}
97
98#[inline(always)]
99fn parse_quoted_string<'a>(
100 context: &mut ParseContext<'a>,
101 node: &Node<'a>,
102) -> Result<String, Error> {
103 let node_value = context.node_source(node)?;
104 Ok(node_value[1..(node_value.len() - 1)].to_string())
105}
106
107fn parse_module_body<'a>(
108 context: &mut ParseContext<'a>,
109 module: &mut Module,
110 cursor: &mut TreeCursor<'a>,
111) -> Result<(), Error> {
112 rule_fn!("module_body", cursor.node());
113
114 for node in cursor.node().named_children(cursor) {
115 check_node!(context, RULE_NAME, &node);
116 match node.kind() {
117 NODE_KIND_IMPORT_STATEMENT => {
118 module.add_to_imports(parse_import_statement(context, &mut node.walk())?);
119 }
120 NODE_KIND_ANNOTATION => {
121 module.add_to_annotations(parse_annotation(context, &mut node.walk())?);
122 }
123 NODE_KIND_DEFINITION => {
124 module.add_to_definitions(parse_definition(context, &mut node.walk())?)?;
125 }
126 NODE_KIND_LINE_COMMENT => {
127 let comment = parse_comment(context, &node)?;
128 context.push_comment(comment);
129 }
130 _ => {
131 unexpected_node!(
132 context,
133 RULE_NAME,
134 node,
135 [
136 NODE_KIND_IMPORT_STATEMENT,
137 NODE_KIND_ANNOTATION,
138 NODE_KIND_DEFINITION,
139 ]
140 );
141 }
142 }
143 }
144 Ok(())
145}
146
147fn parse_import_statement<'a>(
148 context: &mut ParseContext<'a>,
149 cursor: &mut TreeCursor<'a>,
150) -> Result<ImportStatement, Error> {
151 rule_fn!("import_statement", cursor.node());
152
153 let mut import = ImportStatement::default().with_source_span(cursor.node().into());
154
155 for node in cursor.node().named_children(cursor) {
156 check_node!(context, RULE_NAME, &node);
157 match node.kind() {
158 NODE_KIND_FROM_CLAUSE => {
159 import.set_from_module_path(parse_from_clause(context, &mut node.walk())?);
160 }
161 NODE_KIND_MODULE_IMPORT => {
162 let child = node_field_named!(
163 context,
164 RULE_NAME,
165 node,
166 FIELD_NAME_NAME,
167 NODE_KIND_IDENTIFIER
168 );
169 let mut imported: ModuleImport = parse_identifier(context, &child)?.into();
170 imported.set_source_span(node.into());
171
172 if let Some(child) = optional_node_field_named!(
173 context,
174 RULE_NAME,
175 node,
176 FIELD_NAME_VERSION_URI,
177 NODE_KIND_IRI
178 ) {
179 let uri = parse_uri(context, &child)?;
180 imported.set_version_uri(HeaderValue::from(uri).with_source_span(child.into()));
181 }
182
183 if let Some(child) = optional_node_field_named!(
184 context,
185 RULE_NAME,
186 node,
187 FIELD_NAME_RENAME,
188 NODE_KIND_IDENTIFIER
189 ) {
190 imported.set_rename_as(parse_identifier(context, &child)?)
191 }
192
193 let imported: Import = imported.into();
194 context.add_import(&imported)?;
195 import.add_to_imports(imported);
196 }
197 NODE_KIND_MEMBER_IMPORT => {
198 let child = node_field_named!(
199 context,
200 RULE_NAME,
201 node,
202 FIELD_NAME_NAME,
203 NODE_KIND_QUALIFIED_IDENTIFIER
204 );
205 let mut imported: MemberImport =
206 parse_qualified_identifier(context, &mut child.walk())?.into();
207 imported.set_source_span(child.into());
208
209 if let Some(child) = optional_node_field_named!(
210 context,
211 RULE_NAME,
212 node,
213 FIELD_NAME_RENAME,
214 NODE_KIND_IDENTIFIER
215 ) {
216 imported.set_rename_as(parse_identifier(context, &child)?)
217 }
218
219 let imported: Import = imported.into();
220 context.add_import(&imported)?;
221 import.add_to_imports(imported);
222 }
223 NODE_KIND_LINE_COMMENT => {}
224 _ => {
225 unexpected_node!(
226 context,
227 RULE_NAME,
228 node,
229 [
230 NODE_KIND_FROM_CLAUSE,
231 NODE_KIND_MODULE_IMPORT,
232 NODE_KIND_MEMBER_IMPORT,
233 ]
234 );
235 }
236 }
237 }
238 Ok(import)
239}
240
241fn parse_from_clause<'a>(
242 context: &mut ParseContext<'a>,
243 cursor: &mut TreeCursor<'a>,
244) -> Result<ModulePath, Error> {
245 rule_fn!("from_clause", cursor.node());
246
247 if let Some(child) = cursor.node().named_children(cursor).next() {
248 check_node!(context, RULE_NAME, &child);
249 match child.kind() {
250 NODE_KIND_MODULE_PATH_ABSOLUTE => {
251 return Ok(ModulePath::absolute(parse_module_path(
252 context,
253 &mut child.walk(),
254 )?))
255 }
256 NODE_KIND_MODULE_PATH_RELATIVE => {
257 return Ok(ModulePath::relative(parse_module_path(
258 context,
259 &mut child.walk(),
260 )?))
261 }
262 NODE_KIND_MODULE_PATH_ROOT => return Ok(ModulePath::root()),
263 _ => {
264 unexpected_node!(
265 context,
266 RULE_NAME,
267 child,
268 [
269 NODE_KIND_MODULE_PATH_ABSOLUTE,
270 NODE_KIND_MODULE_PATH_RELATIVE,
271 NODE_KIND_MODULE_PATH_ROOT,
272 ]
273 );
274 }
275 }
276 }
277 unreachable!()
278}
279
280fn parse_module_path<'a>(
281 context: &mut ParseContext<'a>,
282 cursor: &mut TreeCursor<'a>,
283) -> Result<Vec<Identifier>, Error> {
284 rule_fn!("module_path", cursor.node());
285 let mut path = Vec::default();
286
287 for child in cursor
288 .node()
289 .children_by_field_name(FIELD_NAME_SEGMENT, cursor)
290 {
291 check_node!(context, RULE_NAME, &child, NODE_KIND_IDENTIFIER);
292 path.push(parse_identifier(context, &child)?);
293 }
294
295 Ok(path)
296}