-
Notifications
You must be signed in to change notification settings - Fork 86
/
grammar.ebnf
117 lines (94 loc) · 3.84 KB
/
grammar.ebnf
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
(*
This is a basic grammar declaration for Amber written in EBNF.
This syntax does not include features that are not fully stable yet.
*)
root = { statement_global } ;
(* Statement *)
statement_local = expression | variable_init | variable_set
| loop | loop_array | if_statement | if_chain ;
statement_global = statement_local | function_def | main
| import_all | import_ids;
(* Block *)
singleline_block = ':', statement_local ;
multiline_block = '{', { statement_local }, '}' ;
block = singleline_block | multiline_block ;
(* Expression *)
expression = number | text | boolean | null | list | command
| binary_operation | unary_operation | parentheses | ternary
| range | range_inclusive | identifier | function_call ;
(* Terminals *)
ANY_CHAR = ? any character ? ;
LETTER = 'A'..'Z' | 'a'..'z' ;
DIGIT = '0'..'9' ;
TYPE = 'Text' | 'Num' | 'Bool' | 'Null';
UNARY_OP = '-' | 'not' ;
BINARY_OP = '+' | '-' | '*' | '/' | '%' | 'and' | 'or' | '==' | '!=' | '<' | '<=' | '>' | '>=' ;
SILENT_MOD = 'silent' ;
TRUST_MOD = 'trust' ;
VISIBILITY = 'pub' ;
(* Identifier *)
any_identifier = (LETTER | '_') , { LETTER | '_' | DIGIT } ;
internal_identifier = '__' , { LETTER | '_' | DIGIT } ;
identifier = any_identifier - internal_identifier ;
(* `Num` literal *)
integer = DIGIT , { DIGIT } ;
real = integer , '.' , integer ;
number = integer | real ;
(* `Text` literal *)
interpolation = '{' , expression , '}' ;
text = '"' , { ANY_CHAR | interpolation } , '"' ;
(* `Bool` literal *)
boolean = 'true' | 'false' ;
(* `Null` literal *)
null = 'null' ;
(* `List` literal *)
empty_list = '[' , TYPE , ']' ;
full_list = '[' , [ expression , { ',' , expression } ] , ']' ;
list = empty_list | full_list ;
(* Command expression *)
(* The ordering of command modifiers doesn't matter *)
command_modifier = SILENT_MOD, [ TRUST_MOD ] ;
command_modifier_block = command_modifier, multiline_block ;
command_base = '$', { ANY_CHAR | interpolation }, '$' ;
command = [ SILENT_MOD ], command_base, [ failure_handler ] ;
command_trust = [ SILENT_MOD ], TRUST_MOD, command_base ;
(* Operations *)
binary_operation = expression , BINARY_OP , expression ;
unary_operation = UNARY_OP , expression ;
(* Parentheses *)
parentheses = '(', expression, ')' ;
(* Failure handler *)
failure_propagation = '?';
failure_block = 'failed', block ;
failure_handler = failure_propagation | failure_block ;
(* Variable *)
variable_index = '[', expression, ']' ;
variable_init = 'let', identifier, '=', expression ;
variable_get = identifier, variable_index? ;
variable_set = identifier, variable_index?, '=', expression ;
(* Function *)
function_call = identifier, '(', [ expression, { ',', expression } ], ')' ;
function_call_failed = [ SILENT_MOD ], function_call, failure_handler ;
function_call_trust = [ SILENT_MOD ], TRUST_MOD, function_call ;
function_def = [ VISIBILITY ], 'fun', identifier, '(', [ identifier, { ',', identifier } ], ')', block ;
function_def_typed = [ VISIBILITY ], 'fun', identifier, '(',
[ identifier, ':', TYPE, { ',', identifier, ':', TYPE } ], ')', ':', TYPE, block ;
(* Loop *)
loop = 'loop', block ;
loop_array = 'loop', identifier, 'in', expression, block ;
loop_array_iterator = 'loop', identifier, ',', identifier, 'in', expression, block ;
(* Ranges *)
range = expression, '..', expression ;
range_inclusive = expression, '..=', expression ;
(* Conditional *)
if_statement = 'if', expression, block, [ 'else', block ] ;
if_chain = 'if', '{', { expression, block }, [ 'else', block ], '}' ;
ternary = expression, 'then', expression, 'else', expression ;
(* Main *)
main = 'main', [ '(', identifier, ')' ], block ;
(* Imports *)
import_path = '"', { ANY_CHAR }, '"' ;
import_all = [ VISIBILITY ], 'import', '*', 'from', import_path ;
import_ids = [ VISIBILITY ], 'import', '{', { identifier, [ 'as', identifier ] }, '}', 'from', import_path ;
(* Comment *)
comment = '//', { ANY_CHAR }, '\n'