Change lambda syntax

This commit is contained in:
greg 2018-11-05 18:50:45 -08:00
parent ad53d4394b
commit a74e09c761
2 changed files with 28 additions and 13 deletions

View File

@ -186,7 +186,8 @@ typed_identifier := IDENTIFIER type_anno
/* Declaration - Functions */
func_declaration := func_signature func_body
func_body := ε | '{' (statement delimiter)* '}'
func_body := ε | nonempty_func_body
nonempty_func_body := '{' (statement delimiter)* '}'
func_signature := 'fn' func_name formal_param_list func_body
func_name := IDENTIFIER | operator
formal_param_list := '(' (formal_param ',')* ')'
@ -221,13 +222,12 @@ prefix_op := '+' | '-' | '!' | '~'
call_expr := index_expr ( '(' expr_list ')' )*
expr_list := expression (',' expression)* | ε
index_expr := primary ( '[' (expression (',' (expression)* | ε) ']' )*
primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | curly_brace_expr | list_expr
primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | lambda_expr | anonymous_struct | list_expr
/* Primary Expressions */
curly_brace_expr := lambda_expr | anonymous_struct //TODO
list_expr := '[' (expression, ',')* ']'
lambda_expr := '{' '|' (formal_param ',')* '|' (type_anno)* (statement delimiter)* '}'
lambda_expr := '\' formal_param_list nonempty_func_body
paren_expr := LParen paren_inner RParen
paren_inner := (expression ',')*
identifier_expr := named_struct | IDENTIFIER
@ -389,7 +389,7 @@ impl Parser {
fn func_declaration(&mut self) -> ParseResult<Declaration> {
let signature = self.func_signature()?;
if let LCurlyBrace = self.peek() {
let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
let statements = self.nonempty_func_body()?;
Ok(Declaration::FuncDecl(signature, statements))
} else {
Ok(Declaration::FuncSig(signature))
@ -407,7 +407,7 @@ impl Parser {
},
_ => (self.identifier()?, false)
};
let params = delimited!(self, LParen, formal_param, Comma, RParen);
let params = self.formal_param_list()?;
let type_anno = match self.peek() {
Colon => Some(self.type_anno()?),
_ => None,
@ -415,6 +415,16 @@ impl Parser {
Ok(Signature { name, operator, params, type_anno })
}
#[recursive_descent_method]
fn nonempty_func_body(&mut self) -> ParseResult<Vec<Statement>> {
Ok(delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict))
}
#[recursive_descent_method]
fn formal_param_list(&mut self) -> ParseResult<Vec<FormalParam>> {
Ok(delimited!(self, LParen, formal_param, Comma, RParen))
}
#[recursive_descent_method]
fn formal_param(&mut self) -> ParseResult<FormalParam> {
let name = self.identifier()?;
@ -603,6 +613,7 @@ impl Parser {
fn primary(&mut self) -> ParseResult<Expression> {
match self.peek() {
LCurlyBrace => self.curly_brace_expr(),
Backslash => self.lambda_expr(),
LParen => self.paren_expr(),
LSquareBracket => self.list_expr(),
Keyword(Kw::If) => self.if_expr(),
@ -621,13 +632,15 @@ impl Parser {
#[recursive_descent_method]
fn curly_brace_expr(&mut self) -> ParseResult<Expression> {
self.lambda_expr()
ParseError::new("Not implemented")
}
#[recursive_descent_method]
fn lambda_expr(&mut self) -> ParseResult<Expression> {
expect!(self, LCurlyBrace);
let params = delimited!(self, Pipe, formal_param, Comma, Pipe);
expect!(self, Backslash);
let params = self.formal_param_list()?; //TODO make this allow some more concise syntaxes
let body = self.nonempty_func_body()?;
/*
let mut body = Vec::new();
loop {
match self.peek() {
@ -640,6 +653,7 @@ impl Parser {
}
}
expect!(self, RCurlyBrace);
*/
Ok(Expression(ExpressionType::Lambda { params, body }, None)) //TODO need to handle types somehow
}
@ -1468,18 +1482,18 @@ fn a(x) {
#[test]
fn parsing_lambdas() {
parse_test! { "{|x| x + 1}", single_expr!(
parse_test! { r#"\(x) { x + 1}"#, single_expr!(
Lambda { params: vec![(rc!(x), None)], body: vec![exst!("+", val!("x"), NatLiteral(1))] }
) }
parse_test!("{ |x: Int, y| a;b;c;}", AST(vec![
parse_test!(r#"\ (x: Int, y) { a;b;c;}"#, AST(vec![
exprstatement!(Lambda {
params: vec![(rc!(x), Some(ty!("Int"))), (rc!(y), None)],
body: vec![exst!(val!("a")), exst!(val!("b")), exst!(val!("c"))]
})
]));
parse_test!("{|x| y}(1)", AST(vec![
parse_test!(r#"\(x){y}(1)"#, AST(vec![
exprstatement!(Call { f: bx!(ex!(
Lambda { params: vec![(rc!(x), None)], body: vec![exprstatement!(val!("y"))] })),
arguments: vec![ex!(NatLiteral(1))] })]));

View File

@ -12,7 +12,7 @@ pub enum TokenType {
LSquareBracket, RSquareBracket,
LAngleBracket, RAngleBracket,
LCurlyBrace, RCurlyBrace,
Pipe,
Pipe, Backslash,
Comma, Period, Colon, Underscore,
Slash,
@ -157,6 +157,7 @@ pub fn tokenize(input: &str) -> Vec<Token> {
'{' => LCurlyBrace, '}' => RCurlyBrace,
'[' => LSquareBracket, ']' => RSquareBracket,
'"' => handle_quote(&mut input),
'\\' => Backslash,
c if c.is_digit(10) => handle_digit(c, &mut input),
c if c.is_alphabetic() || c == '_' => handle_alphabetic(c, &mut input), //TODO I'll probably have to rewrite this if I care about types being uppercase, also type parameterization
c if is_operator(&c) => handle_operator(c, &mut input),