diff options
| author | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-25 12:38:55 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-25 12:52:36 +0200 |
| commit | 7263237a7e2a3dcfb19978e3ebae022a8f2cb0b8 (patch) | |
| tree | de6098a036c56804d8fe445d4e2b69546ac3c0ef | |
| parent | a99986ec4c903f116a5ed264f5cbbcba954c9338 (diff) | |
| download | lambda-nantes-7263237a7e2a3dcfb19978e3ebae022a8f2cb0b8.tar.gz | |
Parse definitions of symbols
| -rw-r--r-- | rust/src/ast.rs | 2 | ||||
| -rw-r--r-- | rust/src/parser.rs | 41 |
2 files changed, 39 insertions, 4 deletions
diff --git a/rust/src/ast.rs b/rust/src/ast.rs index 722e9e0..8729fa2 100644 --- a/rust/src/ast.rs +++ b/rust/src/ast.rs @@ -7,6 +7,7 @@ pub enum Value { Sym(String), App(Box<Value>, Box<Value>), Lam(String, Box<Value>), + Def(String, Box<Value>), } impl Display for Value { @@ -17,6 +18,7 @@ impl Display for Value { Value::Sym(s) => write!(f, "{}", s), Value::App(l, r) => write!(f, "({} {})", l, r), Value::Lam(var, body) => write!(f, "(lam {} {})", var, body), + Value::Def(var, value) => write!(f, "(def {} {})", var, value), } } } diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 48ef2e0..d733008 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -6,8 +6,10 @@ enum Token { RParen, Lambda, Word(String), + Define, } +#[derive(Debug)] struct Parser { tokens: Vec<Token>, index: usize, @@ -55,7 +57,7 @@ pub fn parse(arg: &str) -> Vec<Value> { let mut parser = Parser { tokens, index: 0 }; let mut result = Vec::new(); while parser.index < parser.tokens.len() { - let expr = parse_expression(&mut parser) + let expr = parse_toplevel(&mut parser) .map_err(|e| panic!("Syntax error: {}", e)) .unwrap(); result.push(expr); @@ -63,6 +65,23 @@ pub fn parse(arg: &str) -> Vec<Value> { result } +fn parse_toplevel(parser: &mut Parser) -> Result<Value, String> { + parse_definition(parser).or_else(|_| parse_expression(parser)) +} + +fn parse_definition(parser: &mut Parser) -> Result<Value, String> { + parser.expect(Token::LParen)?; + parser.expect(Token::Define).map_err(|e| { + parser.backtrack(); + e.to_string() + })?; + println!("parser {:?}", parser); + let var = parse_variable(parser)?; + let body = parse_expression(parser)?; + parser.expect(Token::RParen)?; + Ok(Value::Def(var, Box::new(body))) +} + fn parse_expression(parser: &mut Parser) -> Result<Value, String> { parse_abstraction(parser) .or_else(|_| parse_application(parser)) @@ -130,6 +149,8 @@ fn terminate(result: &mut Vec<Token>, word: &mut String) { let w = word.clone(); if w == "lam" { result.push(Token::Lambda); + } else if w == "def" { + result.push(Token::Define); } else { result.push(Token::Word(w)); } @@ -251,6 +272,14 @@ mod tests { } #[test] + fn parse_definition() { + assert_eq!( + vec![Def("x".to_string(), Box::new(Num(12)))], + parse("(def x 12)") + ); + } + + #[test] fn parse_multiple_values() { assert_eq!(vec![Sym("foo".to_string()), Num(42)], parse("foo 42")); } @@ -267,12 +296,16 @@ mod tests { // see https://unicode.org/reports/tr18/#General_Category_Property for one letter unicode categories identifier.prop_map(Sym), ]; - leaf.prop_recursive(4, 128, 5, move |inner| { + let expr = leaf.prop_recursive(4, 128, 5, move |inner| { prop_oneof![ (inner.clone(), inner.clone()).prop_map(|(l, r)| App(Box::new(l), Box::new(r))), - (identifier, inner).prop_map(|(var, body)| Lam(var, Box::new(body))), + (identifier, inner.clone()).prop_map(|(var, body)| Lam(var, Box::new(body))), ] - }) + }); + prop_oneof![ + expr.clone(), + (identifier, expr).prop_map(|(var, body)| Def(var, Box::new(body))) + ] .boxed() } } |
