summaryrefslogtreecommitdiff
path: root/rust/src/parser.rs
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud.bailly@iohk.io>2024-09-25 12:38:55 +0200
committerArnaud Bailly <arnaud.bailly@iohk.io>2024-09-25 12:52:36 +0200
commit7263237a7e2a3dcfb19978e3ebae022a8f2cb0b8 (patch)
treede6098a036c56804d8fe445d4e2b69546ac3c0ef /rust/src/parser.rs
parenta99986ec4c903f116a5ed264f5cbbcba954c9338 (diff)
downloadlambda-nantes-7263237a7e2a3dcfb19978e3ebae022a8f2cb0b8.tar.gz
Parse definitions of symbols
Diffstat (limited to 'rust/src/parser.rs')
-rw-r--r--rust/src/parser.rs41
1 files changed, 37 insertions, 4 deletions
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()
}
}