microcad_lang/parse/
find_rule.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::parse::*;
5
6/// Find rule with proper error handling.
7///
8/// - `pair`: Pair to solve
9/// - `rule`: Rule to parse.
10/// - `def`: if given returns default if not found
11pub fn find_rule<T: crate::parser::Parse>(
12    pair: &crate::parser::Pair<'_>,
13    rule: crate::parser::Rule,
14    def: Option<T>,
15) -> ParseResult<T> {
16    match pair
17        .inner()
18        .find(|pair| pair.as_rule() == rule)
19        .map(T::parse)
20    {
21        Some(Ok(stmts)) => Ok(stmts),
22        Some(Err(err)) => Err(err),
23        None => {
24            if let Some(def) = def {
25                Ok(def)
26            } else {
27                Err(ParseError::NotAvailable)
28            }
29        }
30    }
31}
32
33/// Find rule or use default with proper error handling.
34#[macro_export]
35macro_rules! find_rule {
36    ($pair:ident, $rule:ident) => {
37        find_rule(&$pair, Rule::$rule, Some(Default::default()))
38    };
39}
40
41/// Find rule and return optional with proper error handling.
42#[macro_export]
43macro_rules! find_rule_opt {
44    ($pair:ident, $rule:ident) => {
45        match find_rule(&$pair, Rule::$rule, None) {
46            Ok(t) => Some(t),
47            Err(_) => None,
48        }
49    };
50}
51
52/// Find rule and return definition or [`ParseError::NotAvailable`] with proper error handling.
53#[macro_export]
54macro_rules! find_rule_exact {
55    ($pair:ident, $rule:ident) => {
56        find_rule(&$pair, Rule::$rule, None)
57    };
58}