about summary refs log tree commit diff
path: root/grammar.ebnf
blob: 7e59e74dd2e49ab22cf36fffdfce9f36ef43a735 (plain)
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
(* Grammar definition in EBNF format. *)

Program = {Statement} EOF;

(* Statement *)

Statement = ExpressionStatement | ReturnStatement | BreakStatement | ContinueExpression | PrintStatement;

ExpressionStatement = Expression ";";
ReturnStatement = "return" Expression ";";
BreakStatement = "break" [Expression] ";";
ContinueStatement = "continue" ";";
(* NOTE: Hard-coded PrintStatement until Rabbithole has an standard library *)
PrintStatement = "print" Expression ";";

(* Expression *)

Expression = AssignmentExpression;

(* Expressions affected by precedence*)

(* NOTE: Only allow IDENTIFIERs and their fields as the LValue for now. *)
AssignmentExpression = IDENTIFIER {"." IDENTIFIER} ("=" | ":=") AssignmentExpression | EqualityExpression;
EqualityExpression = ComparisonExpression { ("==" | "!=") ComparisonExpression };
ComparisonExpression = TermExpression { ("<" | "<=" | ">" | ">=") TermExpression };
TermExpression = FactorExpression { ("+" | "-") FactorExpression };
FactorExpression = UnaryExpression { ("*" | "/") UnaryExpression };
UnaryExpression = ( "-" | "!" ) UnaryExpression | PostfixExpression ;
PostfixExpression = UnitExpression { ( "(" [FnCallArguments] ")" | "[" Expression "]" | "." IDENTIFIER ) };
                
(* Unaffected Expressions *)

UnitExpression = FLOAT | INT | STR | TRUE | FALSE | GroupExpression | BlockExpression | FnExpression | TypeExpression | FormExpression | IfExpression;

GroupExpression = "(" Expression ")";
BlockExpression = Block;
FnExpression = "fn" FnHeader Block;
TypeExpression = "type" TypeBlock;
(* NOTE: Will associated functions clash with fields? *)
FormExpression = "form" TypeBlock;
IfExpression = "if" Expression Block { "elif" Expression Block } [ "else" Block ];
LoopExpression = "loop" ["if" Expression] Block;

(* Parts *)

FnHeader = (FnParameters) ["->" Type];
FnParameters = ("self" | FnParameter) { "," FnParameter};

FnCallArguments = Expression { "," Expression };

(* Utils *)

Block = "{" { Statement } [Expression] "}";
TypeBlock = "{" [ TypedIdentifier ] { "," TypedIdentifier } "}";

TypedIdentifier = IDENTIFIER [":" Type];
(* NOTE: Type doesn't include anything other than simple named types for now. *)
Type = IDENTIFIER;