Skip to main content

dada_parser/
miscellaneous.rs

1use dada_ir_ast::ast::{AstGenericTerm, AstPath, AstPathKind};
2
3use crate::tokenizer::operator;
4
5use super::{Expected, Parse, ParseFail, Parser};
6
7impl<'db> Parse<'db> for AstPath<'db> {
8    type Output = Self;
9
10    fn opt_parse(
11        db: &'db dyn crate::Db,
12        parser: &mut Parser<'_, 'db>,
13    ) -> Result<Option<Self>, ParseFail<'db>> {
14        let Ok(id) = parser.eat_id() else {
15            return Ok(None);
16        };
17        let mut path = AstPath::new(db, AstPathKind::Identifier(id));
18
19        loop {
20            if parser.eat_op(operator::DOT).is_ok() {
21                let id = parser.eat_id()?;
22                path = AstPath::new(db, AstPathKind::Member { path, id });
23                continue;
24            }
25
26            if let Some(args) = AstGenericTerm::opt_parse_delimited(
27                db,
28                parser,
29                crate::tokenizer::Delimiter::SquareBrackets,
30                AstGenericTerm::eat_comma,
31            )? {
32                path = AstPath::new(db, AstPathKind::GenericArgs { path, args });
33                continue;
34            }
35
36            return Ok(Some(path));
37        }
38    }
39
40    fn expected() -> Expected {
41        Expected::Nonterminal("path")
42    }
43}
44
45pub trait OrOptParse<'db, Variant1> {
46    fn or_opt_parse<Enum, Variant2>(
47        self,
48        db: &'db dyn crate::Db,
49        parser: &mut Parser<'_, 'db>,
50    ) -> Result<Option<Enum>, ParseFail<'db>>
51    where
52        Variant1: Into<Enum>,
53        Variant2: Parse<'db, Output: Into<Enum>>;
54}
55
56impl<'db, Variant1> OrOptParse<'db, Variant1> for Result<Option<Variant1>, ParseFail<'db>> {
57    fn or_opt_parse<Enum, Variant2>(
58        self,
59        db: &'db dyn crate::Db,
60        parser: &mut Parser<'_, 'db>,
61    ) -> Result<Option<Enum>, ParseFail<'db>>
62    where
63        Variant1: Into<Enum>,
64        Variant2: Parse<'db, Output: Into<Enum>>,
65    {
66        match self {
67            Ok(Some(v1)) => Ok(Some(v1.into())),
68            Ok(None) => match Variant2::opt_parse(db, parser) {
69                Ok(Some(v2)) => Ok(Some(v2.into())),
70                Ok(None) => Ok(None),
71                Err(err) => Err(err),
72            },
73            Err(err) => Err(err),
74        }
75    }
76}