summaryrefslogtreecommitdiff
path: root/grammar.bnf
blob: 8715ad2b905aca2a0179db84044e2a0e88e43f1c (plain) (blame)
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
// Comments are introduced by # and terminated by newline

program ::= (statement ';'?)*;
statement ::= definition;
definition ::= 'def' def-spec '=' expression
             | 'def' '_' '=' expression;
def-spec ::= IDENTIFIER arg-spec*;
arg-spec ::= IDENTIFIER | '(' ')' | '_';
expression ::= binary-expression | unary-expression;
unary-expression ::= unop+ simple-expression;
binary-expression ::= call-expression (binop call-expression)*;
call-expression ::= simple-expression+;
binop ::= '*' | '/' | '+' | '-' | '?=' | '/=' | '>' | '>=' | '<' | '<=';
unop ::= '+' | '-' | '!';
simple-expression ::= '(' expression ')'
                    | 'true' | 'false'
                    | INTEGER
                    | IDENTIFIER
                    | STRING
                    | array
                    | tuple
                    | if-else-expression
                    | let-in-expression
                    | fn-expression
                    | do-expression;

array ::= '[' ']' | '[' expression (',' expression)* ','? ']';
// Note that tuples always have either zero or at least two elements
// A tuple with only one element is just '(' expression ')' -- a parenthese-wrapped expression
// Also '(' expression ',' ')' is illegal
tuple ::= '(' ')' | '(' expression ',' expression (',' expression)* ','? ')';

if-else-expression ::= 'if' expression 'then' expression 'else' expression;
let-in-expression ::= 'let' def-spec '=' expression ('and' def-spec '=' expression)* 'in' expression;
fn-expression ::= 'fn' arg-spec+ '->' expression
                | 'fn' arg-spec+ do-expression;
do-expression ::= 'do' expression (';' expression)* 'end';

repl-program ::= (repl-statement ';'?)* '\n'; // currently, hard-limited by the newline :sweat_smile:
repl-statement ::= statement | expression;