Add parsing for annotations

This commit is contained in:
Greg Shuflin 2021-10-21 11:32:14 -07:00
parent 3b5ebf92b4
commit 248af74ec0
6 changed files with 89 additions and 1 deletions

View File

@ -114,9 +114,28 @@ pub enum Declaration {
Interface {
name: Rc<String>,
signatures: Vec<Signature>
},
Annotation {
name: Rc<String>,
arguments: Vec<Expression>
}
}
/*
* @foo(arg1, arg2)
* fn hello() {
*
* }
*
* Declaration::Annotation {
* name: "foo",
* arguments: vec!["arg1", "arg2"]
* }
*
*
*
*/
#[derive(Debug, PartialEq, Clone)]
pub struct Signature {
pub name: Rc<String>,

View File

@ -60,6 +60,8 @@ fn declaration<V: ASTVisitor>(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 { .. } => ()
}
}

View File

@ -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<Declaration> {
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<Declaration> {
expect!(self, Keyword(Type));
@ -668,6 +686,7 @@ impl Parser {
#[recursive_descent_method]
fn call_expr(&mut self) -> ParseResult<Expression> {
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

View File

@ -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![]
)
)
]
}
};
}

View File

@ -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),
}
}

View File

@ -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<Token> {
'[' => 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),