bluejay_parser/ast/
directive.rs

1use crate::ast::{Arguments, FromTokens, IsMatch, ParseError, Tokens, TryFromTokens};
2use crate::lexical_token::{Name, PunctuatorType};
3use crate::{HasSpan, Span};
4
5#[derive(Debug)]
6pub struct Directive<'a, const CONST: bool> {
7    name: Name<'a>,
8    arguments: Option<Arguments<'a, CONST>>,
9    span: Span,
10}
11
12pub type ConstDirective<'a> = Directive<'a, true>;
13pub type VariableDirective<'a> = Directive<'a, false>;
14
15impl<'a, const CONST: bool> IsMatch<'a> for Directive<'a, CONST> {
16    #[inline]
17    fn is_match(tokens: &mut impl Tokens<'a>) -> bool {
18        tokens.peek_punctuator_matches(0, PunctuatorType::At)
19    }
20}
21
22impl<'a, const CONST: bool> FromTokens<'a> for Directive<'a, CONST> {
23    #[inline]
24    fn from_tokens(tokens: &mut impl Tokens<'a>) -> Result<Self, ParseError> {
25        let at_span = tokens.expect_punctuator(PunctuatorType::At)?;
26        let name = tokens.expect_name()?;
27        let arguments = Arguments::try_from_tokens(tokens).transpose()?;
28        let span = match &arguments {
29            Some(arguments) => at_span.merge(arguments.span()),
30            None => at_span.merge(name.span()),
31        };
32
33        Ok(Self {
34            name,
35            arguments,
36            span,
37        })
38    }
39}
40
41impl<'a, const CONST: bool> bluejay_core::Directive<CONST> for Directive<'a, CONST> {
42    type Arguments = Arguments<'a, CONST>;
43
44    fn name(&self) -> &str {
45        self.name.as_ref()
46    }
47
48    fn arguments(&self) -> Option<&Self::Arguments> {
49        self.arguments.as_ref()
50    }
51}
52
53impl<'a, const CONST: bool> HasSpan for Directive<'a, CONST> {
54    fn span(&self) -> &Span {
55        &self.span
56    }
57}
58
59impl<'a, const CONST: bool> Directive<'a, CONST> {
60    pub fn name(&self) -> &Name<'a> {
61        &self.name
62    }
63}