Skip to main content

aldrin_parser/ast/
named_ref.rs

1use super::Ident;
2use crate::Span;
3use crate::error::MissingImport;
4use crate::grammar::Rule;
5use crate::validate::Validate;
6use pest::iterators::Pair;
7use std::fmt;
8
9#[derive(Debug, Clone)]
10pub struct NamedRef {
11    span: Span,
12    kind: NamedRefKind,
13}
14
15impl NamedRef {
16    pub(crate) fn parse(pair: Pair<Rule>) -> Self {
17        assert_eq!(pair.as_rule(), Rule::named_ref);
18
19        let span = Span::from_pair(&pair);
20
21        let mut pairs = pair.into_inner();
22        let pair = pairs.next().unwrap();
23        let kind = NamedRefKind::parse(pair);
24
25        Self { span, kind }
26    }
27
28    pub(crate) fn dummy_intern(ident: Ident) -> Self {
29        Self {
30            span: Span::dummy(),
31            kind: NamedRefKind::Intern(ident),
32        }
33    }
34
35    pub(crate) fn validate(&self, validate: &mut Validate) {
36        self.kind.validate(validate);
37    }
38
39    pub fn span(&self) -> Span {
40        self.span
41    }
42
43    pub fn kind(&self) -> &NamedRefKind {
44        &self.kind
45    }
46
47    pub fn schema(&self) -> Option<&Ident> {
48        self.kind.schema()
49    }
50
51    pub fn ident(&self) -> &Ident {
52        self.kind.ident()
53    }
54}
55
56#[derive(Debug, Clone)]
57pub enum NamedRefKind {
58    Intern(Ident),
59    Extern(Ident, Ident),
60}
61
62impl NamedRefKind {
63    fn parse(pair: Pair<Rule>) -> Self {
64        #[expect(clippy::wildcard_enum_match_arm)]
65        match pair.as_rule() {
66            Rule::ident => Self::Intern(Ident::parse(&pair)),
67
68            Rule::external_ref => {
69                let mut pairs = pair.into_inner();
70                let pair = pairs.next().unwrap();
71                let schema_name = Ident::parse(&pair);
72                pairs.next().unwrap(); // Skip ::.
73                let ident = Ident::parse(&pairs.next().unwrap());
74
75                Self::Extern(schema_name, ident)
76            }
77
78            _ => unreachable!(),
79        }
80    }
81
82    fn validate(&self, validate: &mut Validate) {
83        match self {
84            Self::Intern(ty) => {
85                ty.validate(false, validate);
86            }
87
88            Self::Extern(schema, ty) => {
89                MissingImport::validate(schema, validate);
90                ty.validate(false, validate);
91            }
92        }
93    }
94
95    pub fn schema(&self) -> Option<&Ident> {
96        match self {
97            Self::Intern(_) => None,
98            Self::Extern(schema, _) => Some(schema),
99        }
100    }
101
102    pub fn ident(&self) -> &Ident {
103        match self {
104            Self::Intern(ident) | Self::Extern(_, ident) => ident,
105        }
106    }
107}
108
109impl fmt::Display for NamedRefKind {
110    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111        match self {
112            Self::Intern(ident) => write!(f, "{}", ident.value()),
113            Self::Extern(schema, ident) => write!(f, "{}::{}", schema.value(), ident.value()),
114        }
115    }
116}