yukigo-haskell-parser 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/.mocharc.json +3 -3
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +10 -10
  4. package/dist/index.d.ts +13 -2
  5. package/dist/index.js +112 -32
  6. package/dist/index.js.map +1 -1
  7. package/dist/parser/grammar.js +220 -231
  8. package/dist/parser/grammar.js.map +1 -1
  9. package/dist/parser/lexer.d.ts +70 -15
  10. package/dist/parser/lexer.js +259 -50
  11. package/dist/parser/lexer.js.map +1 -1
  12. package/dist/prelude.d.ts +1 -1
  13. package/dist/prelude.js +280 -204
  14. package/dist/prelude.js.map +1 -1
  15. package/dist/typechecker/DeclarationCollector.d.ts +6 -1
  16. package/dist/typechecker/DeclarationCollector.js +39 -0
  17. package/dist/typechecker/DeclarationCollector.js.map +1 -1
  18. package/dist/typechecker/TypeBuilder.d.ts +1 -1
  19. package/dist/typechecker/TypeBuilder.js +6 -2
  20. package/dist/typechecker/TypeBuilder.js.map +1 -1
  21. package/dist/typechecker/checker.d.ts +15 -4
  22. package/dist/typechecker/checker.js +108 -25
  23. package/dist/typechecker/checker.js.map +1 -1
  24. package/dist/typechecker/core.d.ts +4 -0
  25. package/dist/typechecker/core.js +45 -19
  26. package/dist/typechecker/core.js.map +1 -1
  27. package/dist/typechecker/inference.d.ts +5 -1
  28. package/dist/typechecker/inference.js +95 -21
  29. package/dist/typechecker/inference.js.map +1 -1
  30. package/dist/utils/helpers.d.ts +1 -1
  31. package/dist/utils/helpers.js +1 -1
  32. package/dist/utils/helpers.js.map +1 -1
  33. package/dist/utils/types.d.ts +1 -1
  34. package/dist/utils/types.js +7 -0
  35. package/dist/utils/types.js.map +1 -1
  36. package/package.json +3 -3
  37. package/src/index.ts +192 -55
  38. package/src/parser/grammar.ne +519 -463
  39. package/src/parser/grammar.ts +230 -239
  40. package/src/parser/lexer.ts +353 -77
  41. package/src/prelude.ts +282 -206
  42. package/src/typechecker/DeclarationCollector.ts +157 -104
  43. package/src/typechecker/TypeBuilder.ts +150 -148
  44. package/src/typechecker/checker.ts +501 -395
  45. package/src/typechecker/core.ts +192 -162
  46. package/src/typechecker/inference.ts +1421 -1327
  47. package/src/utils/helpers.ts +29 -29
  48. package/src/utils/types.ts +63 -56
  49. package/tests/hspec.spec.ts +92 -0
  50. package/tests/lexer.spec.ts +175 -0
  51. package/tests/parser.spec.ts +829 -823
  52. package/tests/prelude.spec.ts +17 -22
  53. package/tests/typechecker.spec.ts +327 -310
  54. package/tsconfig.json +26 -17
  55. package/tsconfig.tsbuildinfo +1 -0
  56. package/dist/parser/layoutPreprocessor.d.ts +0 -1
  57. package/dist/parser/layoutPreprocessor.js +0 -22
  58. package/dist/parser/layoutPreprocessor.js.map +0 -1
  59. package/dist/parser/preprocessor.d.ts +0 -28
  60. package/dist/parser/preprocessor.js +0 -453
  61. package/dist/parser/preprocessor.js.map +0 -1
  62. package/src/parser/layoutPreprocessor.ts +0 -21
  63. package/src/parser/preprocessor.ne +0 -375
  64. package/src/parser/preprocessor.ts +0 -502
  65. package/tests/preprocessor.spec.ts +0 -69
