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