diff --git a/src/grammar.pest b/src/grammar.pest index 70f9810..7c87493 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -5,11 +5,14 @@ block_line = _{ expr | (statement ~ MLF)* } 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* ~ ">" } +type_decl = { "type" ~ #name = type_ident ~ "=" ~ type_expr } +type_expr = { tuple | rec | type_ident } +tuple = { "#(" ~ MLF ~ tuple_entry* ~ MLF ~ ")" } +tuple_entry = _{ type_expr ~ MLF } +rec = { "#{" ~ MLF ~ (rec_field ~ TERMINATE ~ MLF)* ~ rec_field? ~ MLF ~ "}" } +rec_field = { #field_name = ident ~ ":" ~ #field_type = type_expr* } +type_ident = ${ #name = ident ~ #args = type_args? } +type_args = { "<" ~ MLF ~ type_ident* ~ MLF ~ ">" } expr = { infix_expr | call_expr | term } term = _{ ident | literal | "(" ~ MLF ~ expr ~ MLF ~ ")" | block } diff --git a/src/test/types.rs b/src/test/types.rs index 351974d..58af932 100644 --- a/src/test/types.rs +++ b/src/test/types.rs @@ -49,6 +49,40 @@ fn it_parses_tuples() { ]); } +#[test] +fn it_parses_recs() { + parses_to!(parser: SnekParser, input: "type MyRec = #{\nfield1: Num\n field2: Num2 }", rule: Rule::statement, tokens: [ + statement(0, 43, [ + type_decl(0, 43, [ + type_ident(5, 10, [ + ident(5, 10) + ]), + type_expr(13, 43, [ + rec(13, 43, [ + rec_field(16, 27, [ + ident(16, 22), + type_expr(24, 27, [ + type_ident(24, 27, [ + ident(24, 27) + ]) + ]), + ]), + rec_field(29, 41, [ + ident(29, 35), + type_expr(37, 41, [ + type_ident(37, 41, [ + ident(37, 41) + ]) + ]), + ]) + ]) + ]) + ]), + EOI(43, 43) + ]) + ]); +} + #[test] fn it_parses_generics() { parses_to!(parser: SnekParser, input: "type MyNum = Num", rule: Rule::statement, tokens: [