diff options
| author | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-24 11:28:47 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-24 11:28:47 +0200 |
| commit | ee3db87e63a7c1d1dca9ee5eb1bb9525dea86f49 (patch) | |
| tree | 1a286d037ea55ac1510f05e8a369dbf4dee12ef4 /rust/src | |
| parent | de772d0a77d7ca80e344b4a76b324ea8f8051331 (diff) | |
| download | lambda-nantes-ee3db87e63a7c1d1dca9ee5eb1bb9525dea86f49.tar.gz | |
Parse binary application with parens
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/ast.rs | 2 | ||||
| -rw-r--r-- | rust/src/parser.rs | 30 |
2 files changed, 30 insertions, 2 deletions
diff --git a/rust/src/ast.rs b/rust/src/ast.rs index b179704..0493f59 100644 --- a/rust/src/ast.rs +++ b/rust/src/ast.rs @@ -5,6 +5,7 @@ pub enum Value { Num(i32), Bool(bool), Sym(String), + App(Box<Value>, Box<Value>), } impl Display for Value { @@ -13,6 +14,7 @@ impl Display for Value { Value::Num(i) => write!(f, "{}", i), Value::Bool(b) => write!(f, "{}", b), Value::Sym(s) => write!(f, "{}", s), + Value::App(l, r) => write!(f, "({} {})", l, r), } } } 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<Value>) -> Result<Value, String> { + 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<Value, String> { @@ -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 { |
