diff --git a/schala-lang/language/src/ast/mod.rs b/schala-lang/language/src/ast/mod.rs index 83eda7a..05ea5c2 100644 --- a/schala-lang/language/src/ast/mod.rs +++ b/schala-lang/language/src/ast/mod.rs @@ -130,7 +130,7 @@ pub enum Declaration { Binding { name: Rc, constant: bool, type_anno: Option, expr: Expression }, Impl { type_name: TypeIdentifier, interface_name: Option, block: Vec }, Interface { name: Rc, signatures: Vec }, - Annotation { name: Rc, arguments: Vec }, + Annotation { name: Rc, arguments: Vec, inner: Box }, } #[derive(Debug, PartialEq, Clone)] diff --git a/schala-lang/language/src/parsing/mod.rs b/schala-lang/language/src/parsing/mod.rs index 1723dec..b7c050d 100644 --- a/schala-lang/language/src/parsing/mod.rs +++ b/schala-lang/language/src/parsing/mod.rs @@ -17,7 +17,8 @@ //! delimiter := NEWLINE | ";" //! statement := expression | declaration | import | module | flow //! block := "{" (statement delimiter)* "}" -//! declaration := type_declaration | func_declaration | binding_declaration | impl_declaration +//! declaration := annotation? declaration | bare_declaration +//! bare_declaration := type_declaration | func_declaration | binding_declaration | impl_declaration //! ``` //! ## Declarations //! @@ -393,22 +394,30 @@ impl Parser { //TODO handle error recovery here let tok = self.token_handler.peek(); let kind = match tok.get_kind() { - AtSign => self.annotation().map(StatementKind::Declaration), - Keyword(Type) => self.type_declaration().map(StatementKind::Declaration), - Keyword(Func) => self.func_declaration().map(StatementKind::Declaration), - Keyword(Let) => self.binding_declaration().map(StatementKind::Declaration), - Keyword(Interface) => self.interface_declaration().map(StatementKind::Declaration), - Keyword(Impl) => self.impl_declaration().map(StatementKind::Declaration), - Keyword(Import) => self.import_declaration().map(StatementKind::Import), - Keyword(Module) => self.module_declaration().map(StatementKind::Module), + AtSign | Keyword(Let) | Keyword(Type) | Keyword(Func) | Keyword(Interface) | Keyword(Impl) => + self.declaration().map(StatementKind::Declaration), Keyword(Continue) | Keyword(Return) | Keyword(Break) => self.flow_control().map(StatementKind::Flow), + Keyword(Import) => self.import_declaration().map(StatementKind::Import), + Keyword(Module) => self.module_declaration().map(StatementKind::Module), _ => self.expression().map(StatementKind::Expression), }?; let id = self.id_store.fresh(); Ok(Statement { kind, id, location: tok.location }) } + fn declaration(&mut self) -> ParseResult { + match self.token_handler.peek_kind() { + AtSign => self.annotation(), + Keyword(Let) => self.binding_declaration(), + Keyword(Type) => self.type_declaration(), + Keyword(Func) => self.func_declaration(), + Keyword(Interface) => self.interface_declaration(), + Keyword(Impl) => self.impl_declaration(), + _ => return ParseError::new_with_token("Bad parse state encountered", self.token_handler.peek()), + } + } + #[recursive_descent_method] fn flow_control(&mut self) -> ParseResult { let tok = self.token_handler.next(); @@ -423,6 +432,7 @@ impl Parser { }) } + //TODO make it possible to annotate other types of things #[recursive_descent_method] fn annotation(&mut self) -> ParseResult { expect!(self, AtSign); @@ -432,8 +442,11 @@ impl Parser { } else { vec![] }; - - Ok(Declaration::Annotation { name, arguments }) + if let Semicolon | Newline = self.token_handler.peek_kind() { + self.token_handler.next(); + } + let inner = Box::new(self.declaration()?); + Ok(Declaration::Annotation { name, arguments, inner }) } #[recursive_descent_method] diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index 5599734..91bf309 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -928,6 +928,11 @@ fn impls() { fn annotations() { use ExpressionKind::*; + let func = Declaration::FuncDecl( + Signature { name: rc("some_function"), operator: false, params: vec![], type_anno: None }, + vec![].into(), + ); + assert_ast! { r#" @test_annotation @@ -936,25 +941,26 @@ fn annotations() { }"#, vec![decl(Declaration::Annotation { name: rc("test_annotation"), - arguments: vec![] + arguments: vec![], + inner: bx(func.clone()), }), - fn_decl(Signature { name: rc("some_function"), operator: false, params: vec![], type_anno: None }, - vec![].into()) ] }; assert_ast! { r#" @test_annotation(some,value) + @another_annotation fn some_function() { }"#, vec![decl(Declaration::Annotation { name: rc("test_annotation"), - arguments: vec![expr(Value(qn!(some))), expr(Value(qn!(value)))] + arguments: vec![expr(Value(qn!(some))), expr(Value(qn!(value)))], + inner: bx(Declaration::Annotation { + name: rc("another_annotation"), arguments: vec![], inner: bx(func) + }) }), - fn_decl(Signature { name: rc("some_function"), operator: false, params: vec![], type_anno: None }, - vec![].into()) ] }; }