From ccbec05210dfd810a950b483db0e0c60ce83859d Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Wed, 25 Sep 2024 15:18:23 +0200 Subject: Allow multiple variables in single lambda --- rust/src/parser.rs | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'rust/src/parser.rs') diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 23a512b..874b893 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -95,10 +95,30 @@ fn parse_abstraction(parser: &mut Parser) -> Result { parser.backtrack(); e.to_string() })?; - let var = parse_variable(parser)?; + let vars = parse_variables(parser)?; let body = parse_expression(parser)?; parser.expect(Token::RParen)?; - Ok(Value::Lam(var, Box::new(body))) + let result = vars + .iter() + .rev() + .fold(body, |acc, var| Value::Lam(var.clone(), Box::new(acc))); + Ok(result) +} + +fn parse_variables(parser: &mut Parser) -> Result, String> { + parse_variable(parser) + .map(|s| vec![s]) + .or_else(|_| parse_variables_list(parser)) +} + +fn parse_variables_list(parser: &mut Parser) -> Result, String> { + let mut vars = Vec::new(); + parser.expect(Token::LParen)?; + while let Ok(var) = parse_variable(parser) { + vars.push(var); + } + parser.expect(Token::RParen)?; + Ok(vars) } fn parse_variable(parser: &mut Parser) -> Result { @@ -289,6 +309,17 @@ mod tests { ); } + #[test] + fn desugar_abstraction_with_several_variables_into_nested_lambdas() { + assert_eq!( + vec![Lam( + "x".to_string(), + Box::new(Lam("y".to_string(), Box::new(Sym("y".to_string())))) + )], + parse("(lam (x y) y)") + ); + } + #[test] fn parse_definition() { assert_eq!( -- cgit v1.2.3