sdml_parse/parse/definitions/
classes.rs

1use 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
25// ------------------------------------------------------------------------------------------------
26// Parser Functions
27// ------------------------------------------------------------------------------------------------
28
29pub(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}