-
Notifications
You must be signed in to change notification settings - Fork 0
/
deca.scc
418 lines (336 loc) · 14.1 KB
/
deca.scc
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
Package org.deca.compiler.parser;
Helpers
unicode_input_character = [0..0xffff];
letter = ['A'..'Z'] | ['a'..'z'] | [0x7F .. 0xFF];
digit = ['0'..'9'];
all = [0 .. 0xFFFF];
cr = 13;
lf = 10;
tab = 9;
eol = cr | lf | cr lf;
blank = eol | tab | ' ';
input_character = [unicode_input_character - [lf + cr]];
nondigit = '_' | '?' | '!' | letter;
not_cr_lf = [all - [cr + lf]];
not_star = [all - '*'];
not_star_slash = [not_star - '/'];
non_zero_digit = ['1'..'9'];
hex_digit = ['0'..'9'] | ['a'..'f'] | ['A'..'F'];
octal_digit = ['0'..'7'];
zero_to_three = ['0'..'3'];
decimal_numeral = '0' | non_zero_digit digit*;
hex_numeral = '0x' hex_digit+;
octal_numeral = '0' octal_digit+;
single_character = [input_character - ['"' + '\']];
octal_escape = '\' (octal_digit octal_digit? | zero_to_three octal_digit octal_digit);
escape_sequence = '\b' | '\t' | '\n' | '\f' | '\r' | '\"' | '\' ''' | '\\' | octal_escape;
string_character = single_character | escape_sequence;
at_operator = '@';
caret = '^';
Tokens
slot_mutability = 'val' | 'var' | 'constant';
boolean_constant = 'true' | 'false';
asterisk = '*';
slash = '/';
plus = '+';
minus = '-';
exponentiation_operator = '**';
and_operator = 'and';
or_operator = 'or';
xor_operator = 'xor';
minus_operator = '-';
caret = '^';
at_operator = '@';
not_operator = 'not';
method = 'method';
override = 'override';
comma = ',';
assignment_operator = ':=';
lparen = '(';
rparen = ')';
lbracket = '{';
rbracket = '}';
lsbracket = '[';
rsbracket = ']';
dot = '.';
colon = ':';
double_colon = '::';
bang_colon = '!:';
end = 'end';
module = 'module';
unsafe = 'unsafe';
labracket = '<';
rabracket = '>';
import = 'import';
extends = 'extends';
variant = 'variant';
exception = 'exception';
equals = '=';
different = '<>';
greatereq = '>=';
lessereq = '<=';
function = 'function';
let = 'let';
while = 'while';
do = 'do';
for = 'for';
case = 'case';
if = 'if';
then = 'then';
except = 'except';
finally = 'finally';
try = 'try';
throw = 'throw';
else = 'else';
type = 'type';
final = 'final';
implicit = 'implicit';
underscore = '_';
firstclass_function_arrow = '->';
function_pointer_arrow = '@->';
lambda_slash = '\';
sizeof = 'sizeof';
match = 'match';
cast = 'cast';
interface = 'interface';
abstract = 'abstract';
regional_effect_name = '!read' | '!write' | '!destroy' | '!call';
exceptional_effect_name = '!throw';
expression_end = ';';
blank = eol | tab | ' ';
tabspace = [tab + ' '];
space = [cr + [lf + [tab + ' ']]];
comment = '/*' not_star* '*'+ (not_star_slash not_star* '*'+)* '/';
unqualified_identifier = nondigit (digit | nondigit)* | 'exception';
integer_constant = decimal_numeral | hex_numeral | octal_numeral;
string_constant = '"' string_character* '"';
Ignored Tokens
blank,
comment;
Productions
module_definition =
unsafe? module [name]:unqualified_identifier [imports]:import_declaration* [definitions]:definition* end;
qualified_identifier =
{simple} unqualified_identifier |
{imported} qualified_identifier double_colon unqualified_identifier;
identifier_list = {one} unqualified_identifier | {many} identifier_list comma unqualified_identifier;
import_declaration =
import [name]:qualified_identifier;
effect_set = labracket effect_form_list rabracket;
positive_effect = plus effect_set;
negative_effect = minus_operator effect_set;
effect_signature =
{plus} positive_effect |
{minus} negative_effect |
{both} positive_effect negative_effect;
effect_region = lparen unqualified_identifier rparen;
effect_form =
{regional} regional_effect_name effect_region |
{exceptional} exceptional_effect_name type_form;
effect_form_list =
{one} effect_form |
{many} effect_form_list comma effect_form;
effect_annotation = bang_colon effect_signature;
variant_case_parameters = lparen tuple_component_list rparen;
variant_case =
{simple} unqualified_identifier variant_case_parameters? |
{complex} unqualified_identifier lparen [parameters]:argument_list rparen lbracket [members]:member_declaration+ rbracket;
interface_component_form =
{named} unqualified_identifier colon firstclass_function_form |
{unnamed} firstclass_function_form;
pointer_type_form =
{simple} at_operator lower_type_form |
{complex} at_operator lparen slot_mutability type_form rparen;
type_form =
{function} function_type_form |
{variant} final? variant extension_clause? lbracket variant_case+ rbracket |
{pointer} pointer_type_form |
{interface} interface labracket [argument]:unqualified_identifier rabracket lbracket tuple_component+ rbracket |
{exception} exception variant_case_parameters [extension]:extension_clause? |
{others} lower_type_form;
arguments_form = lparen type_form_list? rparen;
function_type_form =
{pointer} function_pointer_form |
{firstclass} firstclass_function_form;
firstclass_function_form =
[formals]:arguments_form [implicits]:arguments_form? firstclass_function_arrow [effect]:effect_annotation? [result]:type_form;
function_pointer_form =
[formals]:arguments_form [implicits]:arguments_form? function_pointer_arrow [effect]:effect_annotation? [result]:type_form;
tuple_component =
{type} slot_mutability type_form |
{binding} slot_mutability [name]:unqualified_identifier type_annotation;
tuple_component_list =
{one} tuple_component |
{many} tuple_component comma tuple_component_list;
type_parameterization = labracket [arguments]:type_form_list rabracket;
lower_type_form =
{tuple} lsbracket tuple_component_list rsbracket |
{array} basic_type_form lsbracket slot_mutability? integer_constant? rsbracket |
{others} basic_type_form;
basic_type_form =
{named} [typename]:qualified_identifier type_parameterization? |
{wildcard} underscore;
definition =
{globaldef} implicit_annotation? slot_declaration assignment_operator expression |
{extglobaldef} import implicit_annotation? slot_mutability unqualified_identifier type_annotation |
{typedef} type unqualified_identifier [parameters]:type_form_arguments? equals type_form |
{moduledef} module_definition |
{fundef} function_definition;
type_form_arguments =
labracket [arguments]:identifier_list rabracket;
type_form_list =
{one} type_form |
{many} type_form_list comma type_form;
type_annotation =
colon [type]:type_form;
member_declaration =
member_assignment expression_end;
extension_clause =
extends lower_type_form;
class_extension_clause =
extends lower_type_form function_arguments?;
argument =
[name]:unqualified_identifier [type]:type_annotation?;
argument_list =
{one} argument |
{many} argument comma argument_list;
implicit_annotation = final? implicit;
implicit_arguments = lparen [implicits]:argument_list rparen;
function_arguments = lparen [arguments]:argument_list? rparen implicit_arguments?;
function_definition =
{method} implicit_annotation? method [name]:unqualified_identifier type_form_arguments? function_arguments [type]:type_annotation [effect]:effect_annotation? [body]:block_expression |
{override} override [name]:qualified_identifier function_arguments [body]:block_expression |
{function} implicit_annotation? function [name]:unqualified_identifier type_form_arguments? function_arguments [type]:type_annotation? [effect]:effect_annotation? [body]:block_expression |
{external} import implicit_annotation? function [name]:unqualified_identifier function_arguments [type]:type_annotation [effect]:effect_annotation;
expression =
{assignmentexp} exp1 assignment_operator expression |
{letexp} let implicit_annotation? slot_declaration assignment_operator expression |
{matchexp} match_expression |
{tryexp} try_expression |
{finalexp} finally [finalizer]:expression |
{forexp} for lparen [initializer]:member_assignment [first_separator]:comma [test]:expression [second_separator]:comma [step]:expression rparen [loop]:expression |
{whilexp} while [condition]:expression do [body]:expression |
{throwexp} throw expression |
{ifwithoutelseexp} if [condition]:expression then [thenbody]:expression |
{ifwithelseexp} if [condition]:expression then [thenbody]:expression_with_else else_clause |
{blockexp} block_expression |
{others} exp5;
expression_with_else =
{assignmentexp} exp1 assignment_operator expression_with_else |
{letexp} let implicit_annotation? slot_declaration assignment_operator expression_with_else |
{matchexp} match_expression |
{tryexp} try_expression_with_else |
{finalexp} finally [finalizer]:expression_with_else |
{forexp} for lparen [initializer]:member_assignment [first_separator]:comma [test]:expression [second_separator]:comma [step]:expression rparen [loop]:expression_with_else |
{whilexp} while [condition]:expression do [body]:expression_with_else |
{throwexp} throw expression_with_else |
{ifwithelseexp} if [condition]:expression then [thenbody]:expression_with_else else [elsebody]:expression_with_else |
{blockexp} block_expression |
{others} exp5;
literal_expression =
{integer} integer_constant |
{boolean} boolean_constant |
{string} string_constant;
member_selector = {name} unqualified_identifier | {index} lsbracket integer_constant rsbracket;
interface_component =
{named} unqualified_identifier assignment_operator lambda_expression |
{unnamed} lambda_expression;
lambda_arguments =
{one} unqualified_identifier type_annotation? |
{many} function_arguments;
lambda_expression = lambda_slash lambda_arguments? firstclass_function_arrow block_expression;
//Increasing precedence levels.
exp1 =
{at} at_operator [variable]:qualified_identifier |
{sizeof} sizeof lparen type_form rparen |
{literal} literal_expression |
{tuple} lsbracket expression_list rsbracket |
{record} lsbracket member_assignment_list rsbracket |
{lambda} lambda_expression |
{interface} interface lbracket interface_component+ rbracket |
{call} function_call_expression |
{cast} cast labracket type_form rabracket lparen expression rparen |
{parenthetical} parenthetical_expression |
{identifier} qualified_identifier |
{field} exp1 dot member_selector |
{dereference} exp1 caret;
exp2 =
{exponentiation} [exp1]:exp1 exponentiation_operator [exp2]:exp2 |
{minus} minus_operator exp2 |
{not} not_operator exp2 |
{others} exp1;
exp3 =
{and} [exp1]:exp3 and_operator [exp2]:exp2 |
{or} [exp1]:exp3 or_operator [exp2]:exp2 |
{xor} [exp1]:exp3 xor_operator [exp2]:exp2 |
{multiply} [exp1]:exp3 asterisk [exp2]:exp2 |
{division} [exp1]:exp3 slash [exp2]:exp2 |
{others} exp2;
exp4 =
{plus} [exp1]:exp4 plus [exp2]:exp3 |
{minus} [exp1]:exp4 minus [exp2]:exp3 |
{others} exp3;
exp5 =
{greater} [exp1]:exp4 rabracket [exp2]:exp4 |
{greatereq} [exp1]:exp4 greatereq [exp2]:exp4 |
{less} [exp1]:exp4 labracket [exp2]:exp4 |
{lessereq} [exp1]:exp4 lessereq [exp2]:exp4 |
{equals} [exp1]:exp4 equals [exp2]:exp4 |
{different} [exp1]:exp4 different [exp2]:exp4 |
{others} exp4;
actual_implicit =
{explicit} expression |
{implicit} underscore;
actual_implicit_list =
{one} actual_implicit |
{many} actual_implicit comma actual_implicit_list;
actual_implicit_parameters = lparen actual_implicit_list rparen;
actual_parameters = lparen [arguments]:expression_list? rparen actual_implicit_parameters?;
function_call_expression =
{named} [function]:qualified_identifier actual_parameters |
{expr} [function]:parenthetical_expression actual_parameters |
{interface} [interface]:exp1 dot [method]:member_selector actual_parameters;
except_case_clause =
case [name]:unqualified_identifier type_annotation firstclass_function_arrow [body]:expression;
except_case_clause_with_else =
case [name]:unqualified_identifier type_annotation firstclass_function_arrow [body]:expression_with_else;
try_expression =
{one} try expression except except_case_clause |
{many} try expression except lbracket except_case_clause+ rbracket;
try_expression_with_else =
{one} try expression except except_case_clause_with_else |
{many} try expression except lbracket except_case_clause+ rbracket;
parenthetical_expression =
lparen expression rparen;
expression_list =
{one} expression |
{many} expression_list comma expression;
else_clause =
else [else_body]:expression;
slot_declaration = slot_mutability unqualified_identifier type_annotation?;
member_assignment =
slot_declaration assignment_operator expression;
member_assignment_list =
{one} member_assignment |
{many} member_assignment comma member_assignment_list;
pattern_list =
{one} match_pattern |
{many} pattern_list comma match_pattern;
pattern_variable = {some} unqualified_identifier | {none} underscore;
variant_pattern_arguments = lparen pattern_list rparen;
match_pattern =
//literal = value
{literal} literal_expression |
//bind variable:= value, unify types rather than values
{variable} slot_mutability [name]:pattern_variable type_annotation |
//data constructor = value, unify by testing value.tag and pushing new constraints on stack based on pattern_list
{variant} [name]:qualified_identifier variant_pattern_arguments? |
//tuple = value, unify by pushing new component-wise constraints
{tuple} lsbracket pattern_list rsbracket;
match_case_clause = case [pattern]:match_pattern firstclass_function_arrow [body]:expression;
match_expression =
match lparen expression rparen lbracket match_case_clause+ rbracket;
block_step = expression expression_end;
block_expression =
{one} lbracket expression rbracket |
{many} lbracket block_step+ rbracket;