272 lines
10 KiB
Plaintext
272 lines
10 KiB
Plaintext
![]() |
ws:ws = " " | "\b" | "\f" | "\r" | "\t" | "\v";
|
||
|
wsc:ws = comment;
|
||
|
nl:alias = "\n";
|
||
|
wsep:alias = ws | nl;
|
||
|
|
||
|
line-comment-content:nows = [^\n]*;
|
||
|
line-comment:alias:nows = "//" line-comment-content;
|
||
|
block-comment-content:nows = ([^*] | "*" [^/])*;
|
||
|
block-comment:alias:nows = "/*" block-comment-content "*/";
|
||
|
comment-part:alias = line-comment | block-comment;
|
||
|
comment:alias = comment-part (nl? comment-part)*;
|
||
|
|
||
|
decimal-digit:alias = [0-9];
|
||
|
octal-digit:alias = [0-7];
|
||
|
hexa-digit:alias = [0-9a-fA-F];
|
||
|
|
||
|
decimal:alias:nows = [1-9] decimal-digit*;
|
||
|
octal:alias:nows = "0" octal-digit*;
|
||
|
hexa:alias:nows = "0" [xX] hexa-digit+;
|
||
|
int = decimal | octal | hexa;
|
||
|
|
||
|
exponent:alias:nows = [eE] [+\-]? decimal-digit+;
|
||
|
float:nows = decimal-digit+ "." decimal-digit* exponent?
|
||
|
| "." decimal-digit+ exponent?
|
||
|
| decimal-digit+ exponent;
|
||
|
|
||
|
string:nows = "\"" ([^\\"] | "\\" .)* "\"";
|
||
|
|
||
|
true = "true";
|
||
|
false = "false";
|
||
|
bool:alias = true | false;
|
||
|
|
||
|
symbol:nows = [a-zA-Z_][a-zA-Z_0-9]*;
|
||
|
|
||
|
spread-expression = primary-expression "...";
|
||
|
list-sep:alias = (nl | ",")+;
|
||
|
list-item:alias = expression | spread-expression;
|
||
|
expression-list:alias = list-item (list-sep list-item)*;
|
||
|
|
||
|
list-fact:alias = "[" list-sep? expression-list? list-sep? "]";
|
||
|
list = list-fact;
|
||
|
mutable-list = "~" nl* list-fact;
|
||
|
|
||
|
expression-key = "[" nl* expression nl* "]";
|
||
|
entry = (symbol | string | expression-key) nl* ":" nl* expression;
|
||
|
entry-list:alias = (entry | spread-expression) (list-sep (entry | spread-expression))*;
|
||
|
struct-fact:alias = "{" list-sep? entry-list? list-sep? "}";
|
||
|
struct = struct-fact;
|
||
|
mutable-struct = "~" nl* struct-fact;
|
||
|
|
||
|
parameter-list:alias = symbol (list-sep symbol)*;
|
||
|
collect-parameter = "..." nl* symbol;
|
||
|
return = "return" | "return" nl* expression;
|
||
|
block = "{" sep? statement-list? sep? "}";
|
||
|
function-fact:alias = "(" list-sep?
|
||
|
(parameter-list
|
||
|
| parameter-list list-sep collect-parameter
|
||
|
| collect-parameter)?
|
||
|
list-sep? ")" nl*
|
||
|
(expression | simple-statement | block);
|
||
|
function = "fn" nl* function-fact;
|
||
|
effect = "fn" nl* "~" nl* function-fact;
|
||
|
|
||
|
range-from = expression;
|
||
|
range-to = expression;
|
||
|
range:alias = range-from? nl* ":" nl* range-to?;
|
||
|
|
||
|
symbol-index = "." nl* symbol;
|
||
|
expression-index = "[" nl* expression nl* "]";
|
||
|
range-index = "[" nl* range nl* "]";
|
||
|
index:alias = symbol-index | expression-index | range-index;
|
||
|
index-list:alias = index (nl* index)?;
|
||
|
indexer = primary-expression nl* index-list;
|
||
|
|
||
|
application = primary-expression "(" list-sep? expression-list? list-sep? ")";
|
||
|
|
||
|
expression-group:alias = "(" nl* expression nl* ")";
|
||
|
primary-expression:alias = int
|
||
|
| float
|
||
|
| string
|
||
|
| bool
|
||
|
| symbol
|
||
|
| list
|
||
|
| mutable-list
|
||
|
| struct
|
||
|
| mutable-struct
|
||
|
| function
|
||
|
| effect
|
||
|
| indexer
|
||
|
| application
|
||
|
| receive
|
||
|
| expression-group;
|
||
|
|
||
|
binary-not = "^";
|
||
|
binary-and = "&";
|
||
|
binary-or = "|";
|
||
|
xor = "^";
|
||
|
and-not = "&^";
|
||
|
lshift = "<<";
|
||
|
rshift = ">>";
|
||
|
|
||
|
plus = "+";
|
||
|
minus = "-";
|
||
|
mul = "*";
|
||
|
div = "/";
|
||
|
mod = "%";
|
||
|
add = "+";
|
||
|
sub = "-";
|
||
|
|
||
|
logical-not = "!";
|
||
|
eq = "==";
|
||
|
not-eq = "!=";
|
||
|
less = "<";
|
||
|
less-or-eq = "<=";
|
||
|
greater = ">";
|
||
|
greater-or-eq = ">=";
|
||
|
logical-and = "&&";
|
||
|
logical-or = "||";
|
||
|
|
||
|
chain:alias = "->";
|
||
|
|
||
|
unary-operator:alias = plus | minus | binary-not | logical-not;
|
||
|
unary-expression = unary-operator primary-expression;
|
||
|
|
||
|
binary-op0:alias = binary-and | and-not | lshift | rshift | mul | div | mod;
|
||
|
binary-op1:alias = binary-or | xor | add | sub;
|
||
|
binary-op2:alias = eq | not-eq | less | less-or-eq | greater | greater-or-eq;
|
||
|
binary-op3:alias = logical-and;
|
||
|
binary-op4:alias = logical-or;
|
||
|
|
||
|
operand0:alias = primary-expression | unary-expression;
|
||
|
operand1:alias = operand0 | binary0;
|
||
|
operand2:alias = operand1 | binary1;
|
||
|
operand3:alias = operand2 | binary2;
|
||
|
operand4:alias = operand3 | binary3;
|
||
|
operand5:alias = operand4 | binary4;
|
||
|
|
||
|
binary0 = operand0 (nl* binary-op0 nl* operand0)+;
|
||
|
binary1 = operand1 (nl* binary-op1 nl* operand1)+;
|
||
|
binary2 = operand2 (nl* binary-op2 nl* operand2)+;
|
||
|
binary3 = operand3 (nl* binary-op3 nl* operand3)+;
|
||
|
binary4 = operand4 (nl* binary-op4 nl* operand4)+;
|
||
|
|
||
|
binary-expression:alias = binary0
|
||
|
| binary1
|
||
|
| binary2
|
||
|
| binary3
|
||
|
| binary4;
|
||
|
|
||
|
ternary-expression = expression nl* "?" nl* expression nl* ":" nl* expression;
|
||
|
|
||
|
chainingOperand:alias = primary-expression
|
||
|
| unary-expression
|
||
|
| binary-expression
|
||
|
| ternary-expression;
|
||
|
chaining = chainingOperand (nl* chain nl* chainingOperand)+;
|
||
|
|
||
|
expression:alias = primary-expression
|
||
|
| unary-expression
|
||
|
| binary-expression
|
||
|
| ternary-expression
|
||
|
| chaining;
|
||
|
|
||
|
if = "if" nl* expression nl* block
|
||
|
(nl* "else" nl* "if" nl* expression nl* block)*
|
||
|
(nl* "else" nl* block)?;
|
||
|
|
||
|
// TODO: empty switch not parsed
|
||
|
default = "default" nl* ":";
|
||
|
default-line:alias = default ";"* statement?;
|
||
|
case = "case" nl* expression nl* ":";
|
||
|
case-line:alias = case ";"* statement?;
|
||
|
switch = "switch" nl* expression? nl* "{" sep?
|
||
|
((case-line | default-line) (sep (case-line | default-line | statement))*)?
|
||
|
sep? "}";
|
||
|
|
||
|
send = "send" nl* primary-expression nl* primary-expression;
|
||
|
receive = "receive" nl* primary-expression;
|
||
|
receive-definition = symbol nl* receive;
|
||
|
communication:alias = send | receive | receive-definition;
|
||
|
select-case = "case" nl* communication nl* ":";
|
||
|
select-case-line:alias = select-case ";"* statement?;
|
||
|
select = "select" nl* "{" sep?
|
||
|
((select-case-line | default-line)
|
||
|
(sep (select-case-line | default-line | statement))*)?
|
||
|
sep? "}";
|
||
|
|
||
|
go = "go" nl* application;
|
||
|
defer = "defer" nl* application;
|
||
|
|
||
|
break = "break";
|
||
|
continue = "continue";
|
||
|
loop-control:alias = break | continue;
|
||
|
range-over = symbol nl* "in" nl* (expression | range) | range;
|
||
|
loop-expression:alias = expression | range-over;
|
||
|
loop = "for" ((nl* loop-expression)? nl* block | nl* block);
|
||
|
|
||
|
assignment = (symbol | indexer) nl* "=" nl* expression;
|
||
|
|
||
|
value-capture-fact:alias = symbol (nl* "=")? nl* expression;
|
||
|
value-capture = value-capture-fact;
|
||
|
mutable-capture = "~" nl* value-capture-fact;
|
||
|
value-definition = "let" nl* (value-capture | mutable-capture);
|
||
|
mixed-capture-list:alias = (value-capture | mutable-capture) (list-sep (value-capture | mutable-capture))*;
|
||
|
value-capture-list:alias = value-capture (list-sep value-capture)*;
|
||
|
value-definition-group = "let" nl* "(" list-sep? mixed-capture-list? list-sep? ")";
|
||
|
mutable-definition-group = "let" nl* "~" nl* "(" list-sep? value-capture-list? list-sep? ")";
|
||
|
|
||
|
function-definition-fact:alias = symbol nl* function-fact;
|
||
|
function-capture = function-definition-fact;
|
||
|
effect-capture = "~" nl* function-definition-fact;
|
||
|
function-definition = "fn" nl* (function-capture | effect-capture);
|
||
|
function-capture-list:alias = function-capture (list-sep function-capture)*;
|
||
|
mixed-function-capture-list:alias = (function-capture | effect-capture)
|
||
|
(list-sep (function-capture | effect-capture))*;
|
||
|
function-definition-group = "fn" nl* "(" list-sep?
|
||
|
mixed-function-capture-list?
|
||
|
list-sep? ")";
|
||
|
effect-definition-group = "fn" nl* "~" nl* "(" list-sep?
|
||
|
function-capture-list?
|
||
|
list-sep? ")";
|
||
|
|
||
|
definition:alias = value-definition
|
||
|
| value-definition-group
|
||
|
| mutable-definition-group
|
||
|
| function-definition
|
||
|
| function-definition-group
|
||
|
| effect-definition-group;
|
||
|
|
||
|
// TODO:
|
||
|
// - use effect
|
||
|
|
||
|
use-inline = ".";
|
||
|
use-fact = string
|
||
|
| (symbol | use-inline) (nl* "=")? nl* string;
|
||
|
use-fact-list:alias = use-fact (list-sep use-fact)*;
|
||
|
use-statement:alias = "use" nl* use-fact;
|
||
|
use-statement-group:alias = "use" nl* "(" list-sep?
|
||
|
use-fact-list?
|
||
|
list-sep? ")";
|
||
|
use = use-statement | use-statement-group;
|
||
|
|
||
|
export = "export" nl* definition;
|
||
|
|
||
|
simple-statement:alias = send
|
||
|
| go
|
||
|
| defer
|
||
|
| assignment
|
||
|
| simple-statement-group;
|
||
|
simple-statement-group:alias = "(" nl* simple-statement nl* ")";
|
||
|
statement:alias = simple-statement
|
||
|
| return
|
||
|
| if
|
||
|
| switch
|
||
|
| select
|
||
|
| loop
|
||
|
| loop-control
|
||
|
| definition
|
||
|
| use
|
||
|
| export
|
||
|
| application // TODO: sendSomething() and sendSomething
|
||
|
| chaining
|
||
|
| statement-group;
|
||
|
statement-group:alias = "(" nl* statement nl* ")";
|
||
|
|
||
|
sep:alias = (";" | nl)+;
|
||
|
statement-list:alias = statement (sep statement)*;
|
||
|
|
||
|
shebang-command = [^\n]*;
|
||
|
shebang = "#!" shebang-command "\n";
|
||
|
mml:root = shebang? sep? statement-list? sep?;
|