From ee3db87e63a7c1d1dca9ee5eb1bb9525dea86f49 Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Tue, 24 Sep 2024 11:28:47 +0200 Subject: Parse binary application with parens --- rust/src/parser.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'rust/src/parser.rs') diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 50cf918..8f95ca9 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -8,8 +8,27 @@ enum Token { } pub fn parse(arg: &str) -> Value { - let tokens = tokenize(arg); - parse_value(&tokens[0]).unwrap() + let mut tokens = tokenize(arg); + let mut state = Vec::new(); + parse_tokens(&mut tokens, &mut state).unwrap() +} + +fn parse_tokens(tokens: &mut [Token], state: &mut Vec) -> Result { + match tokens { + [] => state.pop().ok_or("Empty expression".to_string()), + [Token::LParen, rest @ ..] => parse_tokens(rest, state), + [Token::RParen, rest @ ..] => { + let right = state.pop().ok_or("Unbalanced parentheses".to_string())?; + let left = state.pop().ok_or("Unbalanced parentheses".to_string())?; + state.push(Value::App(Box::new(left), Box::new(right))); + parse_tokens(rest, state) + } + [Token::Word(s), rest @ ..] => { + let value = parse_value(&Token::Word(s.clone()))?; + state.push(value); + parse_tokens(rest, state) + } + } } fn parse_value(token: &Token) -> Result { @@ -133,6 +152,13 @@ mod tests { tokenize("( \r() 42) \ntrue( ") ); } + + #[test] + fn parse_application_of_two_values() { + assert_eq!( + App(Box::new(Sym("foo".to_string())), Box::new(Num(42))), + parse("(foo 42)") + ); } impl Arbitrary for Value { -- cgit v1.2.3