diff --git a/src/grammar.pest b/src/grammar.pest
index 384338f..70f9810 100644
--- a/src/grammar.pest
+++ b/src/grammar.pest
@@ -2,9 +2,15 @@ file = { "hello world" }
block = { "{" ~ MLF ~ block_line ~ MLF ~ "}" }
block_line = _{ expr | (statement ~ MLF)* }
-statement = { (decl | expr) ~ TERMINATE }
+statement = { (decl | type_decl | expr) ~ TERMINATE }
decl = { "let" ~ #name = ident ~ #args = (ident)* ~ "=" ~ expr }
+type_decl = { "type" ~ #name = type_ident ~ "=" ~ type_expr }
+type_expr = { tuple | type_ident }
+tuple = { "#(" ~ type_expr* ~ ")" }
+type_ident = ${ #name = ident ~ #args = type_args? }
+type_args = { "<" ~ type_ident* ~ ">" }
+
expr = { infix_expr | call_expr | term }
term = _{ ident | literal | "(" ~ MLF ~ expr ~ MLF ~ ")" | block }
call_expr = {
diff --git a/src/test/expressions.rs b/src/test/expressions.rs
index 86708b4..9d315ee 100644
--- a/src/test/expressions.rs
+++ b/src/test/expressions.rs
@@ -130,4 +130,27 @@ fn it_parses_calls() {
])
])
]);
+ parses_to!(parser: SnekParser, input: "print {1 + 1} a", rule: Rule::expr, tokens: [
+ expr(0, 15, [
+ call_expr(0, 15, [
+ ident(0, 5),
+ block(6, 13, [
+ expr(7, 12, [
+ infix_expr(7, 12, [
+ literal(7, 8, [
+ integer(7, 8)
+ ]),
+ operator(9, 10),
+ expr(11, 12, [
+ literal(11, 12, [
+ integer(11, 12)
+ ]),
+ ])
+ ])
+ ])
+ ]),
+ ident(14, 15)
+ ])
+ ])
+ ]);
}
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 255b9e3..ae20ded 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -1,6 +1,7 @@
mod expressions;
mod literals;
mod statements;
+mod types;
use crate::parse;
diff --git a/src/test/types.rs b/src/test/types.rs
new file mode 100644
index 0000000..351974d
--- /dev/null
+++ b/src/test/types.rs
@@ -0,0 +1,79 @@
+use pest::{consumes_to, parses_to};
+
+use crate::{Rule, SnekParser};
+
+#[test]
+fn it_parses_aliases() {
+ parses_to!(parser: SnekParser, input: "type MyNum = Num", rule: Rule::statement, tokens: [
+ statement(0, 16, [
+ type_decl(0, 16, [
+ type_ident(5, 10, [
+ ident(5, 10)
+ ]),
+ type_expr(13, 16, [
+ type_ident(13, 16, [
+ ident(13, 16)
+ ])
+ ])
+ ]),
+ EOI(16, 16)
+ ])
+ ]);
+}
+
+#[test]
+fn it_parses_tuples() {
+ parses_to!(parser: SnekParser, input: "type MyTuple = #(Str Int)", rule: Rule::statement, tokens: [
+ statement(0, 25, [
+ type_decl(0, 25, [
+ type_ident(5, 12, [
+ ident(5, 12)
+ ]),
+ type_expr(15, 25, [
+ tuple(15, 25, [
+ type_expr(17, 20, [
+ type_ident(17, 20, [
+ ident(17, 20)
+ ])
+ ]),
+ type_expr(21, 24, [
+ type_ident(21, 24, [
+ ident(21, 24)
+ ])
+ ]),
+ ])
+ ])
+ ]),
+ EOI(25, 25)
+ ])
+ ]);
+}
+
+#[test]
+fn it_parses_generics() {
+ parses_to!(parser: SnekParser, input: "type MyNum = Num", rule: Rule::statement, tokens: [
+ statement(0, 22, [
+ type_decl(0, 22, [
+ type_ident(5, 13, [
+ ident(5, 10),
+ type_args(10, 13, [
+ type_ident(11, 12, [
+ ident(11, 12)
+ ])
+ ])
+ ]),
+ type_expr(16, 22, [
+ type_ident(16, 22, [
+ ident(16, 19),
+ type_args(19, 22, [
+ type_ident(20, 21, [
+ ident(20, 21)
+ ])
+ ])
+ ])
+ ])
+ ]),
+ EOI(22, 22)
+ ])
+ ]);
+}