microcad_lang/parse/
statement.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::{parse::*, parser::*, rc::*, syntax::*};
5
6impl Parse for Assignment {
7    fn parse(pair: Pair) -> ParseResult<Self> {
8        Ok(Self::new(
9            crate::find_rule_opt!(pair, doc_block),
10            crate::find_rule!(pair, visibility)?,
11            crate::find_rule!(pair, qualifier)?,
12            crate::find_rule!(pair, identifier)?,
13            crate::find_rule_opt!(pair, r#type),
14            crate::find_rule_exact!(pair, expression)?,
15            pair.into(),
16        ))
17    }
18}
19
20impl Parse for Rc<Assignment> {
21    fn parse(pair: Pair) -> ParseResult<Self> {
22        Ok(Rc::new(Assignment::parse(pair)?))
23    }
24}
25
26impl Parse for AssignmentStatement {
27    fn parse(pair: Pair) -> crate::parse::ParseResult<Self> {
28        Ok(Self {
29            attribute_list: crate::find_rule!(pair, attribute_list)?,
30            assignment: crate::find_rule_opt!(pair, assignment).expect("Assignment"),
31            src_ref: pair.into(),
32        })
33    }
34}
35
36impl Parse for IfStatement {
37    fn parse(pair: Pair) -> ParseResult<Self> {
38        let mut cond = Default::default();
39        let mut body = None;
40        let mut body_else = None;
41        let mut next_if = None;
42
43        for pair in pair.inner() {
44            match pair.as_rule() {
45                Rule::expression => cond = Expression::parse(pair)?,
46                Rule::body => {
47                    if body.is_none() {
48                        body = Some(Body::parse(pair)?)
49                    } else {
50                        body_else = Some(Body::parse(pair)?)
51                    }
52                }
53                Rule::if_statement => {
54                    if next_if.is_none() {
55                        next_if = Some(Box::new(IfStatement::parse(pair)?));
56                    }
57                }
58                rule => unreachable!("Unexpected rule in if, got {:?}", rule),
59            }
60        }
61
62        let body = body.expect("Body");
63
64        Ok(IfStatement {
65            cond,
66            body,
67            body_else,
68            next_if,
69            src_ref: pair.into(),
70        })
71    }
72}
73
74impl Parse for ExpressionStatement {
75    fn parse(pair: Pair) -> crate::parse::ParseResult<Self> {
76        Parser::ensure_rules(
77            &pair,
78            &[Rule::expression_statement, Rule::final_expression_statement],
79        );
80
81        Ok(Self {
82            attribute_list: crate::find_rule!(pair, attribute_list)?,
83            expression: pair.find(Rule::expression).expect("Expression"),
84            src_ref: pair.into(),
85        })
86    }
87}
88
89impl Parse for Statement {
90    fn parse(pair: Pair) -> ParseResult<Self> {
91        Parser::ensure_rule(&pair, Rule::statement);
92        let first = pair.inner().next().expect(INTERNAL_PARSE_ERROR);
93        Ok(match first.as_rule() {
94            Rule::workbench_definition => Self::Workbench(Rc::<WorkbenchDefinition>::parse(first)?),
95            Rule::module_definition => Self::Module(Rc::<ModuleDefinition>::parse(first)?),
96            Rule::function_definition => Self::Function(Rc::<FunctionDefinition>::parse(first)?),
97            Rule::init_definition => Self::Init(Rc::new(InitDefinition::parse(first)?)),
98
99            Rule::use_statement => Self::Use(UseStatement::parse(first)?),
100            Rule::return_statement => Self::Return(ReturnStatement::parse(first)?),
101            Rule::if_statement => Self::If(IfStatement::parse(first)?),
102            Rule::inner_attribute => Self::InnerAttribute(Attribute::parse(first)?),
103
104            Rule::assignment_statement => Self::Assignment(AssignmentStatement::parse(first)?),
105            Rule::expression_statement | Rule::final_expression_statement => {
106                Self::Expression(ExpressionStatement::parse(first)?)
107            }
108            rule => unreachable!("Unexpected statement, got {:?} {:?}", rule, first.clone()),
109        })
110    }
111}
112
113impl Parse for ReturnStatement {
114    fn parse(pair: Pair) -> ParseResult<Self> {
115        let mut result = None;
116
117        for pair in pair.inner() {
118            match pair.as_rule() {
119                Rule::expression => result = Some(Expression::parse(pair)?),
120                rule => unreachable!("Unexpected rule in return, got {:?}", rule),
121            }
122        }
123
124        Ok(ReturnStatement {
125            result,
126            src_ref: pair.into(),
127        })
128    }
129}
130
131impl Parse for StatementList {
132    fn parse(pair: Pair) -> ParseResult<Self> {
133        let mut statements = Vec::new();
134
135        for pair in pair.inner() {
136            match pair.as_rule() {
137                Rule::final_expression_statement => {
138                    statements.push(Statement::Expression(ExpressionStatement::parse(pair)?));
139                }
140                Rule::statement => {
141                    statements.push(Statement::parse(pair)?);
142                }
143                _ => {}
144            }
145        }
146
147        Ok(Self(statements))
148    }
149}
150
151impl Parse for Qualifier {
152    fn parse(pair: Pair) -> ParseResult<Self> {
153        Parser::ensure_rule(&pair, Rule::qualifier);
154        match pair.as_str() {
155            "prop" => Ok(Self::Prop),
156            "const" => Ok(Self::Const),
157            _ => Ok(Self::Value),
158        }
159    }
160}