diff --git a/src/lib.rs b/src/lib.rs index e69de29..4e2245c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -0,0 +1,82 @@ +use logos::Logos; + +mod lexer { + use logos::Logos; + + #[derive(Logos, Clone, Eq, PartialEq, Hash)] + pub enum Token<'a> { + #[token("λ")] + Lambda, + + #[token(".")] + Dot, + + #[token(":=")] + Binding, + + #[token("(")] + ParenO, + + #[token(")")] + ParenC, + + #[regex("[a-zA-Z]+")] + Ident(&'a str), + + #[error] + #[regex(r"[ \t\r\n]+", logos::skip)] + Error, + } +} + +mod parser { + use crate::lexer::Token; + use chumsky::prelude::*; + + enum Expr { + Name(String), + Application { + function: Box, + argument: Box, + }, + Abstraction { + args: Vec, + body: Expr, + }, + } + + fn expr_parser<'a>() -> impl Parser, Spanned, Error = Simple>> + Clone + { + recursive(|expr| { + let variable = filter_map(|span, token| match token { + Token::Ident(name) => Ok(Expr::Name(name.to_string())), + _ => Err(Simple::expected_input_found(span, [], Some(token))), + }) + .labelled("variable"); + + let abstraction = just(Token::Lambda) + .ignore_then(variable) + .then(Token::Dot) + .then(expr.clone()); + + let application = just(expr).then(expr.clone()); + + let atom = variable + .or(expr.delimited_by(Token::ParenO, Token::ParenC)) + .or(abstraction) + .or(application); + + let binding = just(variable) + .then_ignore(Token::Binding) + .then(expr.clone()); + + let statement = just(expr.clone()).or(binding); + + todo!() + }) + } +} + +pub fn run(input: &str) { + let mut lex = lexer::Token::lexer(input); +} diff --git a/src/main.rs b/src/main.rs index e7a11a9..4021117 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,3 @@ fn main() { - println!("Hello, world!"); + lambda_calculus::run("hello"); }