microcad_lang/parse/
lang_type.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::{parse::*, parser::*, syntax::*, ty::*};
5
6impl Parse for TupleType {
7    fn parse(pair: Pair) -> ParseResult<Self> {
8        use crate::ty::Ty;
9        Parser::ensure_rule(&pair, Rule::tuple_type);
10
11        match pair.as_str() {
12            "Color" => Ok(TupleType::new_color()),
13            "Vec2" => Ok(TupleType::new_vec2()),
14            "Vec3" => Ok(TupleType::new_vec3()),
15            "Size2" => Ok(TupleType::new_size2()),
16            _ => {
17                let mut named = std::collections::HashMap::new();
18                let mut unnamed = std::collections::HashSet::new();
19
20                pair.inner().try_for_each(|pair| {
21                    let mut inner = pair.inner();
22                    let next = inner.next().expect("Identifier or type expected");
23                    if next.as_rule() == Rule::identifier {
24                        let id = Identifier::parse(next)?;
25                        if named
26                            .insert(
27                                id.clone(),
28                                TypeAnnotation::parse(
29                                    inner.next().expect("Identifier or type expected"),
30                                )?
31                                .ty(),
32                            )
33                            .is_some()
34                        {
35                            return Err(ParseError::DuplicateTupleIdentifier(id));
36                        }
37                    } else {
38                        let ty = TypeAnnotation::parse(next)?.ty();
39                        if !unnamed.insert(ty.clone()) {
40                            return Err(ParseError::DuplicateTupleType(Refer::new(
41                                ty,
42                                pair.clone().into(),
43                            )));
44                        }
45                    }
46
47                    Ok::<(), ParseError>(())
48                })?;
49
50                Ok(Self { named, unnamed })
51            }
52        }
53    }
54}
55
56impl Parse for MatrixType {
57    fn parse(pair: Pair) -> ParseResult<Self> {
58        Parser::ensure_rule(&pair, Rule::matrix_type);
59
60        let mut m: Option<usize> = None;
61        let mut n: Option<usize> = None;
62
63        for p in pair.inner() {
64            match p.as_rule() {
65                Rule::int => match m {
66                    None => m = Some(p.as_str().parse().expect("Valid integer")),
67                    Some(_) => n = Some(p.as_str().parse().expect("Valid integer")),
68                },
69                _ => unreachable!(),
70            }
71        }
72
73        let m = m.expect("M");
74
75        Ok(Self {
76            rows: m,
77            columns: n.unwrap_or(m),
78        })
79    }
80}
81
82#[test]
83fn array_type() {
84    use crate::parser::{Parser, Rule};
85    use crate::ty::Ty;
86
87    let type_annotation =
88        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "[Integer]", 0).expect("test error");
89    assert_eq!(type_annotation.ty().to_string(), "[Integer]");
90    assert_eq!(type_annotation.ty(), Type::Array(Box::new(Type::Integer)));
91}
92
93#[test]
94fn matrix_type() {
95    use crate::parser::*;
96    use crate::ty::Ty;
97
98    let type_annotation =
99        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "Matrix4x3", 0).expect("test error");
100    assert_eq!(type_annotation.ty().to_string(), "Matrix4x3");
101    assert_eq!(
102        type_annotation.ty(),
103        Type::Matrix(MatrixType {
104            rows: 4,
105            columns: 3,
106        })
107    );
108}