diff options
| author | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-25 15:49:59 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-25 15:49:59 +0200 |
| commit | 7f83391f3e4f37fbc512fd7d2bb7c7ec2f0858e9 (patch) | |
| tree | de401812879b7857e8ba10fc3c740bf4a0651d15 | |
| parent | 56678d54123426d7975cb5786b10c82af5bc0472 (diff) | |
| download | lambda-nantes-7f83391f3e4f37fbc512fd7d2bb7c7ec2f0858e9.tar.gz | |
Ensure application has at least two values
| -rw-r--r-- | rust/src/parser.rs | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 3ac01ef..121a10f 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -54,16 +54,20 @@ impl Parser { } pub fn parse(arg: &str) -> Vec<Value> { + parse_total(arg) + .map_err(|e| panic!("Syntax error: {}", e)) + .unwrap() +} + +pub fn parse_total(arg: &str) -> Result<Vec<Value>, String> { let tokens = tokenize(arg); let mut parser = Parser { tokens, index: 0 }; let mut result = Vec::new(); while parser.index < parser.tokens.len() { - let expr = parse_toplevel(&mut parser) - .map_err(|e| panic!("Syntax error: {}", e)) - .unwrap(); + let expr = parse_toplevel(&mut parser)?; result.push(expr); } - result + Ok(result) } fn parse_toplevel(parser: &mut Parser) -> Result<Value, String> { @@ -83,10 +87,10 @@ fn parse_definition(parser: &mut Parser) -> Result<Value, String> { } fn parse_expression(parser: &mut Parser) -> Result<Value, String> { - parse_abstraction(parser) + parse_value(parser) + .or_else(|_| parse_abstraction(parser)) .or_else(|_| parse_let(parser)) .or_else(|_| parse_application(parser)) - .or_else(|_| parse_value(parser)) } fn parse_abstraction(parser: &mut Parser) -> Result<Value, String> { @@ -148,6 +152,9 @@ fn parse_application(parser: &mut Parser) -> Result<Value, String> { while let Ok(expr) = parse_expression(parser) { exprs.push(expr); } + if exprs.is_empty() { + return Err("Application needs two values".to_string()); + } parser.expect(Token::RParen)?; let app: Value = exprs.iter().fold(init, |acc, expr| { Value::App(Box::new(acc.clone()), Box::new(expr.clone())) @@ -228,6 +235,8 @@ fn parse_number(token: &Token) -> Result<Value, String> { #[cfg(test)] mod tests { + use crate::parse_total; + use super::Token::*; use super::Value; use super::Value::*; @@ -302,6 +311,14 @@ mod tests { } #[test] + fn reject_application_of_single_value() { + assert_eq!( + Err("Application needs two values".to_string()), + parse_total("(foo )") + ); + } + + #[test] fn desugar_application_of_more_than_two_values() { assert_eq!( vec