diff --git a/compiler/pipec-ast/src/ast/mod.rs b/compiler/pipec-ast/src/ast/mod.rs index d1f3e07..44c5980 100644 --- a/compiler/pipec-ast/src/ast/mod.rs +++ b/compiler/pipec-ast/src/ast/mod.rs @@ -78,6 +78,7 @@ impl<'this> ASTGenerator<'this> { Token::FunctionKeyword => self.consume_function_keyword(), Token::PublicKeyword => self.consume_public_keyword(), Token::TypeKeyword => self.consume_type_keyword(), + Token::AtSign => self.consume_attributes(), _v => { println!("{_v:#?}"); todo!(); @@ -87,6 +88,34 @@ impl<'this> ASTGenerator<'this> { } } + #[inline] + pub(crate) fn consume_attributes(&mut self) -> ASTNode { + let mut attributes = Vec::new(); + loop { + if self.next_is(Token::AtSign) { + self.advance_stream(); + let name = self + .must_ident() + .parse_arena(self.loader.load(self.src), self.arena); + match name { + "language" => attributes.push(self.consume_language_attribute()), + _ => todo!(), + } + } else { + break; + } + } + ASTNode::Attributed(attributes, Box::new(self.parse_value())) + } + + #[inline] + pub(crate) fn consume_language_attribute(&mut self) -> Attribute { + self.must(Token::LeftParenthesis); + let name = self.must_string(); + self.must(Token::RightParenthesis); + Attribute::LanguageAttribute(name) + } + #[inline] pub(crate) fn consume_type_keyword(&mut self) -> ASTNode { self.advance_stream(); @@ -275,6 +304,14 @@ impl<'this> ASTGenerator<'this> { unreachable!() } + #[inline] + pub(crate) fn must_string(&mut self) -> Span { + if let Some(Token::String(v)) = self.advance_stream() { + return v; + } + unreachable!() + } + #[inline] pub(crate) fn consume_function_parameter(&mut self) -> FunctionDeclarationParameter { let name = self.must_ident(); @@ -1127,9 +1164,15 @@ pub enum ASTNode { subtype: SubType, }, Public(Box), + Attributed(Vec, Box), EOF, } +#[derive(Debug, Clone)] +pub enum Attribute { + LanguageAttribute(Span), +} + #[derive(Debug, Clone)] pub enum SubType { Map(HashMap),