summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock54
-rw-r--r--Cargo.toml6
-rw-r--r--src/parser.rs84
3 files changed, 143 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2484e75..1f0b48f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,5 +3,59 @@
version = 3
[[package]]
+name = "peg"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a07f2cafdc3babeebc087e499118343442b742cc7c31b4d054682cc598508554"
+dependencies = [
+ "peg-macros",
+ "peg-runtime",
+]
+
+[[package]]
+name = "peg-macros"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a90084dc05cf0428428e3d12399f39faad19b0909f64fb9170c9fdd6d9cd49b"
+dependencies = [
+ "peg-runtime",
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "peg-runtime"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
name = "type-systems"
version = "0.1.0"
+dependencies = [
+ "peg",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
diff --git a/Cargo.toml b/Cargo.toml
index 6151d0f..e32075d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,3 +4,9 @@ version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+peg = "0.8.1"
+
+[features]
+trace = ["peg/trace"]
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<Expression, peg::error::ParseError<peg::str::LineCol>> {
+ // 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::<String>()
+ }
+ 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::<String>().parse::<Value>().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>
+ = 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<Expression> {
todo!();
}