1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
WHITESPACE = _{ (" " | "\t")+ }
botwork = _{ SOI ~ statements* ~ EOI }
reserved = { "true" | "false" | "and" | "or" }
// Special statements. Can cause changes to program behaviour.
IF = _{ ("i" | "I") ~ ("f" | "F") }
IN = _{ ("i" | "I") ~ ("n" | "N") }
ELSE = _{ ("e" | "E") ~ ("l" | "L") ~ ("s" | "S") ~ ("e" | "E") }
FOR = _{ ("f" | "F") ~ ("o" | "O") ~ ("r" | "R") }
BREAK = _{ ("b" | "B") ~ ("r" | "R") ~ ("e" | "E") ~ ("a" | "A") ~ ("k" | "K") }
RETURN = _{ ("r" | "R") ~ ("e" | "E") ~ ("t" | "T") ~ ("u" | "U") ~ ("r" | "R") ~ ("n" | "N") }
CONTINUE = _{ ("c" | "C") ~ ("o" | "O") ~ ("n" | "N") ~ ("t" | "T") ~ ("i" | "I") ~ ("n" | "N") ~ ("u" | "U") ~ ("e" | "E") }
WHILE = _{ ("w" | "W") ~ ("h" | "H") ~ ("i" | "I") ~ ("l" | "L") ~ ("e" | "E") }
TRY = _{ ("t" | "T") ~ ("r" | "R") ~ ("y" | "Y") }
CATCH = _{ ("c" | "C") ~ ("a" | "A") ~ ("t" | "T") ~ ("c" | "C") ~ ("h" | "H") }
reserved_parts = _{ IF | ELSE | FOR | BREAK | RETURN | CONTINUE | WHILE | TRY | CATCH }
COMMENT = _{ comment_block | comment_line }
comment_block = @{ "###" ~ (!"###" ~ ANY)* ~ "###" }
comment_line = @{ "#" ~ (!NEWLINE ~ ANY)* }
part = { (!("|" | "{" | "}" | "\r" | "\n" | "#") ~ ANY)+ }
statements = _{ stmt_break | stmt_continue | stmt_return | stmt_if | stmt_for | stmt_while | stmt_try | stmt_define | stmt_assign | stmt_invoke | NEWLINE }
stmt_assign = { param_define ~ "=" ~ (stmt_invoke | param_invoke) }
stmt_if = { IF ~ param_invoke ~ stmt_block ~ stmt_else? }
stmt_else = { ELSE ~ ( stmt_block | stmt_if) }
stmt_for = { FOR ~ param_define ~ IN ~ param_invoke ~ stmt_block }
stmt_while = { WHILE ~ param_invoke ~ stmt_block }
stmt_try = { TRY ~ stmt_block ~ (stmt_catch)? }
stmt_catch = { CATCH ~ stmt_block }
stmt_define = { stmt_header ~ stmt_block }
stmt_header = { !reserved_parts ~ part ~ (param_define | part)*}
stmt_invoke = { !reserved_parts ~ part ~ (param_invoke | part)* }
stmt_block = { "{" ~ statements* ~ "}" }
stmt_break = { BREAK }
stmt_continue = { CONTINUE }
stmt_return = { RETURN ~ param_invoke? }
param_invoke = { "|" ~ expression ~ "|" }
param_define = _{ "|" ~ ident ~ "|" }
expression = { infix | expression_inner }
infix = _{ expression_inner ~ (binary_operator ~ expression_inner)+ }
expression_inner = _{ unary | primary }
braced_expression = _{ "(" ~ expression ~ ")" }
unary = { unary_operator ~ primary }
primary = _{ literal | dot_path | ident | braced_expression }
dot_path = { ident ~ ("." ~ (ident | integer))+ }
literal = _{ map | array | string | float | integer | boolean }
array = { "[" ~ (expression ~ ("," ~ expression)*)? ~ "]" }
ident = @{ !reserved ~ LETTER ~ (LETTER | NUMBER | "_")* }
map = { "{" ~ (map_pair ~ ("," ~ map_pair)*)? ~ "}" }
map_pair = { keyword ~ seperator ~ expression }
keyword = @{ ident }
seperator = _{ ":" }
integer = @{ NUMBER+ }
float = @{ NUMBER+ ~ "." ~ NUMBER+ }
string = { string_delimiter ~ string_content ~ string_delimiter }
string_content = ${ (string_escape | !(string_delimiter | "\\") ~ ANY)* }
string_delimiter = _{ "\"" }
string_escape = _{ "\\" ~ ("\"" | "\\" | "n") }
exponent = { "^" }
multiply = { "*" }
divide = { "/" }
modulus = { "%" }
plus = { "+" }
minus = { "-" }
less_than = { "<" }
less_than_or_equal = { "<=" }
greater_than = { ">" }
greater_than_or_equal = { ">=" }
not_equal = { "!=" }
equal = { "==" }
logical_and = { "and" }
logical_or = { "or" }
logical_not = { "!" }
binary_operator = _{
exponent
| multiply
| divide
| modulus
| plus
| minus
| less_than_or_equal
| less_than
| greater_than_or_equal
| greater_than
| not_equal
| equal
| logical_and
| logical_or
}
unary_operator = _{ minus | logical_not }
boolean = _{ boolean_true | boolean_false }
boolean_true = { "true" }
boolean_false = { "false" }