Add lambdas
This commit is contained in:
parent
d93b5c0a2e
commit
77297c7e06
@ -9,19 +9,20 @@ use std::convert::From;
|
|||||||
// program := (statement delimiter ?)*
|
// program := (statement delimiter ?)*
|
||||||
// delimiter := Newline | Semicolon
|
// delimiter := Newline | Semicolon
|
||||||
// statement := declaration | expression
|
// statement := declaration | expression
|
||||||
// declaration := Fn prototype LCurlyBrace (statement)* RCurlyBrace
|
// declaration := FN prototype LCurlyBrace (statement)* RCurlyBrace
|
||||||
// prototype := identifier LParen identlist RParen
|
// prototype := identifier LParen identlist RParen
|
||||||
// identlist := Ident (Comma Ident)* | e
|
// identlist := Ident (Comma Ident)* | e
|
||||||
// exprlist := Expression (Comma Expression)* | e
|
// exprlist := Expression (Comma Expression)* | e
|
||||||
//
|
//
|
||||||
// expression := primary_expression (op primary_expression)*
|
// expression := primary_expression (op primary_expression)*
|
||||||
// primary_expression := Number | String | identifier_expr | paren_expr | conditional_expr |
|
// primary_expression := Number | String | identifier_expr | paren_expr | conditional_expr |
|
||||||
// while_expr
|
// while_expr | lambda_expr
|
||||||
// identifier_expr := call_expression | Variable
|
// identifier_expr := call_expression | Variable
|
||||||
// while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace
|
// while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace
|
||||||
// paren_expr := LParen expression RParen
|
// paren_expr := LParen expression RParen
|
||||||
// call_expr := Identifier LParen exprlist RParen
|
// call_expr := Identifier LParen exprlist RParen
|
||||||
// conditional_expr := IF expression LCurlyBrace (expression delimiter)* RCurlyBrace (LCurlyBrace (expresion delimiter)* RCurlyBrace)?
|
// conditional_expr := IF expression LCurlyBrace (expression delimiter)* RCurlyBrace (LCurlyBrace (expresion delimiter)* RCurlyBrace)?
|
||||||
|
// lambda_expr := FN LParen identlist RParen LCurlyBrace (expression delimiter)* RCurlyBrace
|
||||||
// op := '+', '-', etc.
|
// op := '+', '-', etc.
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -394,6 +395,7 @@ impl Parser {
|
|||||||
Some(Keyword(Kw::While)) => try!(self.while_expr()),
|
Some(Keyword(Kw::While)) => try!(self.while_expr()),
|
||||||
Some(Identifier(_)) => try!(self.identifier_expr()),
|
Some(Identifier(_)) => try!(self.identifier_expr()),
|
||||||
Some(Token::LParen) => try!(self.paren_expr()),
|
Some(Token::LParen) => try!(self.paren_expr()),
|
||||||
|
Some(Keyword(Kw::Fn)) => try!(self.lambda_expr()),
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
return ParseError::result_from_str(&format!("Expected primary expression, got \
|
return ParseError::result_from_str(&format!("Expected primary expression, got \
|
||||||
{:?}",
|
{:?}",
|
||||||
@ -403,6 +405,30 @@ impl Parser {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lambda_expr(&mut self) -> ParseResult<Expression> {
|
||||||
|
use self::Expression::*;
|
||||||
|
expect!(self, Keyword(Kw::Fn));
|
||||||
|
skip_whitespace!(self);
|
||||||
|
expect!(self, LParen);
|
||||||
|
let parameters = try!(self.identlist());
|
||||||
|
expect!(self, RParen);
|
||||||
|
skip_whitespace!(self);
|
||||||
|
expect!(self, LCurlyBrace);
|
||||||
|
let body = try!(self.body());
|
||||||
|
expect!(self, RCurlyBrace);
|
||||||
|
|
||||||
|
let prototype = Prototype {
|
||||||
|
name: Rc::new("a lambda yo!".to_string()),
|
||||||
|
parameters: parameters,
|
||||||
|
};
|
||||||
|
|
||||||
|
let function = Function {
|
||||||
|
prototype: prototype,
|
||||||
|
body: body,
|
||||||
|
};
|
||||||
|
Ok(Lambda(function))
|
||||||
|
}
|
||||||
|
|
||||||
fn while_expr(&mut self) -> ParseResult<Expression> {
|
fn while_expr(&mut self) -> ParseResult<Expression> {
|
||||||
use self::Expression::*;
|
use self::Expression::*;
|
||||||
expect!(self, Keyword(Kw::While));
|
expect!(self, Keyword(Kw::While));
|
||||||
@ -503,7 +529,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn call_parse_test() {
|
fn function_parse_test() {
|
||||||
use super::Function;
|
use super::Function;
|
||||||
parsetest!(
|
parsetest!(
|
||||||
"fn a() { 1 + 2 }",
|
"fn a() { 1 + 2 }",
|
||||||
@ -518,6 +544,10 @@ mod tests {
|
|||||||
match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false }
|
match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false }
|
||||||
&& **name == "a" && *parameters[0] == "x" && *parameters[1] == "y" && parameters.len() == 2
|
&& **name == "a" && *parameters[0] == "x" && *parameters[1] == "y" && parameters.len() == 2
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let t3 = "fn (x) { x + 2 }";
|
||||||
|
let tokens3 = tokenizer::tokenize(t3).unwrap();
|
||||||
|
assert!(parse(&tokens3, &[]).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -537,6 +567,20 @@ mod tests {
|
|||||||
**plus == "+" && **mul == "*" && **a == "a" && **b == "b" && **c == "c");
|
**plus == "+" && **mul == "*" && **a == "a" && **b == "b" && **c == "c");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lambda_parse_test() {
|
||||||
|
use tokenizer;
|
||||||
|
let t1 = "(fn(x) { x + 2 })";
|
||||||
|
let tokens1 = tokenizer::tokenize(t1).unwrap();
|
||||||
|
match parse(&tokens1, &[]).unwrap()[..] {
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
let t2 = "fn(x) { x + 2 }";
|
||||||
|
let tokens2 = tokenizer::tokenize(t2).unwrap();
|
||||||
|
assert!(parse(&tokens2, &[]).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn conditional_parse_test() {
|
fn conditional_parse_test() {
|
||||||
use tokenizer;
|
use tokenizer;
|
||||||
|
Loading…
Reference in New Issue
Block a user