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 let Ok(id) = Identifier::parse(next.clone()) {
24                        if named
25                            .insert(
26                                id.clone(),
27                                TypeAnnotation::parse(
28                                    inner.next().expect("Identifier or type expected"),
29                                )?
30                                .ty(),
31                            )
32                            .is_some()
33                        {
34                            return Err(ParseError::DuplicateTupleIdentifier(id));
35                        }
36                    } else {
37                        let ty = TypeAnnotation::parse(next)?.ty();
38                        if !unnamed.insert(ty.clone()) {
39                            return Err(ParseError::DuplicateTupleType(ty));
40                        }
41                    }
42
43                    Ok::<(), ParseError>(())
44                })?;
45
46                Ok(Self { named, unnamed })
47            }
48        }
49    }
50}
51
52impl Parse for MatrixType {
53    fn parse(pair: Pair) -> ParseResult<Self> {
54        Parser::ensure_rule(&pair, Rule::matrix_type);
55
56        let mut m: Option<usize> = None;
57        let mut n: Option<usize> = None;
58
59        for p in pair.inner() {
60            match p.as_rule() {
61                Rule::int => match m {
62                    None => m = Some(p.as_str().parse().expect("Valid integer")),
63                    Some(_) => n = Some(p.as_str().parse().expect("Valid integer")),
64                },
65                _ => unreachable!(),
66            }
67        }
68
69        let m = m.expect("M");
70
71        Ok(Self {
72            rows: m,
73            columns: n.unwrap_or(m),
74        })
75    }
76}
77
78#[test]
79fn array_type() {
80    use crate::parser::{Parser, Rule};
81    use crate::ty::Ty;
82
83    let type_annotation =
84        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "[Integer]", 0).expect("test error");
85    assert_eq!(type_annotation.ty().to_string(), "[Integer]");
86    assert_eq!(type_annotation.ty(), Type::Array(Box::new(Type::Integer)));
87}
88
89#[test]
90fn matrix_type() {
91    use crate::parser::*;
92    use crate::ty::Ty;
93
94    let type_annotation =
95        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "Matrix4x3", 0).expect("test error");
96    assert_eq!(type_annotation.ty().to_string(), "Matrix4x3");
97    assert_eq!(
98        type_annotation.ty(),
99        Type::Matrix(MatrixType {
100            rows: 4,
101            columns: 3,
102        })
103    );
104}