Update type syntax

main
trivernis 2 months ago
parent 621664a23b
commit a14471651b
Signed by: Trivernis
GPG Key ID: 7E6D18B61C8D2F4B

@ -87,36 +87,36 @@ let add_all a b c: Num -> Num -> Num -> Num =
The value for a type is one of the following:
- `enum {...}` enum
- `rec {...}` record
- `(|...|...)` enum
- `{...}` record
- `#(...)` tuple
These expressions can be nested.
```sk
type MyEnum = enum {
Var1 Int
Var2 Bool
}
type MyEnum = (
| Var1 Int
| Var2 Bool
)
type MyRec = rec {
type MyRec = {
field1: Float
field2: Str
}
// records declared in one line need to put a semicolon after each field declaration
type MyRecOneline = rec {field1: Float; field2: Str}
// records declared in one line need to put a comma after each field declaration
type MyRecOneline = {field1: Float, field2: Str}
// tuples can be declared in one line without a semicolon because there's no ambiguity
type MyTuple = #(Float Str)
// so need tuples
type MyTuple = #(Float, Str)
type Nested = rec {
field1: enum {
Boolean Bool
Number Float
}
field2: #(Bool Bool)
field3: rec {
type Nested = {
field1: (
| Boolean Bool
| Number Float
)
field2: #(Bool, Bool)
field3: {
first: Int
second: Int
}

@ -1,40 +1,40 @@
type Food = enum {
Apple Num
Banana Num
Cereal Num
Milk #(String Num)
}
type Food = (
| Apple Num
| Banana Num
| Cereal Num
| Milk #(String, Num)
)
type Utils = enum {
Paper Num
Detergent Num
Pencils Num
}
type Utils = (
| Paper Num
| Detergent Num
| Pencils Num
)
type Packaging = enum {
Bag
PlasticBag
}
type Packaging = (
| Bag
| PlasticBag
)
type ShoppingList = rec {
type ShoppingList = {
food: Food
utils: Utils
packaging: Packaging
}
type NestedHell = enum {
NoNesting Num
Nesting enum {
FirstLevel enum {
SecondLevel enum {
Third Lvl<a>
}
Second rec {
type NestedHell a = (
| NoNesting Num
| Nesting (
| FirstLevel (
| SecondLevel (
| Third Lvl
)
| Second {
first: Num
second: Num
}
}
StillFirst Num<a>
}
}
)
| StillFirst Num a
)
)

@ -20,7 +20,7 @@ infix_expr = {
}
operator = { "+" | "-" | "*" | "/" | "&&" | "||" | "<" | ">" | "==" | "!=" }
ident = @{ !KEYWORD ~ ALPHABETIC ~ (ALPHABETIC | NUMBER | "_")* | quoted_indent }
ident = @{ SYM_ANY_CASE | quoted_indent }
quoted_indent = _{ "`" ~ (!"`" ~ ANY)+ ~ "`" }
// types
@ -31,19 +31,20 @@ type_decl = { "type" ~ #name = type_ident ~ "=" ~ type_expr }
type_expr = { func | type_term | type_ident }
type_term = _{ tuple | rec | enum | type_ident }
tuple = { "#(" ~ MLF ~ tuple_entry* ~ MLF ~ ")" }
tuple = { "#(" ~ MLF ~ (tuple_entry ~ SEPARATE)* ~ MLF ~ tuple_entry? ~ ")" }
tuple_entry = _{ type_expr ~ MLF }
rec = { "rec" ~ "{" ~ MLF ~ (rec_field ~ TERMINATE ~ MLF)* ~ rec_field? ~ MLF ~ "}" }
rec = { "{" ~ MLF ~ (rec_field ~ SEPARATE ~ MLF)* ~ rec_field? ~ MLF ~ "}" }
rec_field = { #field_name = ident ~ ":" ~ #field_type = type_expr* }
enum = { "enum" ~ "{" ~ MLF ~ (enum_vrt ~ TERMINATE ~ MLF)* ~ enum_vrt? ~ "}" }
enum = { "(" ~ MLF ~ ("|" ~ enum_vrt ~ MLF)* ~ "|"? ~ MLF ~ ")" }
enum_vrt = { #vrt_name = ident ~ type_expr? }
func = { type_term ~ "->" ~ type_expr }
type_ident = ${ #name = ident ~ #args = type_args? }
type_args = { "<" ~ MLF ~ type_ident* ~ MLF ~ ">" }
type_ident = { #name = type_name ~ #args = (type_arg)* }
type_name = @{ SYM_PASCAL_CASE }
type_arg = @{ SYM_CAMEL_CASE }
// match patterns that destructure a variant
// TODO: copy it for declarations where destructuring can only be done into one variant
@ -75,8 +76,13 @@ byte = @{ "0x" ~ ASCII_HEX_DIGIT{1, 2} | "0b" ~ ASCII_BIN_DIGIT{0, 8} }
// utils
KEYWORD = _{ "let" | "rec" | "enum" | "if" | "then" | "else" }
SYM_ANY_CASE = @{ !KEYWORD ~ ASCII_ALPHA ~ (ALPHABETIC | NUMBER | "_")* }
SYM_PASCAL_CASE = @{ !KEYWORD ~ ASCII_ALPHA_UPPER ~ (ALPHABETIC | NUMBER | "_")* }
SYM_CAMEL_CASE = @{ !KEYWORD ~ ASCII_ALPHA_LOWER ~ (ALPHABETIC | NUMBER | "_")* }
KEYWORD = _{ "let" | "enum" | "if" | "then" | "else" }
TERMINATE = _{ LF | EOI | ";" }
SEPARATE = _{ LF | EOI | "," }
MLF = _{ (LF)* }
LF = _{ "\n" | "\r" }

@ -10,49 +10,16 @@ lazy_static! {
#[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)
])
]);
if let Err(e) = (*TESTER).evaluate_strict("aliases") {
panic!("{e}")
}
}
#[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)
])
]);
if let Err(e) = (*TESTER).evaluate_strict("tuples") {
panic!("{e}")
}
}
#[test]

