summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud.bailly@iohk.io>2024-09-25 15:49:59 +0200
committerArnaud Bailly <arnaud.bailly@iohk.io>2024-09-25 15:49:59 +0200
commit7f83391f3e4f37fbc512fd7d2bb7c7ec2f0858e9 (patch)
treede401812879b7857e8ba10fc3c740bf4a0651d15 /rust/src
parent56678d54123426d7975cb5786b10c82af5bc0472 (diff)
downloadlambda-nantes-7f83391f3e4f37fbc512fd7d2bb7c7ec2f0858e9.tar.gz
Ensure application has at least two values
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/parser.rs29
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![App(