From 248af74ec0f2cdd8fc367cb23c4ee55ac6250b84 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Thu, 21 Oct 2021 11:32:14 -0700 Subject: [PATCH] Add parsing for annotations --- schala-lang/language/src/ast/mod.rs | 19 +++++++++ schala-lang/language/src/ast/walker.rs | 2 + schala-lang/language/src/parsing/mod.rs | 19 +++++++++ schala-lang/language/src/parsing/test.rs | 44 +++++++++++++++++++++ schala-lang/language/src/reduced_ast/mod.rs | 1 + schala-lang/language/src/tokenizing.rs | 5 ++- 6 files changed, 89 insertions(+), 1 deletion(-) diff --git a/schala-lang/language/src/ast/mod.rs b/schala-lang/language/src/ast/mod.rs index 674d664..6dee34e 100644 --- a/schala-lang/language/src/ast/mod.rs +++ b/schala-lang/language/src/ast/mod.rs @@ -114,9 +114,28 @@ pub enum Declaration { Interface { name: Rc, signatures: Vec + }, + Annotation { + name: Rc, + arguments: Vec } } +/* + * @foo(arg1, arg2) + * fn hello() { + * + * } + * + * Declaration::Annotation { + * name: "foo", + * arguments: vec!["arg1", "arg2"] + * } + * + * + * + */ + #[derive(Debug, PartialEq, Clone)] pub struct Signature { pub name: Rc, diff --git a/schala-lang/language/src/ast/walker.rs b/schala-lang/language/src/ast/walker.rs index 2776500..4fc63b8 100644 --- a/schala-lang/language/src/ast/walker.rs +++ b/schala-lang/language/src/ast/walker.rs @@ -60,6 +60,8 @@ fn declaration(v: &mut V, decl: &Declaration) { v.implemention(type_name, interface_name.as_ref(), block); } Interface { name, signatures } => v.interface(name, signatures), + //TODO fill this in + Annotation { .. } => () } } diff --git a/schala-lang/language/src/parsing/mod.rs b/schala-lang/language/src/parsing/mod.rs index abfc267..08a881f 100644 --- a/schala-lang/language/src/parsing/mod.rs +++ b/schala-lang/language/src/parsing/mod.rs @@ -371,6 +371,7 @@ 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(|decl| { StatementKind::Declaration(decl) }), Keyword(Func)=> self.func_declaration().map(|func| { StatementKind::Declaration(func) }), Keyword(Let) => self.binding_declaration().map(StatementKind::Declaration), @@ -384,6 +385,23 @@ impl Parser { Ok(Statement { kind, id, location: tok.location }) } + + #[recursive_descent_method] + fn annotation(&mut self) -> ParseResult { + expect!(self, AtSign); + let name = self.identifier()?; + let arguments = if let LParen = self.token_handler.peek().get_kind() { + delimited!(self, LParen, expression, Comma, RParen) + } else { + vec![] + }; + + Ok(Declaration::Annotation { + name, + arguments, + }) + } + #[recursive_descent_method] fn type_declaration(&mut self) -> ParseResult { expect!(self, Keyword(Type)); @@ -668,6 +686,7 @@ impl Parser { #[recursive_descent_method] fn call_expr(&mut self) -> ParseResult { let mut expr = self.index_expr()?; + //TODO look at this while let LParen = self.token_handler.peek_kind() { let arguments = delimited!(self, LParen, invocation_argument, Comma, RParen); expr = Expression::new(self.id_store.fresh(), ExpressionKind::Call { f: Box::new(expr), arguments }); //TODO no type anno is incorrect diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index ab0d4d4..d98bcd3 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -840,3 +840,47 @@ module!( ) } } + +#[test] +fn annotations() { + parse_test! { + r#" + @test_annotation + fn some_function() { + + }"#, + AST { + id: Default::default(), + statements: vec![ + decl!(Annotation { name: rc!(test_annotation), arguments: vec![] }), + decl!(FuncDecl( + Signature { name: rc!(some_function), operator: false, params: vec![], type_anno: None } + , vec![] + ) + ) + ] + } + }; + parse_test! { + r#" + @test_annotation(some, value) + fn some_function() { + + }"#, + AST { + id: Default::default(), + statements: vec![ + decl!(Annotation { name: rc!(test_annotation), arguments: vec![ + ex!(val!("some")), + ex!(val!("value")) + ] }), + decl!(FuncDecl( + Signature { name: rc!(some_function), operator: false, params: vec![], type_anno: None } + , vec![] + ) + ) + ] + } + }; +} + diff --git a/schala-lang/language/src/reduced_ast/mod.rs b/schala-lang/language/src/reduced_ast/mod.rs index 633ed0f..4c247ae 100644 --- a/schala-lang/language/src/reduced_ast/mod.rs +++ b/schala-lang/language/src/reduced_ast/mod.rs @@ -327,6 +327,7 @@ impl<'a> Reducer<'a> { TypeAlias { .. } => Stmt::Noop, Interface { .. } => Stmt::Noop, Impl { .. } => Stmt::Expr(Expr::UnimplementedSigilValue), + Annotation { .. } => Stmt::Noop, _ => Stmt::Expr(Expr::UnimplementedSigilValue), } } diff --git a/schala-lang/language/src/tokenizing.rs b/schala-lang/language/src/tokenizing.rs index 3568e4f..4f67dbf 100644 --- a/schala-lang/language/src/tokenizing.rs +++ b/schala-lang/language/src/tokenizing.rs @@ -29,6 +29,8 @@ pub enum TokenKind { LAngleBracket, RAngleBracket, LCurlyBrace, RCurlyBrace, Pipe, Backslash, + AtSign, + Comma, Period, Colon, Underscore, Slash, Equals, @@ -125,7 +127,7 @@ impl Token { } } -const OPERATOR_CHARS: [char; 18] = ['!', '$', '%', '&', '*', '+', '-', '.', ':', '<', '>', '=', '?', '@', '^', '|', '~', '`']; +const OPERATOR_CHARS: [char; 17] = ['!', '$', '%', '&', '*', '+', '-', '.', ':', '<', '>', '=', '?', '^', '|', '~', '`']; fn is_operator(c: &char) -> bool { OPERATOR_CHARS.iter().any(|x| x == c) } @@ -183,6 +185,7 @@ pub fn tokenize(input: &str) -> Vec { '[' => LSquareBracket, ']' => RSquareBracket, '"' => handle_quote(&mut input, None), '\\' => Backslash, + '@' => AtSign, c if c.is_digit(10) => handle_digit(c, &mut input), c if c.is_alphabetic() || c == '_' => handle_alphabetic(c, &mut input), c if is_operator(&c) => handle_operator(c, &mut input),