dada_parser/
miscellaneous.rs1use 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}