From 3188a0ec2174945a6b004db78b534f80c7927796 Mon Sep 17 00:00:00 2001 From: JJ Date: Wed, 5 Apr 2023 09:18:12 -0700 Subject: this was a bad idea --- src/parser.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'src/parser.rs') diff --git a/src/parser.rs b/src/parser.rs index 3223619..cb86ea7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,88 @@ use crate::ast::*; +// (λx:T.y): T z pub fn parse(input: &str) -> Expression { - let input = input.trim(); + return parse_str(input).expect("invalid expression"); +} + +/// Parses a lambda-calculus-like language into an AST. +pub fn parse_str(input: &str) -> Result> { + // this is kinda awful + // i miss my nim pegs + peg::parser!{ + grammar lambda() for str { + rule identifier() -> String + = i:['a'..='z' | 'A'..='Z' | '0'..='9']+ { + i.iter().collect::() + } + rule kind() -> Type + = k:identifier() { + match k.as_str() { + "unit" => Type::Unit, + "bool" => Type::Bool, + "int" => Type::Natural, + _ => panic!("invalid type") + } + } + rule annotation() -> Expression + = e:(conditional() / abstraction() / application() / constant() / variable()) " "* ":" " "* k:kind() { + Expression::Annotation { + expr: Box::new(e), + kind: k + } + } + rule constant() -> Expression + = c:['0'..='9']+ { + Expression::Constant { + term: Term { + val: c.iter().collect::().parse::().unwrap(), + kind: Type::Empty + } + } + } + rule variable() -> Expression + = v:identifier() { + Expression::Variable { + id: v + } + } + // fixme: lambda is causing problems with rust-peg + rule abstraction() -> Expression + = "λ" " "* p:identifier() " "+ "." " "+ f:expression() { + Expression::Abstraction { + param: p, + func: Box::new(f) + } + } + rule application() -> Expression + = "(" f:(abstraction() / annotation()) ")" " "+ a:expression() { + Expression::Application { + func: Box::new(f), + arg: Box::new(a) + } + } + rule conditional() -> Expression + = "if" " "+ c:expression() " "+ "then" " "+ t:expression() " "+ "else" " "+ e:expression() { + Expression::Conditional { + if_cond: Box::new(c), + if_then: Box::new(t), + if_else: Box::new(e) + } + } + pub rule expression() -> Expression + = e:(conditional() / annotation() / abstraction() / application() / constant() / variable()) { + e + } + pub rule ast() -> Vec + = expression() ** ("\n"+) + } + } + // assert_eq!(lambda::expression("(λx:bool.x)").unwrap(), lambda::expression("(λx: bool . x)").unwrap()); + + return lambda::expression(input.trim()); +} + +/// Parses a Nim-like language into an AST. +pub fn parse_file(path: &str) -> Vec { todo!(); } -- cgit v1.2.3-70-g09d2