@ -14,7 +14,7 @@ let add_a x: Num -> Num = x + a
(type_annot
(type_expr
(type_ident
(ident: "Num")
(type_name: "Num")
)
)
)
@ -39,11 +39,11 @@ let add_a x: Num -> Num = x + a
(type_expr
(func
(type_ident
(ident: "Num")
(type_name: "Num")
)
(type_expr
(type_ident
(ident: "Num")
(type_name: "Num")
)
)
)

@ -0,0 +1,23 @@
Aliases Test
======
type MyNum = Num
======
(file
(statement
(type_decl
(type_ident
(type_name: "MyNum")
)
(type_expr
(type_ident
(type_name: "Num")
)
)
)
)
(EOI: "")
)

@ -2,10 +2,10 @@ Enums Test
======
type MyEnum = enum {
First Num
Second Str
}
type MyEnum = (
| First Num
| Second Str
)
======
@ -13,7 +13,7 @@ type MyEnum = enum {
(statement
(type_decl
(type_ident
(ident: "MyEnum")
(type_name: "MyEnum")
)
(type_expr
(enum
@ -21,7 +21,7 @@ type MyEnum = enum {
(ident: "First")
(type_expr
(type_ident
(ident: "Num")
(type_name: "Num")
)
)
)
@ -29,7 +29,7 @@ type MyEnum = enum {
(ident: "Second")
(type_expr
(type_ident
(ident: "Str")
(type_name: "Str")
)
)
)

@ -10,21 +10,21 @@ type MyFn = Num -> Num -> Str
(statement
(type_decl
(type_ident
(ident: "MyFn")
(type_name: "MyFn")
)
(type_expr
(func
(type_ident
(ident: "Num")
(type_name: "Num")
)
(type_expr
(func
(type_ident
(ident: "Num")
(type_name: "Num")
)
(type_expr
(type_ident
(ident: "Str")
(type_name: "Str")
)
)
)

@ -2,7 +2,7 @@ Generics Test
======
type MyNum<a> = Num<a>
type MyNum a = Num a
======
@ -10,21 +10,13 @@ type MyNum<a> = Num<a>
(statement
(type_decl
(type_ident
(ident: "MyNum")
(type_args
(type_ident
(ident: "a")
)
)
(type_name: "MyNum")
(type_arg: "a")
)
(type_expr
(type_ident
(ident: "Num")
(type_args
(type_ident
(ident: "a")
)
)
(type_name: "Num")
(type_arg: "a")
)
)
)

@ -2,7 +2,7 @@ Recs Test
======
type MyRec = rec {
type MyRec = {
first: Num
second: Str
}
@ -13,7 +13,7 @@ type MyRec = rec {
(statement
(type_decl
(type_ident
(ident: "MyRec")
(type_name: "MyRec")
)
(type_expr
(rec
@ -21,7 +21,7 @@ type MyRec = rec {
(ident: "first")
(type_expr
(type_ident
(ident: "Num")
(type_name: "Num")
)
)
)
@ -29,7 +29,7 @@ type MyRec = rec {
(ident: "second")
(type_expr
(type_ident
(ident: "Str")
(type_name: "Str")
)
)
)

@ -0,0 +1,32 @@
Tuples Test
======
type MyTuple = #(Str, Int)
======
(file
(statement
(type_decl
(type_ident
(type_name: "MyTuple")
)
(type_expr
(tuple
(type_expr
(type_ident
(type_name: "Str")
)
)
(type_expr
(type_ident
(type_name: "Int")
)
)
)
)
)
)
(EOI: "")
)
Loading…
Cancel
Save