@@ -1,463 +1,519 @@
1
- @{%
2
- import { HSLexer } from "./lexer.js"
3
- import {
4
- TypeCast,
5
- Application,
6
- ConsExpression,
7
- StringOperation,
8
- LogicalBinaryOperation,
9
- ComparisonOperation,
10
- ArithmeticBinaryOperation,
11
- Print,
12
- ListBinaryOperation,
13
- ListUnaryOperation,
14
- ArithmeticUnaryOperation,
15
- LogicalUnaryOperation,
16
- SymbolPrimitive,
17
- ListPrimitive,
18
- Switch,
19
- CompositionExpression,
20
- Lambda,
21
- TupleExpression,
22
- DataExpression,
23
- Function,
24
- FieldExpression,
25
- If,
26
- Record,
27
- Constructor,
28
- Field,
29
- ListComprehension,
30
- Generator,
31
- RangeExpression,
32
- TypeSignature,
33
- Return,
34
- GuardedBody,
35
- Equation,
36
- Raise,
37
- UnguardedBody,
38
- Sequence,
39
- Otherwise,
40
- WildcardPattern,
41
- ConsPattern,
42
- VariablePattern,
43
- LiteralPattern,
44
- AsPattern,
45
- ConstructorPattern,
46
- ListPattern,
47
- TuplePattern,
48
- TypeAlias,
49
- ParameterizedType,
50
- Constraint,
51
- TypeApplication,
52
- LetInExpression,
53
- SimpleType,
54
- ListType,
55
- TupleType,
56
- NumberPrimitive,
57
- CharPrimitive,
58
- StringPrimitive,
59
- BooleanPrimitive,
60
- SourceLocation
61
- } from "yukigo-ast";
62
-
63
- const filter = d => {
64
- return d.filter((token) => token !== null);
65
- };
66
-
67
- const loc = (token) => new SourceLocation(token.line, token.col);
68
-
69
- %}
70
- @preprocessor typescript
71
- @lexer HSLexer
72
-
73
- program -> declaration:+ {% (d) => d[0].filter(x => x !== null) %}
74
-
75
- declaration -> (function_declaration
76
- | function_signature
77
- | type_declaration
78
- | data_declaration
79
- | comment
80
- | empty_line
81
- | apply_operator) {% (d) => d[0][0] %}
82
-
83
- comment -> %comment {% d => null %}
84
-
85
- empty_line -> _ %NL {% d => null %}
86
-
87
- expression ->
88
- (type_cast
89
- | letin_expression
90
- | if_expression
91
- | case_expression) {% (d) => d[0][0] %}
92
-
93
- type_cast -> apply_operator _ "::" _ type {% (d) => new TypeCast(d[0], d[4]) %}
94
- | apply_operator {% id %}
95
-
96
- # Operation rules
97
-
98
- # priority 0
99
- apply_operator ->
100
- bind_expression _ "$" _ apply_operator {% (d) => new Application(d[0], d[4]) %}
101
- | bind_expression {% id %}
102
-
103
- # priority 1
104
- bind_expression ->
105
- logical_expression _ ">>=" _ bind_expression {% (d) => new Application(new Application(new SymbolPrimitive("(>>=)"), d[0]), d[4]) %}
106
- | logical_expression _ ">>" _ bind_expression {% (d) => new Application(new Application(new SymbolPrimitive("(>>)"), d[0]), d[4]) %}
107
- | logical_expression {% id %}
108
-
109
- # priority 3
110
- logical_expression ->
111
- comparison _ "&&" _ logical_expression {% (d) => new LogicalBinaryOperation("And", d[0], d[4]) %}
112
- | comparison _ "||" _ logical_expression {% (d) => new LogicalBinaryOperation("Or", d[0], d[4]) %}
113
- | comparison {% id %}
114
-
115
- # priority 4
116
- comparison ->
117
- cons_expression _ comparison_operator _ cons_expression {% (d) => new ComparisonOperation(d[2], d[0], d[4]) %}
118
- | cons_expression {% id %}
119
-
120
- # priority 5
121
- cons_expression ->
122
- concatenation _ ":" _ cons_expression {% (d) => new ConsExpression(d[0], d[4]) %}
123
- | concatenation {% id %}
124
-
125
- concatenation ->
126
- addition _ "++" _ concatenation {% (d) => d[0] instanceof StringPrimitive || d[4] instanceof StringPrimitive ? new StringOperation("Concat", d[0], d[4]) : new ListBinaryOperation("Concat", d[0], d[4]) %}
127
- | addition {% id %}
128
-
129
- # priority 6
130
- addition ->
131
- addition _ "+" _ multiplication {% (d) => new ArithmeticBinaryOperation("Plus", d[0], d[4]) %}
132
- | addition _ "-" _ multiplication {% (d) => new ArithmeticBinaryOperation("Minus", d[0], d[4]) %}
133
- | multiplication {% id %}
134
-
135
- # priority 7
136
- multiplication ->
137
- multiplication _ "*" _ power {% (d) => new ArithmeticBinaryOperation("Multiply", d[0], d[4]) %}
138
- | multiplication _ "/" _ power {% (d) => new ArithmeticBinaryOperation("Divide", d[0], d[4]) %}
139
- | power {% id %}
140
-
141
- # priority 8
142
- power ->
143
- unary_negation _ "**" _ power {% (d) => new ArithmeticBinaryOperation("Power", d[0], d[4]) %}
144
- | unary_negation _ "^" _ power {% (d) => new ArithmeticBinaryOperation("Power", d[0], d[4]) %}
145
- | unary_negation _ "^^" _ power {% (d) => new ArithmeticBinaryOperation("Power", d[0], d[4]) %}
146
- | unary_negation {% id %}
147
-
148
- unary_negation ->
149
- "-" _ unary_negation {% (d) => new ArithmeticUnaryOperation("Negation", d[2]) %}
150
- | index_access {% id %}
151
-
152
- # priority 9
153
- index_access ->
154
- index_access _ "!!" _ composition_expression {% (d) => new ListBinaryOperation("GetAt", d[0], d[4]) %}
155
- | composition_expression {% id %}
156
-
157
- composition_expression ->
158
- composition_expression _ "." _ infix_operator_expression {% (d) => new CompositionExpression(d[0], d[4]) %}
159
- | infix_operator_expression {% id %}
160
-
161
- infix_operator_expression ->
162
- infix_operator_expression _ "`" _ variable _ "`" _ application {% (d) => new Application(new Application(d[4], d[0]), d[8]) %}
163
- | application {% id %}
164
-
165
- application ->
166
- "error" __ primary {% d => new Raise(d[2]) %}
167
- | primary ((_ | (_ %NL __)) primary):* {% (d) => {
168
- if (d[1].length === 0) return d[0];
169
- return d[1].reduce((left, right) => new Application(left, right[1]), d[0]);
170
- } %}
171
-
172
- operator ->
173
- ("=="
174
- | "/="
175
- | "<"
176
- | ">"
177
- | "<="
178
- | "&&"
179
- | "||"
180
- | ">="
181
- | "++"
182
- | "+"
183
- | ","
184
- | "*"
185
- | "/"
186
- | ":") {% (d) => d[0][0].value %}
187
-
188
- left_section -> "(" _ expression _ operator _ ")" {% (d) => new Application(new SymbolPrimitive(d[4]), d[2]) %}
189
-
190
- right_section -> "(" _ operator _ expression _ ")" {% (d) => {
191
- const flipBody = new SymbolPrimitive("flip");
192
- const op = new SymbolPrimitive(d[2]);
193
- const expr = d[4];
194
- const flipAppliedToOp = new Application(flipBody, op);
195
- return new Application(flipAppliedToOp, expr);
196
- }
197
- %}
198
-
199
- operator_section -> "(" _ operator _ ")" {% (d) => new SymbolPrimitive(d[2]) %}
200
-
201
- primary ->
202
- primitive {% id %}
203
- | variable {% id %}
204
- | constr {% id %}
205
- | tuple_expression {% id %}
206
- | left_section {% id %}
207
- | right_section {% id %}
208
- | operator_section {% id %}
209
- | list_literal {% id %}
210
- | lambda_expression {% id %}
211
- | data_expression {% id %}
212
- | list_comprehension {% id %}
213
- | "(" _ expression _ ")" {% (d) => d[2] %}
214
- | "[" _ range_expression _ "]" {% (d) => d[2] %}
215
- # Expression rules
216
-
217
- # List comprehension rules
218
- list_comprehension ->
219
- "[" _ expression _ "|" _ comprehension_clause_list _ "]" {% (d) => {
220
- return new ListComprehension(d[2], d[6]);
221
- } %}
222
-
223
- comprehension_clause_list ->
224
- comprehension_clause (_ "," _ comprehension_clause):* {% (d) => {
225
- return [d[0], ...d[1].map((x) => x[3])];
226
- } %}
227
-
228
- comprehension_clause ->
229
- variable _ "<-" _ expression {% (d) => new Generator(d[0], d[4]) %}
230
- | expression {% id %}
231
-
232
- lambda_expression ->
233
- "(" _ "\\" _ parameter_list _ "->" _ expression _ ")" {% (d) => new Lambda(d[4], d[8]) %}
234
-
235
- tuple_expression -> "(" _ tuple_value (_ "," _ tuple_value):+ _ ")" {% (d) => new TupleExpression([d[2], ...d[3].map(x => x[3])]) %}
236
- tuple_value -> expression {% id %}
237
-
238
-
239
- data_expression -> constr _ %lbracket _ fields_expressions _ %rbracket {% (d) => new DataExpression(d[0], d[4]) %}
240
-
241
- fields_expressions -> field_exp (_ "," _ field_exp):* {% (d) => [d[0], ...d[1].map(x => x[3])] %}
242
-
243
- field_exp -> variable _ "=" _ expression {% (d) => new FieldExpression(d[0], d[4]) %}
244
-
245
- if_expression -> "if" __ expression __ "then" __ expression __ "else" __ expression {% (d) => new If(d[2], d[6], d[10]) %}
246
-
247
- letin_expression -> "let" (_ "{" _) bindings_list:? (_ "}" _) "in" _ expression {% (d) => new LetInExpression(new Sequence(d[2] ?? []), d[6]) %}
248
-
249
- case_expression -> "case" _ expression _ "of" (_ "{" _) case_arms (_ "}" _) {% (d) => new Switch(d[2], d[6]) %}
250
-
251
- case_arms -> case_arm ((_ ";" _) case_arm):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
252
-
253
- case_arm -> pattern _ "->" _ expression {% (d) => ({condition: d[0], body: d[4] }) %}
254
-
255
- # Data rules
256
-
257
- data_declaration -> "data" __ constr (__ type_variable):* _ "=" _ constructor_def (_ "|" _ constructor_def):* deriving_clause:? {%
258
- (d) => new Record(d[2], [d[7], ...d[8].map(x => x[3])], d[9])
259
- %}
260
-
261
- deriving_clause ->
262
- _ "deriving" _ deriving_spec {% (d) => d[3] %}
263
-
264
- deriving_spec ->
265
- "(" _ deriving_classes _ ")" {% (d) => d[2] %}
266
- | constr {% (d) => [d[0]] %}
267
-
268
- deriving_classes ->
269
- %typeClass (_ "," _ %typeClass):* {% (d) => [new SymbolPrimitive(d[0].value), ...d[1].map(x => new SymbolPrimitive(x[3].value))] %}
270
-
271
- constructor_def ->
272
- constr _ (%NL __):? %lbracket _ (%NL _):? field_list _ (%NL _):? %rbracket {% (d) => new Constructor(d[0], d[6]) %}
273
- | constr (__ simple_type):* {% (d) => new Constructor(d[0], d[1].map(x => new Field(undefined, x[1]))) %}
274
-
275
- field_list -> field (_ "," _ (%NL _):? field):* {% (d) => [d[0], ...d[1].map(x => x[4])]%}
276
-
277
- field -> variable _ %typeEquals _ type {% (d) => new Field(d[0], d[4]) %}
278
-
279
- # Function rules
280
-
281
- binding_name ->
282
- "(" _ %op _ ")" {% d => new SymbolPrimitive(`${d[2].value}`) %}
283
- | variable {% id %}
284
-
285
- function_signature -> binding_name (_ "," _ binding_name):* _ %typeEquals _ type {% (d) => new TypeSignature(d[0], d[5]) %}
286
-
287
- function_declaration ->
288
- variable equation {% (d) => new Function(d[0], [d[1]]) %}
289
- | "(" _ %op _ ")" equation {% (d) => new Function(new SymbolPrimitive(`${d[2].value}`), [d[5]]) %}
290
-
291
- return_expression -> expression {% d => new Return(d[0]) %}
292
-
293
- where_clause -> "where" _ "{" _ bindings_list _ "}" {% d => d[4] %}
294
-
295
- bindings_list -> function_declaration ((_ ";" _) function_declaration):* {% d => [d[0], ...d[1].map(x => x[1])] %}
296
-
297
- equation ->
298
- params (%NL __):? guarded_rhs (_ where_clause):? {% (d) => {
299
- const body = d[2];
300
- const finalBody = d[3]
301
- ? new LetInExpression(d[3], body)
302
- : body;
303
- return new Equation(d[0], finalBody);
304
- } %}
305
- | params %assign ((_ %NL __) | _) return_expression (_ where_clause):? {% d => new Equation(d[0], new UnguardedBody(new Sequence(d[4] ? [...d[4][1], d[3]] : [d[3]])), d[3]) %}
306
-
307
- params ->
308
- __ parameter_list _ {% d => d[1] %}
309
- | _ {% d => [] %}
310
-
311
- guarded_rhs ->
312
- guarded_branch ((_ %NL __) | _) guarded_rhs {% (d) => [d[0], ...d[2]] %}
313
- | guarded_branch {% (d) => [d[0]] %}
314
-
315
- guarded_branch ->
316
- "|" ((_ %NL __) | _) condition ((_ %NL __) | _) "=" ((_ %NL __) | _) expression {% (d) => new GuardedBody(d[2], d[6]) %}
317
-
318
- condition ->
319
- "otherwise" {% d => new Otherwise() %}
320
- | expression {% d => d[0] %}
321
-
322
- parameter_list -> pattern (__ pattern):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
323
-
324
- # Patterns
325
-
326
- pattern -> cons_pattern {% id %}
327
-
328
- cons_pattern ->
329
- "(" _ cons_pattern (_ ":" _ cons_pattern):+ _ ")" {%
330
- (d) => {
331
- const patterns = [d[2], ...d[3].map(item => item[3])];
332
- return patterns.reduceRight((tail, head, index, arr) => {
333
- if (index === arr.length - 1) return tail;
334
- return new ConsPattern(head, tail);
335
- });
336
- }
337
- %}
338
- | simple_pattern {% id %}
339
-
340
- simple_pattern ->
341
- (as_pattern
342
- | constructor_pattern
343
- | list_pattern
344
- | tuple_pattern
345
- #| record_pattern
346
- | literal_pattern
347
- | variable_pattern
348
- | wildcard_pattern
349
- | paren_pattern) {% (d) => d[0][0] %}
350
-
351
- wildcard_pattern -> %anonymousVariable {% (d) => new WildcardPattern() %}
352
-
353
- paren_pattern -> "(" _ pattern _ ")" {% (d) => d[2] %}
354
-
355
- variable_pattern -> variable {% (d) => new VariablePattern(d[0]) %}
356
-
357
- literal_pattern -> primitive {% (d) => new LiteralPattern(d[0]) %}
358
-
359
- as_pattern -> (variable_pattern | wildcard_pattern) "@" pattern {% (d) => new AsPattern(d[0][0], d[2]) %}
360
-
361
- constructor_pattern ->
362
- "(" _ constr (__ pattern):+ _ ")" {% (d) => new ConstructorPattern(d[2].value, d[3].map(x => x[1])) %}
363
- | constr {% (d) => new ConstructorPattern(d[0].value, []) %}
364
-
365
- # record_pattern ->
366
- # constr:? _ %lbracket _ field_pattern_list _ %rbracket {% (d) => ({
367
- # type: "RecordPattern",
368
- # constructor: d[0] ? d[0].value : null,
369
- # fields: d[4]
370
- # }) %}
371
-
372
- field_pattern_list -> field_pattern (_ "," _ field_pattern):* {% (d) => [d[0], ...d[1].map(x => x[3])] %}
373
-
374
- field_pattern -> variable _ "=" _ pattern {% (d) => ({ field: d[0].value, pattern: d[4] }) %}
375
-
376
- list_pattern -> "[" _ pattern_list:? _ "]" {% (d) => new ListPattern(d[2] || []) %}
377
-
378
- pattern_list -> pattern (_ "," _ pattern):* {% (d) => [d[0], ...d[1].map(x => x[3])] %}
379
-
380
- tuple_pattern -> "(" _ pattern (_ "," _ pattern):+ _ ")" {% (d) => new TuplePattern([d[2], ...d[3].map(x => x[3])]) %}
381
-
382
- # Type rules
383
-
384
- type_declaration -> "type" __ constr (__ variable_list):? _ "=" _ type {% (d) => new TypeAlias(d[2], d[3] ? d[3][1] : [], d[7]) %}
385
-
386
- variable_list -> variable (__ variable):* {% (d) => [d[0].value, ...d[1].map(x => x[1].value)] %}
387
-
388
- type -> function_type {% id %}
389
-
390
- constrained_type -> constraint_list _ %arrow _ type {% (d) => new ParameterizedType([], d[4], d[0]) %}
391
-
392
- context ->
393
- constraint {% (d) => [d[0]] %}
394
- | "(" _ constraint_list _ ")" {% (d) => d[2] %}
395
-
396
- constraint_list ->
397
- constraint (_ "," _ constraint):* {% (d) =>
398
- [d[0], ...d[1].map(x => x[3])]
399
- %}
400
-
401
- constraint -> %typeClass (_ application_type):+ {% (d) => new Constraint(d[0].value, d[1].map(x => x[1])) %}
402
-
403
- function_type ->
404
- (context _ %arrow _):? (application_type (_ | (_ %NL __)) %typeArrow (_ | (_ %NL __))):* application_type {% (d) => {
405
- const constraints = d[0] ? d[0][0] : [];
406
-
407
- if (d[1].length > 0)
408
- return new ParameterizedType(d[1].map(x => x[0]), d[2], constraints);
409
-
410
- if (constraints.length === 0)
411
- return d[2];
412
-
413
- return new ParameterizedType([], d[2], constraints);
414
- }
415
- %}
416
-
417
- application_type ->
418
- simple_type (_ simple_type):+ {% (d) => d[1].reduce((acc, arg) => new TypeApplication(acc, arg[1]), d[0]) %}
419
- | simple_type {% id %}
420
-
421
- simple_type ->
422
- (type_variable | type_constructor) {% (d) => new SimpleType(d[0][0].value, []) %}
423
- | "[" _ type _ "]" {% (d) => new ListType(d[2], []) %}
424
- | "(" _ type (_ "," _ type):+ _ ")" {% (d) => new TupleType([d[2], ...d[3].map(x => x[3])], []) %}
425
- | "(" _ type _ ")" {% (d) => d[2] %}
426
-
427
- type_variable -> variable {% ([v]) => ({ value: v.value }) %}
428
- type_constructor -> constr {% ([c]) => ({ value: c.value }) %}
429
-
430
- # Misc rules
431
-
432
- constr -> %constructor {% ([c]) => new SymbolPrimitive(c.value, loc(c)) %} # constr because js doesnt like rules called constructor
433
- variable -> %variable {% ([v]) => new SymbolPrimitive(v.value, loc(v)) %}
434
-
435
- list_literal ->
436
- "[" _ "]" {% (_) => new ListPrimitive([]) %}
437
- | "[" _ expression_list _ "]" {% ([_, __, list]) => new ListPrimitive(list) %}
438
-
439
- range_expression ->
440
- expression _ ".." {% (d) => new RangeExpression(d[0]) %} # [start ..]
441
- | expression _ ".." _ expression {% (d) => new RangeExpression(d[0], d[4]) %} # [start .. end]
442
- | expression _ "," _ expression _ ".." {% (d) => new RangeExpression(d[0], undefined, d[4]) %} # [start, second ..]
443
- | expression _ "," _ expression _ ".." _ expression {% (d) => new RangeExpression(d[0], d[6], d[4]) %} # [start, second .. end]
444
-
445
- expression_list -> expression (_ "," _ expression):* {% (d) => [d[0], ...d[1].map(x => x[3])] %}
446
-
447
- comparison_operator ->
448
- "==" {% (d) => "Equal" %}
449
- | "/=" {% (d) => "NotEqual" %}
450
- | "<" {% (d) => "LessThan" %}
451
- | ">" {% (d) => "GreaterThan" %}
452
- | "<=" {% (d) => "LessOrEqualThan" %}
453
- | ">=" {% (d) => "GreaterOrEqualThan" %}
454
-
455
- primitive ->
456
- %number {% ([n]) => new NumberPrimitive(Number(n.value), loc(n)) %}
457
- | %char {% ([c]) => new CharPrimitive(c.value, loc(c)) %}
458
- | %string {% ([s]) => new StringPrimitive(s.value.slice(1, -1), loc(s)) %}
459
- | %bool {% ([b]) => new BooleanPrimitive(b.value === 'True' ? true : false, loc(b)) %}
460
-
461
- _ -> %WS:*
462
-
463
- __ -> %WS:+
1
+ @{%
2
+ import { HaskellLayoutLexer } from "./lexer.js"
3
+ import {
4
+ TypeCast,
5
+ Application,
6
+ ConsExpression,
7
+ StringOperation,
8
+ LogicalBinaryOperation,
9
+ ComparisonOperation,
10
+ ArithmeticBinaryOperation,
11
+ Print,
12
+ ListBinaryOperation,
13
+ ListUnaryOperation,
14
+ ArithmeticUnaryOperation,
15
+ LogicalUnaryOperation,
16
+ Case,
17
+ SymbolPrimitive,
18
+ ListPrimitive,
19
+ Switch,
20
+ CompositionExpression,
21
+ Lambda,
22
+ TupleExpression,
23
+ DataExpression,
24
+ Function,
25
+ FieldExpression,
26
+ If,
27
+ Record,
28
+ Constructor,
29
+ Field,
30
+ ListComprehension,
31
+ Generator,
32
+ RangeExpression,
33
+ TypeSignature,
34
+ Return,
35
+ GuardedBody,
36
+ Equation,
37
+ Raise,
38
+ UnguardedBody,
39
+ Sequence,
40
+ Otherwise,
41
+ WildcardPattern,
42
+ ConsPattern,
43
+ VariablePattern,
44
+ LiteralPattern,
45
+ AsPattern,
46
+ ConstructorPattern,
47
+ ListPattern,
48
+ TuplePattern,
49
+ TypeAlias,
50
+ ParameterizedType,
51
+ Constraint,
52
+ TypeApplication,
53
+ LetInExpression,
54
+ SimpleType,
55
+ ListType,
56
+ TupleType,
57
+ TypeClass,
58
+ Instance,
59
+ NumberPrimitive,
60
+ CharPrimitive,
61
+ StringPrimitive,
62
+ BooleanPrimitive,
63
+ SourceLocation,
64
+ TestGroup,
65
+ Test,
66
+ Assert,
67
+ Equality,
68
+ Truth,
69
+ Failure
70
+ } from "yukigo-ast";
71
+
72
+ const filter = d => {
73
+ return d.filter((token) => token !== null);
74
+ };
75
+
76
+ const loc = (token) => new SourceLocation(token.line, token.col);
77
+ const HSLexer = new HaskellLayoutLexer();
78
+
79
+ %}
80
+ @preprocessor typescript
81
+ @lexer HSLexer
82
+
83
+ program -> declaration (";" declaration):* ";":? {% (d) => [d[0], ...d[1].map(x => x[1])].flat(Infinity) %}
84
+
85
+ declaration -> (function_declaration
86
+ | function_signature
87
+ | type_declaration
88
+ | data_declaration
89
+ | typeclass_declaration
90
+ | instance_declaration
91
+ | apply_operator
92
+ | test_declaration
93
+ | "let" function_declaration) {% (d) => d[0][0] === "let" ? d[0][1] : d[0][0] %}
94
+
95
+ expression ->
96
+ (type_cast
97
+ | letin_expression
98
+ | if_expression
99
+ | case_expression
100
+ | test_declaration) {% (d) => d[0][0] %}
101
+
102
+ # Test rules
103
+
104
+ test_declaration ->
105
+ "describe" expression "do" %lbracket test_body %rbracket {% (d) => new TestGroup(d[1], new Sequence(d[4])) %}
106
+ | "describe" expression "$" "do" %lbracket test_body %rbracket {% (d) => new TestGroup(d[1], new Sequence(d[5])) %}
107
+ | "it" expression "do" %lbracket test_body %rbracket {% (d) => new Test(d[1], new Sequence(d[4])) %}
108
+ | "it" expression "$" "do" %lbracket test_body %rbracket {% (d) => new Test(d[1], new Sequence(d[5])) %}
109
+ | "let" function_declaration {% (d) => d[1] %}
110
+ | assertion {% id %}
111
+
112
+ test_body ->
113
+ test_declaration (";" test_declaration):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
114
+
115
+ assertion ->
116
+ expression "shouldBe" expression {% (d) => new Assert(new BooleanPrimitive(false), new Equality(d[2], d[0])) %}
117
+ | expression "`" "shouldBe" "`" expression {% (d) => new Assert(new BooleanPrimitive(false), new Equality(d[4], d[0])) %}
118
+ | expression "shouldNotBe" expression {% (d) => new Assert(new BooleanPrimitive(true), new Equality(d[2], d[0])) %}
119
+ | expression "`" "shouldNotBe" "`" expression {% (d) => new Assert(new BooleanPrimitive(true), new Equality(d[4], d[0])) %}
120
+ | expression "shouldSatisfy" expression {% (d) => new Assert(new BooleanPrimitive(false), new Truth(new Application(d[2], d[0]))) %}
121
+ | expression "`" "shouldSatisfy" "`" expression {% (d) => new Assert(new BooleanPrimitive(false), new Truth(new Application(d[4], d[0]))) %}
122
+ | expression "shouldThrow" expression {% (d) => new Assert(new BooleanPrimitive(false), new Failure(d[0], d[2])) %}
123
+ | expression "`" "shouldThrow" "`" expression {% (d) => new Assert(new BooleanPrimitive(false), new Failure(d[0], d[4])) %}
124
+
125
+
126
+ type_cast -> apply_operator "::" type {% (d) => new TypeCast(d[0], d[2]) %}
127
+ | apply_operator {% id %}
128
+
129
+ # Operation rules
130
+
131
+ # priority 0
132
+ apply_operator ->
133
+ bind_expression ("$" | "$!") apply_operator {% (d) => new Application(d[0], d[2]) %}
134
+ | bind_expression {% id %}
135
+
136
+ # priority 1
137
+ bind_expression ->
138
+ logical_expression ">>=" bind_expression {% (d) => new Application(new Application(new SymbolPrimitive("(>>=)"), d[0]), d[2]) %}
139
+ | logical_expression ">>" bind_expression {% (d) => new Application(new Application(new SymbolPrimitive("(>>)"), d[0]), d[2]) %}
140
+ | logical_expression {% id %}
141
+
142
+ # priority 3
143
+ logical_expression ->
144
+ comparison "&&" logical_expression {% (d) => new LogicalBinaryOperation("And", d[0], d[2]) %}
145
+ | comparison "||" logical_expression {% (d) => new LogicalBinaryOperation("Or", d[0], d[2]) %}
146
+ | comparison {% id %}
147
+
148
+ # priority 4
149
+ comparison ->
150
+ cons_expression comparison_operator cons_expression {% (d) => new ComparisonOperation(d[1], d[0], d[2]) %}
151
+ | cons_expression {% id %}
152
+
153
+ # priority 5
154
+ cons_expression ->
155
+ concatenation ":" cons_expression {% (d) => new ConsExpression(d[0], d[2]) %}
156
+ | concatenation {% id %}
157
+
158
+ concatenation ->
159
+ addition "++" concatenation {% (d) => new ListBinaryOperation("Concat", d[0], d[2]) %}
160
+ | addition {% id %}
161
+
162
+ # priority 6
163
+ addition ->
164
+ addition "+" multiplication {% (d) => new ArithmeticBinaryOperation("Plus", d[0], d[2]) %}
165
+ | addition "-" multiplication {% (d) => new ArithmeticBinaryOperation("Minus", d[0], d[2]) %}
166
+ | multiplication {% id %}
167
+
168
+ # priority 7
169
+ multiplication ->
170
+ multiplication "*" power {% (d) => new ArithmeticBinaryOperation("Multiply", d[0], d[2]) %}
171
+ | multiplication "/" power {% (d) => new ArithmeticBinaryOperation("Divide", d[0], d[2]) %}
172
+ | power {% id %}
173
+
174
+ # priority 8
175
+ power ->
176
+ unary_negation "**" power {% (d) => new ArithmeticBinaryOperation("Power", d[0], d[2]) %}
177
+ | unary_negation "^" power {% (d) => new ArithmeticBinaryOperation("Power", d[0], d[2]) %}
178
+ | unary_negation "^^" power {% (d) => new ArithmeticBinaryOperation("Power", d[0], d[2]) %}
179
+ | unary_negation {% id %}
180
+
181
+ unary_negation ->
182
+ "-" unary_negation {% (d) => new ArithmeticUnaryOperation("Negation", d[1]) %}
183
+ | index_access {% id %}
184
+
185
+ # priority 9
186
+ index_access ->
187
+ index_access "!!" composition_expression {% (d) => new ListBinaryOperation("GetAt", d[0], d[2]) %}
188
+ | composition_expression {% id %}
189
+
190
+ composition_expression ->
191
+ composition_expression "." infix_operator_expression {% (d) => new CompositionExpression(d[0], d[2]) %}
192
+ | infix_operator_expression {% id %}
193
+
194
+ infix_operator_expression ->
195
+ infix_operator_expression "`" variable "`" application {% (d) => new Application(new Application(d[2], d[0]), d[4]) %}
196
+ | application {% id %}
197
+
198
+ application ->
199
+ "error" primary {% d => new Raise(d[1]) %}
200
+ | primary primary:* {% (d) => {
201
+ if (d[1].length === 0) return d[0];
202
+ return d[1].reduce((left, right) => new Application(left, right), d[0]);
203
+ } %}
204
+
205
+ operator ->
206
+ operator_no_minus {% id %}
207
+ | "-" {% (d) => d[0].value %}
208
+
209
+ operator_no_minus ->
210
+ ("=="
211
+ | "/="
212
+ | "<"
213
+ | ">"
214
+ | "<="
215
+ | "&&"
216
+ | "||"
217
+ | ">="
218
+ | "++"
219
+ | "+"
220
+ | ","
221
+ | "^^"
222
+ | "^"
223
+ | "**"
224
+ | "*"
225
+ | "!!"
226
+ | "/"
227
+ | "$"
228
+ | "$!"
229
+ | "."
230
+ | ":") {% (d) => d[0][0].value %}
231
+
232
+ left_section -> "(" expression operator ")" {% (d) => new Application(new SymbolPrimitive(d[2]), d[1]) %}
233
+
234
+ right_section -> "(" operator_no_minus expression ")" {% (d) => {
235
+ const flipBody = new SymbolPrimitive("flip");
236
+ const op = new SymbolPrimitive(d[1]);
237
+ const expr = d[2];
238
+ const flipAppliedToOp = new Application(flipBody, op);
239
+ return new Application(flipAppliedToOp, expr);
240
+ }
241
+ %}
242
+
243
+ operator_section -> "(" operator ")" {% (d) => new SymbolPrimitive(d[1]) %}
244
+
245
+ primary ->
246
+ primitive {% id %}
247
+ | variable {% id %}
248
+ | constr {% id %}
249
+ | tuple_expression {% id %}
250
+ | left_section {% id %}
251
+ | right_section {% id %}
252
+ | operator_section {% id %}
253
+ | list_literal {% id %}
254
+ | lambda_expression {% id %}
255
+ | data_expression {% id %}
256
+ | list_comprehension {% id %}
257
+ | "(" expression ")" {% (d) => d[1] %}
258
+ | "[" range_expression "]" {% (d) => d[1] %}
259
+ # Expression rules
260
+
261
+ # List comprehension rules
262
+ list_comprehension ->
263
+ "[" expression "|" comprehension_clause_list "]" {% (d) => {
264
+ return new ListComprehension(d[1], d[3]);
265
+ } %}
266
+
267
+ comprehension_clause_list ->
268
+ comprehension_clause ("," comprehension_clause):* {% (d) => {
269
+ return [d[0], ...d[1].map((x) => x[1])];
270
+ } %}
271
+
272
+ comprehension_clause ->
273
+ variable "<-" expression {% (d) => new Generator(d[0], d[2]) %}
274
+ | expression {% id %}
275
+
276
+ lambda_expression ->
277
+ "(" "\\" parameter_list "->" expression ")" {% (d) => new Lambda(d[2], d[4]) %}
278
+
279
+ tuple_expression -> "(" expression ("," expression):+ ")" {% (d) => new TupleExpression([d[1], ...d[2].map(x => x[1])]) %}
280
+
281
+ data_expression -> constr %lbracket fields_expressions %rbracket {% (d) => new DataExpression(d[0], d[2]) %}
282
+
283
+ fields_expressions -> field_exp ("," field_exp):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
284
+
285
+ field_exp -> variable "=" expression {% (d) => new FieldExpression(d[0], d[2]) %}
286
+
287
+ if_expression -> "if" expression "then" expression "else" expression {% (d) => new If(d[1], d[3], d[5]) %}
288
+
289
+ letin_expression -> "let" "{" bindings_list:? "}" "in" expression {% (d) => new LetInExpression(new Sequence(d[2] ?? []), d[5]) %}
290
+
291
+ case_expression -> "case" expression "of" "{" case_arms "}" {% (d) => new Switch(d[1], d[4]) %}
292
+
293
+ case_arms -> case_arm (";" case_arm):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
294
+
295
+ case_arm -> pattern "->" expression {% (d) => new Case(d[0], d[2]) %}
296
+
297
+ # Type class rules
298
+
299
+ typeclass_declaration -> "class" constr variable "where" %lbracket typeclass_body %rbracket {% (d) => new TypeClass(d[1], d[2], d[5]) %}
300
+
301
+ typeclass_body -> function_signature (";" function_signature):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
302
+
303
+ instance_declaration -> "instance" constr type "where" %lbracket instance_body %rbracket {% (d) => new Instance(d[1], d[2], d[5]) %}
304
+
305
+ instance_body -> (function_declaration | function_signature) (";" (function_declaration | function_signature)):* ";":? {% (d) => [d[0][0], ...d[1].map(x => x[1][0])] %}
306
+
307
+ # Data rules
308
+
309
+ data_declaration -> "data" constr type_variable:* "=" constructor_def ("|" constructor_def):* deriving_clause:? {%
310
+ (d) => new Record(d[1], [d[4], ...d[5].map(x => x[1])], d[6])
311
+ %}
312
+
313
+ deriving_clause ->
314
+ "deriving" deriving_spec {% (d) => d[1] %}
315
+
316
+ deriving_spec ->
317
+ "(" deriving_classes ")" {% (d) => d[1] %}
318
+ | constr {% (d) => [d[0]] %}
319
+
320
+ deriving_classes ->
321
+ constr ("," constr):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
322
+
323
+ constructor_def ->
324
+ constr %lbracket field_list %rbracket {% (d) => new Constructor(d[0], d[2]) %}
325
+ | constr simple_type:* {% (d) => new Constructor(d[0], d[1].map(x => new Field(undefined, x))) %}
326
+
327
+ field_list -> field ("," field):* {% (d) => [d[0], ...d[1].map(x => x[1])]%}
328
+
329
+ field -> variable "::" type {% (d) => new Field(d[0], d[2]) %}
330
+
331
+ # Function rules
332
+
333
+ op_name -> "(" operator ")" {% d => new SymbolPrimitive(d[1]) %}
334
+
335
+ binding_name ->
336
+ op_name {% id %}
337
+ | variable {% id %}
338
+
339
+ function_signature -> binding_name "::" type {% (d) => new TypeSignature(d[0], d[2]) %}
340
+
341
+ function_declaration -> binding_name equation {% (d) => new Function(d[0], [d[1]]) %}
342
+
343
+ return_expression -> expression {% d => new Return(d[0]) %}
344
+
345
+ where_clause -> "where" "{" bindings_list "}" {% d => d[2] %}
346
+
347
+ bindings_list ->
348
+ function_declaration ";" bindings_list {% d => [d[0], ...d[2]] %}
349
+ | function_declaration {% d => [d[0]] %}
350
+
351
+ equation ->
352
+ params guarded_rhs where_clause:? {% (d) => {
353
+ const body = d[1];
354
+ const finalBody = d[2]
355
+ ? body.map(guard => new GuardedBody(guard.condition, new Sequence([...d[2], new Return(guard.body)])))
356
+ : body;
357
+ return new Equation(d[0], finalBody);
358
+ } %}
359
+ | params %assign return_expression where_clause:? {% d => new Equation(d[0], new UnguardedBody(new Sequence(d[3] ? [...d[3], d[2]] : [d[2]])), d[2]) %}
360
+
361
+ params -> parameter_list:? {% (d) => d[0] || [] %}
362
+
363
+ guarded_rhs -> guarded_branch:+ {% (d) => d[0] %}
364
+
365
+ guarded_branch ->
366
+ "|" condition "=" expression {% (d) => new GuardedBody(d[1], d[3]) %}
367
+
368
+ condition ->
369
+ "otherwise" {% d => new Otherwise() %}
370
+ | expression {% d => d[0] %}
371
+
372
+ parameter_list -> pattern:+ {% id %}
373
+
374
+ # Patterns
375
+
376
+ pattern -> cons_pattern {% id %}
377
+
378
+ cons_pattern ->
379
+ "(" cons_pattern (":" cons_pattern):+ ")" {%
380
+ (d) => {
381
+ const patterns = [d[1], ...d[2].map(item => item[1])];
382
+ return patterns.reduceRight((tail, head, index, arr) => {
383
+ if (index === arr.length - 1) return tail;
384
+ return new ConsPattern(head, tail);
385
+ });
386
+ }
387
+ %}
388
+ | simple_pattern {% id %}
389
+
390
+ simple_pattern ->
391
+ (as_pattern
392
+ | constructor_pattern
393
+ | list_pattern
394
+ | tuple_pattern
395
+ #| record_pattern
396
+ | literal_pattern
397
+ | variable_pattern
398
+ | wildcard_pattern
399
+ | paren_pattern) {% (d) => d[0][0] %}
400
+
401
+ wildcard_pattern -> %anonymousVariable {% (d) => new WildcardPattern() %}
402
+
403
+ paren_pattern -> "(" pattern ")" {% (d) => d[1] %}
404
+
405
+ variable_pattern -> variable {% (d) => new VariablePattern(d[0]) %}
406
+
407
+ literal_pattern -> primitive {% (d) => new LiteralPattern(d[0]) %}
408
+
409
+ as_pattern -> (variable_pattern | wildcard_pattern) "@" pattern {% (d) => new AsPattern(d[0][0], d[2]) %}
410
+
411
+ constructor_pattern ->
412
+ "(" constr pattern:+ ")" {% (d) => new ConstructorPattern(d[1], d[2]) %}
413
+ | constr {% (d) => new ConstructorPattern(d[0], []) %}
414
+
415
+ # record_pattern ->
416
+ # constr:? _ %lbracket _ field_pattern_list _ %rbracket {% (d) => ({
417
+ # type: "RecordPattern",
418
+ # constructor: d[0] ? d[0].value : null,
419
+ # fields: d[4]
420
+ # }) %}
421
+
422
+ field_pattern_list -> field_pattern ("," field_pattern):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
423
+
424
+ field_pattern -> variable "=" pattern {% (d) => ({ field: d[0].value, pattern: d[2] }) %}
425
+
426
+ list_pattern -> "[" pattern_list:? "]" {% (d) => new ListPattern(d[1] || []) %}
427
+
428
+ pattern_list -> pattern ("," pattern):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
429
+
430
+ tuple_pattern -> "(" pattern ("," pattern):+ ")" {% (d) => new TuplePattern([d[1], ...d[2].map(x => x[1])]) %}
431
+
432
+ # Type rules
433
+
434
+ type_declaration -> "type" constr variable_list:? "=" type {% (d) => new TypeAlias(d[1], d[2] || [], d[4]) %}
435
+
436
+ variable_list -> variable variable:* {% (d) => [d[0].value, ...d[1]] %}
437
+
438
+ type -> function_type {% id %}
439
+
440
+ constrained_type -> constraint_list "=>" type {% (d) => new ParameterizedType([], d[2], d[0]) %}
441
+
442
+ context ->
443
+ constraint {% (d) => [d[0]] %}
444
+ | "(" constraint_list ")" {% (d) => d[1] %}
445
+
446
+ constraint_list ->
447
+ constraint ("," constraint):* {% (d) =>
448
+ [d[0], ...d[1].map(x => x[1])]
449
+ %}
450
+
451
+ constraint -> constr application_type:+ {% (d) => new Constraint(d[0].value, d[1]) %}
452
+
453
+ function_type ->
454
+ (context "=>"):? (application_type %typeArrow):* application_type {% (d) => {
455
+ const constraints = d[0] ? d[0][0] : [];
456
+
457
+ if (d[1].length > 0)
458
+ return new ParameterizedType(d[1].map(x => x[0]), d[2], constraints);
459
+
460
+ if (constraints.length === 0)
461
+ return d[2];
462
+
463
+ return new ParameterizedType([], d[2], constraints);
464
+ }
465
+ %}
466
+
467
+ application_type ->
468
+ simple_type application_type {% (d) => new TypeApplication(d[0], d[1]) %}
469
+ | simple_type {% id %}
470
+
471
+ simple_type ->
472
+ (type_variable | type_constructor) {% (d) => new SimpleType(d[0][0].value, []) %}
473
+ | "[" type "]" {% (d) => new ListType(d[1], []) %}
474
+ | "(" type ("," type):+ ")" {% (d) => new TupleType([d[1], ...d[2].map(x => x[1])], []) %}
475
+ | "(" type ")" {% (d) => d[1] %}
476
+
477
+ type_variable -> variable {% ([v]) => ({ value: v.value }) %}
478
+ type_constructor -> constr {% ([c]) => ({ value: c.value }) %}
479
+
480
+ # Misc rules
481
+
482
+ constr -> %constructor {% ([c]) => new SymbolPrimitive(c.value, loc(c)) %} # constr because js doesnt like rules called constructor
483
+ variable -> %variable {% ([v]) => new SymbolPrimitive(v.value, loc(v)) %}
484
+
485
+ list_literal ->
486
+ "[" "]" {% (_) => new ListPrimitive([]) %}
487
+ | "[" expression_list "]" {% (d) => new ListPrimitive(d[1]) %}
488
+
489
+ range_expression ->
490
+ expression ".." {% (d) => new RangeExpression(d[0]) %} # [start ..]
491
+ | expression ".." expression {% (d) => new RangeExpression(d[0], d[2]) %} # [start .. end]
492
+ | expression "," expression ".." {% (d) => new RangeExpression(d[0], undefined, d[2]) %} # [start, second ..]
493
+ | expression "," expression ".." expression {% (d) => new RangeExpression(d[0], d[4], d[2]) %} # [start, second .. end]
494
+
495
+ expression_list -> expression ("," expression):* {% (d) => [d[0], ...d[1].map(x => x[1])] %}
496
+
497
+ comparison_operator ->
498
+ "==" {% (d) => "Equal" %}
499
+ | "/=" {% (d) => "NotEqual" %}
500
+ | "<" {% (d) => "LessThan" %}
501
+ | ">" {% (d) => "GreaterThan" %}
502
+ | "<=" {% (d) => "LessOrEqualThan" %}
503
+ | ">=" {% (d) => "GreaterOrEqualThan" %}
504
+
505
+ primitive ->
506
+ %number {% ([n]) => new NumberPrimitive(Number(n.value), loc(n)) %}
507
+ | %char {% ([c]) => new CharPrimitive(c.value.slice(1, -1), loc(c)) %}
508
+ | %string {% ([s]) => {
509
+ let val = s.value.slice(1, -1);
510
+ // Haskell multiline string continuation: \ whitespace \
511
+ val = val.replace(/\\\s+\\/g, "");
512
+ // Standard escapes
513
+ val = val.replace(/\\n/g, "\n")
514
+ .replace(/\\t/g, "\t")
515
+ .replace(/\\"/g, "\"")
516
+ .replace(/\\\\/g, "\\");
517
+ return new StringPrimitive(val, loc(s));
518
+ } %}
519
+ | %bool {% ([b]) => new BooleanPrimitive(b.value === 'True' ? true : false, loc(b)) %}