sdml_parse/parse/definitions/
classes.rs1use crate::parse::annotations::parse_annotation;
2use crate::parse::constraints::{
3 parse_function_body, parse_function_cardinality_expression, parse_function_signature,
4};
5use crate::parse::definitions::parse_annotation_only_body;
6use crate::parse::identifiers::{parse_identifier, parse_identifier_reference};
7use crate::parse::{parse_comment, ParseContext};
8use sdml_core::error::Error;
9use sdml_core::load::ModuleLoader as ModuleLoaderTrait;
10use sdml_core::model::annotations::{Annotation, HasAnnotations};
11use sdml_core::model::definitions::{
12 MethodDef, TypeClassArgument, TypeClassBody, TypeClassDef, TypeClassReference, TypeVariable,
13};
14use sdml_core::model::{HasOptionalBody, HasSourceSpan};
15use sdml_core::syntax::{
16 FIELD_NAME_ARGUMENTS, FIELD_NAME_BODY, FIELD_NAME_CARDINALITY, FIELD_NAME_NAME,
17 FIELD_NAME_RESTRICTION, FIELD_NAME_SIGNATURE, FIELD_NAME_VARIABLE, FIELD_NAME_WILDCARD,
18 NODE_KIND_ANNOTATION, NODE_KIND_ANNOTATION_ONLY_BODY, NODE_KIND_FUNCTION_BODY,
19 NODE_KIND_FUNCTION_SIGNATURE, NODE_KIND_IDENTIFIER, NODE_KIND_IDENTIFIER_REFERENCE,
20 NODE_KIND_LINE_COMMENT, NODE_KIND_METHOD_DEF, NODE_KIND_TYPE_CLASS_BODY,
21 NODE_KIND_TYPE_CLASS_REFERENCE, NODE_KIND_TYPE_OP_COMBINER,
22};
23use tree_sitter::TreeCursor;
24
25pub(super) fn parse_type_class_def<'a>(
30 context: &mut ParseContext<'a>,
31 cursor: &mut TreeCursor<'a>,
32) -> Result<TypeClassDef, Error> {
33 let node = cursor.node();
34 rule_fn!("type_class_def", node);
35
36 let child = node_field_named!(
37 context,
38 RULE_NAME,
39 node,
40 FIELD_NAME_NAME,
41 NODE_KIND_IDENTIFIER
42 );
43 let name = parse_identifier(context, &child)?;
44
45 let mut variables: Vec<TypeVariable> = Default::default();
46
47 for child in node.children_by_field_name(FIELD_NAME_VARIABLE, cursor) {
48 check_node!(context, RULE_NAME, &node);
49 variables.push(parse_type_variable(context, &mut child.walk())?);
50 }
51
52 let mut type_class = TypeClassDef::new(name.clone(), variables).with_source_span(node.into());
53
54 context.start_type(&name)?;
55
56 if let Some(child) = optional_node_field_named!(
57 context,
58 RULE_NAME,
59 node,
60 FIELD_NAME_BODY,
61 NODE_KIND_TYPE_CLASS_BODY
62 ) {
63 let body = parse_type_class_body(context, &mut child.walk())?;
64 type_class.set_body(body);
65 }
66
67 context.end_type();
68 Ok(type_class)
69}
70
71fn parse_type_variable<'a>(
72 context: &mut ParseContext<'a>,
73 cursor: &mut TreeCursor<'a>,
74) -> Result<TypeVariable, Error> {
75 let node = cursor.node();
76 rule_fn!("type_variable", node);
77
78 let child = node_field_named!(
79 context,
80 RULE_NAME,
81 node,
82 FIELD_NAME_NAME,
83 NODE_KIND_IDENTIFIER
84 );
85 let name = parse_identifier(context, &child)?;
86 context.start_type(&name)?;
87
88 let mut variable = TypeVariable::new(name).with_source_span(node.into());
89
90 if let Some(child) = node.child_by_field_name(FIELD_NAME_CARDINALITY) {
91 context.check_if_error(&child, RULE_NAME)?;
92 let cardinality = parse_function_cardinality_expression(context, &mut child.walk())?;
93 variable.set_cardinality(cardinality);
94 }
95
96 if let Some(child) =
97 optional_node_field_named!(context, RULE_NAME, node, FIELD_NAME_RESTRICTION)
98 {
99 let restrictions = parse_type_variable_restriction(context, &mut child.walk())?;
100 variable.extend_restrictions(restrictions);
101 }
102
103 Ok(variable)
104}
105
106fn parse_type_variable_restriction<'a>(
107 context: &mut ParseContext<'a>,
108 cursor: &mut TreeCursor<'a>,
109) -> Result<Vec<TypeClassReference>, Error> {
110 let node = cursor.node();
111 rule_fn!("type_variable_restriction", node);
112 let mut restrictions = Vec::default();
113
114 for child in node.named_children(cursor) {
115 check_node!(context, RULE_NAME, &node);
116 match child.kind() {
117 NODE_KIND_TYPE_CLASS_REFERENCE => {
118 restrictions.push(parse_type_class_reference(context, &mut child.walk())?);
119 }
120 NODE_KIND_TYPE_OP_COMBINER => {}
121 NODE_KIND_LINE_COMMENT => {}
122 _ => {
123 unexpected_node!(
124 context,
125 RULE_NAME,
126 node,
127 [NODE_KIND_TYPE_CLASS_REFERENCE, NODE_KIND_TYPE_OP_COMBINER,]
128 );
129 }
130 }
131 }
132
133 Ok(restrictions)
134}
135
136fn parse_type_class_reference<'a>(
137 context: &mut ParseContext<'a>,
138 cursor: &mut TreeCursor<'a>,
139) -> Result<TypeClassReference, Error> {
140 let node = cursor.node();
141 rule_fn!("type_class_reference", node);
142
143 let child = node_field_named!(
144 context,
145 RULE_NAME,
146 node,
147 FIELD_NAME_NAME,
148 NODE_KIND_IDENTIFIER_REFERENCE
149 );
150 let name = parse_identifier_reference(context, &mut child.walk())?;
151 let mut result = TypeClassReference::new(name).with_source_span(node.into());
152
153 if let Some(child) = optional_node_field_named!(context, RULE_NAME, node, FIELD_NAME_ARGUMENTS)
154 {
155 if node.child_by_field_name(FIELD_NAME_WILDCARD).is_some() {
156 result.add_to_arguments(TypeClassArgument::Wildcard);
157 } else {
158 for node in child.children_by_field_name(FIELD_NAME_VARIABLE, cursor) {
159 check_node!(context, RULE_NAME, &node);
160 let variable = parse_type_class_reference(context, &mut node.walk())?;
161 result.add_to_arguments(TypeClassArgument::Reference(Box::new(variable)));
162 }
163 }
164 }
165
166 Ok(result)
167}
168
169pub(crate) fn parse_type_class_body<'a>(
170 context: &mut ParseContext<'a>,
171 cursor: &mut TreeCursor<'a>,
172) -> Result<TypeClassBody, Error> {
173 rule_fn!("type_class_body", cursor.node());
174 let mut body = TypeClassBody::default().with_source_span(cursor.node().into());
175
176 for node in cursor.node().named_children(cursor) {
177 check_node!(context, RULE_NAME, &node);
178 match node.kind() {
179 NODE_KIND_ANNOTATION => {
180 body.add_to_annotations(parse_annotation(context, &mut node.walk())?);
181 }
182 NODE_KIND_METHOD_DEF => {
183 body.add_to_methods(parse_method_def(context, &mut node.walk())?);
184 }
185 NODE_KIND_LINE_COMMENT => {
186 let comment = parse_comment(context, &node)?;
187 context.push_comment(comment);
188 }
189 _ => {
190 unexpected_node!(
191 context,
192 RULE_NAME,
193 node,
194 [NODE_KIND_ANNOTATION, NODE_KIND_METHOD_DEF,]
195 );
196 }
197 }
198 }
199
200 Ok(body)
201}
202
203fn parse_method_def<'a>(
204 context: &mut ParseContext<'a>,
205 cursor: &mut TreeCursor<'a>,
206) -> Result<MethodDef, Error> {
207 let node = cursor.node();
208 rule_fn!("method_def", node);
209
210 let child = node_field_named!(
211 context,
212 RULE_NAME,
213 node,
214 FIELD_NAME_SIGNATURE,
215 NODE_KIND_FUNCTION_SIGNATURE
216 );
217 let signature = parse_function_signature(context, &mut child.walk())?;
218 let mut method = MethodDef::new(signature).with_source_span(node.into());
219
220 if let Some(child) = optional_node_field_named!(
221 context,
222 RULE_NAME,
223 node,
224 FIELD_NAME_BODY,
225 NODE_KIND_FUNCTION_BODY
226 ) {
227 method.set_body(parse_function_body(context, &mut child.walk())?);
228 }
229
230 for child in node.named_children(cursor) {
231 check_node!(context, RULE_NAME, &node);
232 if child.kind() == NODE_KIND_ANNOTATION_ONLY_BODY {
233 let ann_body = parse_annotation_only_body(context, &mut child.walk())?;
234 let annotations: Vec<Annotation> = ann_body.into();
235 method.extend_annotations(annotations);
236 break;
237 }
238 }
239
240 Ok(method)
241}