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) + ]) + ]); +}