yukigo-prolog-parser 0.1.0

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.
@@ -0,0 +1,830 @@
1
+ import { describe, it } from "mocha";
2
+ import { assert } from "chai";
3
+ import { YukigoPrologParser } from "../src/index.js";
4
+ import { inspect } from "util";
5
+ import { readFileSync } from "fs";
6
+ import {
7
+ ArithmeticBinaryOperation,
8
+ ArithmeticUnaryOperation,
9
+ AssignOperation,
10
+ ComparisonOperation,
11
+ Exist,
12
+ Fact,
13
+ Findall,
14
+ Forall,
15
+ FunctorPattern,
16
+ If,
17
+ LiteralPattern,
18
+ Not,
19
+ NumberPrimitive,
20
+ Return,
21
+ Rule,
22
+ Sequence,
23
+ SymbolPrimitive,
24
+ TuplePattern,
25
+ UnifyOperation,
26
+ VariablePattern,
27
+ WildcardPattern,
28
+ YukigoParser,
29
+ } from "yukigo-ast";
30
+ const _deepEqual = assert.deepEqual;
31
+ assert.deepEqual = function (actual: any, expected: any, ...args: any[]) {
32
+ function stripLoc(obj: any): any {
33
+ if (Array.isArray(obj)) return obj.map(stripLoc);
34
+ if (obj && typeof obj === "object") {
35
+ const { loc, ...rest } = obj;
36
+ return Object.fromEntries(
37
+ Object.entries(rest).map(([k, v]) => [k, stripLoc(v)])
38
+ );
39
+ }
40
+ return obj;
41
+ }
42
+ return _deepEqual(stripLoc(actual), stripLoc(expected), ...args);
43
+ };
44
+
45
+ describe("Parser Test", () => {
46
+ let parser: YukigoParser;
47
+ beforeEach(() => {
48
+ parser = new YukigoPrologParser();
49
+ });
50
+ it("std.pl", () => {
51
+ assert.doesNotThrow(() =>
52
+ parser.parse(readFileSync("./src/std.pl").toString())
53
+ );
54
+ });
55
+ it("simplest fact/0", () => {
56
+ assert.deepEqual(parser.parse("foo."), [
57
+ new Fact(new SymbolPrimitive("foo"), []),
58
+ ]);
59
+ });
60
+ it("simplest fact/1", () => {
61
+ assert.deepEqual(parser.parse("foo(bar)."), [
62
+ new Fact(new SymbolPrimitive("foo"), [
63
+ new LiteralPattern(new SymbolPrimitive("bar")),
64
+ ]),
65
+ ]);
66
+ });
67
+ it("literal integer", () => {
68
+ assert.deepEqual(parser.parse("foo(3)."), [
69
+ new Fact(new SymbolPrimitive("foo"), [
70
+ new LiteralPattern(new NumberPrimitive(3)),
71
+ ]),
72
+ ]);
73
+ });
74
+ it("literal float", () => {
75
+ assert.deepEqual(parser.parse("foo(3.4)."), [
76
+ new Fact(new SymbolPrimitive("foo"), [
77
+ new LiteralPattern(new NumberPrimitive(3.4)),
78
+ ]),
79
+ ]);
80
+ });
81
+ it("wildcard", () => {
82
+ assert.deepEqual(parser.parse("foo(_)."), [
83
+ new Fact(new SymbolPrimitive("foo"), [new WildcardPattern()]),
84
+ ]);
85
+ });
86
+ it("multiple facts", () => {
87
+ assert.deepEqual(parser.parse("foo(bar).baz(bar)."), [
88
+ new Fact(new SymbolPrimitive("foo"), [
89
+ new LiteralPattern(new SymbolPrimitive("bar")),
90
+ ]),
91
+ new Fact(new SymbolPrimitive("baz"), [
92
+ new LiteralPattern(new SymbolPrimitive("bar")),
93
+ ]),
94
+ ]);
95
+ });
96
+ it("multiple facts, whitespaces separated", () => {
97
+ assert.deepEqual(parser.parse("foo(bar). baz(bar)."), [
98
+ new Fact(new SymbolPrimitive("foo"), [
99
+ new LiteralPattern(new SymbolPrimitive("bar")),
100
+ ]),
101
+ new Fact(new SymbolPrimitive("baz"), [
102
+ new LiteralPattern(new SymbolPrimitive("bar")),
103
+ ]),
104
+ ]);
105
+ });
106
+ it("multiple facts, newline separated", () => {
107
+ assert.deepEqual(parser.parse("foo(bar).\nbaz(bar)."), [
108
+ new Fact(new SymbolPrimitive("foo"), [
109
+ new LiteralPattern(new SymbolPrimitive("bar")),
110
+ ]),
111
+ new Fact(new SymbolPrimitive("baz"), [
112
+ new LiteralPattern(new SymbolPrimitive("bar")),
113
+ ]),
114
+ ]);
115
+ });
116
+ it("simplest fact/2", () => {
117
+ assert.deepEqual(parser.parse("foo(bar, baz)."), [
118
+ new Fact(new SymbolPrimitive("foo"), [
119
+ new LiteralPattern(new SymbolPrimitive("bar")),
120
+ new LiteralPattern(new SymbolPrimitive("baz")),
121
+ ]),
122
+ ]);
123
+ });
124
+ it("simplest rule/1", () => {
125
+ assert.deepEqual(parser.parse("baz(bar):-foo."), [
126
+ new Rule(
127
+ new SymbolPrimitive("baz"),
128
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
129
+ [new Exist(new SymbolPrimitive("foo"), [])]
130
+ ),
131
+ ]);
132
+ });
133
+ it("simplest rule/0", () => {
134
+ assert.deepEqual(parser.parse("baz:-foo."), [
135
+ new Rule(
136
+ new SymbolPrimitive("baz"),
137
+ [],
138
+ [new Exist(new SymbolPrimitive("foo"), [])]
139
+ ),
140
+ ]);
141
+ });
142
+ it("rules with withiespaces", () => {
143
+ assert.deepEqual(
144
+ parser.parse("baz:-foo(X), baz(X,Y)."),
145
+ parser.parse("baz :- foo( X) ,baz( X , Y) .")
146
+ );
147
+ });
148
+ it("rules with bang", () => {
149
+ assert.deepEqual(parser.parse("baz:-fail,!."), [
150
+ new Rule(
151
+ new SymbolPrimitive("baz"),
152
+ [],
153
+ [
154
+ new Exist(new SymbolPrimitive("fail"), []),
155
+ new Exist(new SymbolPrimitive("!"), []),
156
+ ]
157
+ ),
158
+ ]);
159
+ });
160
+ it("simplest rule/1 with condition/1", () => {
161
+ assert.deepEqual(parser.parse("baz(bar):-foo(bar)."), [
162
+ new Rule(
163
+ new SymbolPrimitive("baz"),
164
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
165
+ [
166
+ new Exist(new SymbolPrimitive("foo"), [
167
+ new LiteralPattern(new SymbolPrimitive("bar")),
168
+ ]),
169
+ ]
170
+ ),
171
+ ]);
172
+ });
173
+ it("fact with functors", () => {
174
+ assert.deepEqual(parser.parse("foo(f(bar))."), [
175
+ new Fact(new SymbolPrimitive("foo"), [
176
+ new FunctorPattern(new SymbolPrimitive("f"), [
177
+ new LiteralPattern(new SymbolPrimitive("bar")),
178
+ ]),
179
+ ]),
180
+ ]);
181
+ });
182
+ it("fact with functor with variables", () => {
183
+ assert.deepEqual(parser.parse("foo(f(X))."), [
184
+ new Fact(new SymbolPrimitive("foo"), [
185
+ new FunctorPattern(new SymbolPrimitive("f"), [
186
+ new VariablePattern(new SymbolPrimitive("X")),
187
+ ]),
188
+ ]),
189
+ ]);
190
+ });
191
+ it("fact with multiple variables", () => {
192
+ assert.deepEqual(parser.parse("foo(X, Y)."), [
193
+ new Fact(new SymbolPrimitive("foo"), [
194
+ new VariablePattern(new SymbolPrimitive("X")),
195
+ new VariablePattern(new SymbolPrimitive("Y")),
196
+ ]),
197
+ ]);
198
+ });
199
+ it("multiple rules", () => {
200
+ assert.deepEqual(
201
+ parser.parse("baz(bar) :- foo(bar).foo(bar) :- bar(bar)."),
202
+ [
203
+ new Rule(
204
+ new SymbolPrimitive("baz"),
205
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
206
+ [
207
+ new Exist(new SymbolPrimitive("foo"), [
208
+ new LiteralPattern(new SymbolPrimitive("bar")),
209
+ ]),
210
+ ]
211
+ ),
212
+ new Rule(
213
+ new SymbolPrimitive("foo"),
214
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
215
+ [
216
+ new Exist(new SymbolPrimitive("bar"), [
217
+ new LiteralPattern(new SymbolPrimitive("bar")),
218
+ ]),
219
+ ]
220
+ ),
221
+ ]
222
+ );
223
+ });
224
+ it("simplest rule/2 with condition/2", () => {
225
+ assert.deepEqual(parser.parse("baz(bar,fux):-foo(bar,goo)."), [
226
+ new Rule(
227
+ new SymbolPrimitive("baz"),
228
+ [
229
+ new LiteralPattern(new SymbolPrimitive("bar")),
230
+ new LiteralPattern(new SymbolPrimitive("fux")),
231
+ ],
232
+ [
233
+ new Exist(new SymbolPrimitive("foo"), [
234
+ new LiteralPattern(new SymbolPrimitive("bar")),
235
+ new LiteralPattern(new SymbolPrimitive("goo")),
236
+ ]),
237
+ ]
238
+ ),
239
+ ]);
240
+ });
241
+ it("rule/1 with not", () => {
242
+ assert.deepEqual(parser.parse("baz(X):-not(bar(X))."), [
243
+ new Rule(
244
+ new SymbolPrimitive("baz"),
245
+ [new VariablePattern(new SymbolPrimitive("X"))],
246
+ [
247
+ new Not([
248
+ new Exist(new SymbolPrimitive("bar"), [
249
+ new VariablePattern(new SymbolPrimitive("X")),
250
+ ]),
251
+ ]),
252
+ ]
253
+ ),
254
+ ]);
255
+ });
256
+ it("rules with infix not", () => {
257
+ assert.deepEqual(parser.parse("baz(X):-\\+ bar(X)."), [
258
+ new Rule(
259
+ new SymbolPrimitive("baz"),
260
+ [new VariablePattern(new SymbolPrimitive("X"))],
261
+ [
262
+ new Not([
263
+ new Exist(new SymbolPrimitive("bar"), [
264
+ new VariablePattern(new SymbolPrimitive("X")),
265
+ ]),
266
+ ]),
267
+ ]
268
+ ),
269
+ ]);
270
+ });
271
+ it("rule/1 with complex not", () => {
272
+ assert.deepEqual(parser.parse("baz(X):-not((bar(X), baz(Y)))."), [
273
+ new Rule(
274
+ new SymbolPrimitive("baz"),
275
+ [new VariablePattern(new SymbolPrimitive("X"))],
276
+ [
277
+ new Not([
278
+ new Sequence([
279
+ new Exist(new SymbolPrimitive("bar"), [
280
+ new VariablePattern(new SymbolPrimitive("X")),
281
+ ]),
282
+ new Exist(new SymbolPrimitive("baz"), [
283
+ new VariablePattern(new SymbolPrimitive("Y")),
284
+ ]),
285
+ ]),
286
+ ]),
287
+ ]
288
+ ),
289
+ ]);
290
+ });
291
+ it("rule/1 with forall", () => {
292
+ assert.deepEqual(parser.parse("baz(X):- forall(bar(X), bar(X))."), [
293
+ new Rule(
294
+ new SymbolPrimitive("baz"),
295
+ [new VariablePattern(new SymbolPrimitive("X"))],
296
+ [
297
+ new Forall(
298
+ new Exist(new SymbolPrimitive("bar"), [
299
+ new VariablePattern(new SymbolPrimitive("X")),
300
+ ]),
301
+
302
+ new Exist(new SymbolPrimitive("bar"), [
303
+ new VariablePattern(new SymbolPrimitive("X")),
304
+ ])
305
+ ),
306
+ ]
307
+ ),
308
+ ]);
309
+ });
310
+ it("rule/1 with findall", () => {
311
+ assert.deepEqual(parser.parse("baz(X):- findall(Y, bar(X, Y), Z)."), [
312
+ new Rule(
313
+ new SymbolPrimitive("baz"),
314
+ [new VariablePattern(new SymbolPrimitive("X"))],
315
+ [
316
+ new Findall(
317
+ new Exist(new SymbolPrimitive("Y"), []),
318
+ new Exist(new SymbolPrimitive("bar"), [
319
+ new VariablePattern(new SymbolPrimitive("X")),
320
+ new VariablePattern(new SymbolPrimitive("Y")),
321
+ ]),
322
+ new Exist(new SymbolPrimitive("Z"), [])
323
+ ),
324
+ ]
325
+ ),
326
+ ]);
327
+ });
328
+ it("rule/1 with major", () => {
329
+ assert.deepEqual(parser.parse("baz(X):- X > 4."), [
330
+ new Rule(
331
+ new SymbolPrimitive("baz"),
332
+ [new VariablePattern(new SymbolPrimitive("X"))],
333
+ [
334
+ new ComparisonOperation(
335
+ "GreaterThan",
336
+ new SymbolPrimitive("X"),
337
+ new NumberPrimitive(4)
338
+ ),
339
+ ]
340
+ ),
341
+ ]);
342
+ });
343
+ it("rule/1 with minor", () => {
344
+ assert.deepEqual(parser.parse("baz(X):- X < 4."), [
345
+ new Rule(
346
+ new SymbolPrimitive("baz"),
347
+ [new VariablePattern(new SymbolPrimitive("X"))],
348
+ [
349
+ new ComparisonOperation(
350
+ "LessThan",
351
+ new SymbolPrimitive("X"),
352
+ new NumberPrimitive(4)
353
+ ),
354
+ ]
355
+ ),
356
+ ]);
357
+ });
358
+ it("rule/1 with greater or equal", () => {
359
+ assert.deepEqual(parser.parse("baz(X):- X >= 4."), [
360
+ new Rule(
361
+ new SymbolPrimitive("baz"),
362
+ [new VariablePattern(new SymbolPrimitive("X"))],
363
+ [
364
+ new ComparisonOperation(
365
+ "GreaterOrEqualThan",
366
+ new SymbolPrimitive("X"),
367
+ new NumberPrimitive(4)
368
+ ),
369
+ ]
370
+ ),
371
+ ]);
372
+ });
373
+ it("rule/1 with minor or equal", () => {
374
+ assert.deepEqual(parser.parse("baz(X):- X =< 4."), [
375
+ new Rule(
376
+ new SymbolPrimitive("baz"),
377
+ [new VariablePattern(new SymbolPrimitive("X"))],
378
+ [
379
+ new ComparisonOperation(
380
+ "LessOrEqualThan",
381
+ new SymbolPrimitive("X"),
382
+ new NumberPrimitive(4)
383
+ ),
384
+ ]
385
+ ),
386
+ ]);
387
+ });
388
+ it("rule/1 with distinct", () => {
389
+ assert.deepEqual(parser.parse("baz(X):- X \\= 4."), [
390
+ new Rule(
391
+ new SymbolPrimitive("baz"),
392
+ [new VariablePattern(new SymbolPrimitive("X"))],
393
+ [
394
+ new ComparisonOperation(
395
+ "NotSame",
396
+ new SymbolPrimitive("X"),
397
+ new NumberPrimitive(4)
398
+ ),
399
+ ]
400
+ ),
401
+ ]);
402
+ });
403
+ it("rule/1 with unify operator", () => {
404
+ assert.deepEqual(parser.parse("baz(X):- X = 4."), [
405
+ new Rule(
406
+ new SymbolPrimitive("baz"),
407
+ [new VariablePattern(new SymbolPrimitive("X"))],
408
+ [
409
+ new UnifyOperation(
410
+ "Unify",
411
+ new SymbolPrimitive("X"),
412
+ new NumberPrimitive(4)
413
+ ),
414
+ ]
415
+ ),
416
+ ]);
417
+ });
418
+ it("rule/1 with simple is", () => {
419
+ assert.deepEqual(parser.parse("baz(X):- X is 4."), [
420
+ new Rule(
421
+ new SymbolPrimitive("baz"),
422
+ [new VariablePattern(new SymbolPrimitive("X"))],
423
+ [
424
+ new AssignOperation(
425
+ "Assign",
426
+ new SymbolPrimitive("X"),
427
+ new NumberPrimitive(4)
428
+ ),
429
+ ]
430
+ ),
431
+ ]);
432
+ });
433
+ it("rule/1 with is with parenthesis", () => {
434
+ assert.deepEqual(parser.parse("baz(X):- X is (4)."), [
435
+ new Rule(
436
+ new SymbolPrimitive("baz"),
437
+ [new VariablePattern(new SymbolPrimitive("X"))],
438
+ [
439
+ new AssignOperation(
440
+ "Assign",
441
+ new SymbolPrimitive("X"),
442
+ new NumberPrimitive(4)
443
+ ),
444
+ ]
445
+ ),
446
+ ]);
447
+ });
448
+ it("fact/1 with tuples", () => {
449
+ assert.deepEqual(parser.parse("baz((1, 2))."), [
450
+ new Fact(new SymbolPrimitive("baz"), [
451
+ new TuplePattern([
452
+ new LiteralPattern(new NumberPrimitive(1)),
453
+ new LiteralPattern(new NumberPrimitive(2)),
454
+ ]),
455
+ ]),
456
+ ]);
457
+ });
458
+ it("rule/1 with is and -", () => {
459
+ assert.deepEqual(parser.parse("baz(X, Y):- X is Y - 5 ."), [
460
+ new Rule(
461
+ new SymbolPrimitive("baz"),
462
+ [
463
+ new VariablePattern(new SymbolPrimitive("X")),
464
+ new VariablePattern(new SymbolPrimitive("Y")),
465
+ ],
466
+ [
467
+ new AssignOperation(
468
+ "Assign",
469
+ new SymbolPrimitive("X"),
470
+ new ArithmeticBinaryOperation(
471
+ "Minus",
472
+ new SymbolPrimitive("Y"),
473
+ new NumberPrimitive(5)
474
+ )
475
+ ),
476
+ ]
477
+ ),
478
+ ]);
479
+ });
480
+ it("rule/1 with is and +", () => {
481
+ assert.deepEqual(parser.parse("baz(X, Y):- X is Y + 5."), [
482
+ new Rule(
483
+ new SymbolPrimitive("baz"),
484
+ [
485
+ new VariablePattern(new SymbolPrimitive("X")),
486
+ new VariablePattern(new SymbolPrimitive("Y")),
487
+ ],
488
+ [
489
+ new AssignOperation(
490
+ "Assign",
491
+ new SymbolPrimitive("X"),
492
+ new ArithmeticBinaryOperation(
493
+ "Plus",
494
+ new SymbolPrimitive("Y"),
495
+ new NumberPrimitive(5)
496
+ )
497
+ ),
498
+ ]
499
+ ),
500
+ ]);
501
+ });
502
+ it("rule/1 with =:=", () => {
503
+ assert.deepEqual(parser.parse("baz(X, Y):- X =:= Y."), [
504
+ new Rule(
505
+ new SymbolPrimitive("baz"),
506
+ [
507
+ new VariablePattern(new SymbolPrimitive("X")),
508
+ new VariablePattern(new SymbolPrimitive("Y")),
509
+ ],
510
+ [
511
+ new ComparisonOperation(
512
+ "Equal",
513
+ new SymbolPrimitive("X"),
514
+ new SymbolPrimitive("Y")
515
+ ),
516
+ ]
517
+ ),
518
+ ]);
519
+ });
520
+ it("rule/1 with ==", () => {
521
+ assert.deepEqual(parser.parse("baz(X, Y):- X == Y."), [
522
+ new Rule(
523
+ new SymbolPrimitive("baz"),
524
+ [
525
+ new VariablePattern(new SymbolPrimitive("X")),
526
+ new VariablePattern(new SymbolPrimitive("Y")),
527
+ ],
528
+ [
529
+ new ComparisonOperation(
530
+ "Same",
531
+ new SymbolPrimitive("X"),
532
+ new SymbolPrimitive("Y")
533
+ ),
534
+ ]
535
+ ),
536
+ ]);
537
+ });
538
+ it("rule/1 with is and parenthesis", () => {
539
+ assert.deepEqual(parser.parse("baz(X, Y):- X is (Y / 5) + 20."), [
540
+ new Rule(
541
+ new SymbolPrimitive("baz"),
542
+ [
543
+ new VariablePattern(new SymbolPrimitive("X")),
544
+ new VariablePattern(new SymbolPrimitive("Y")),
545
+ ],
546
+ [
547
+ new AssignOperation(
548
+ "Assign",
549
+ new SymbolPrimitive("X"),
550
+ new ArithmeticBinaryOperation(
551
+ "Plus",
552
+ new ArithmeticBinaryOperation(
553
+ "Divide",
554
+ new SymbolPrimitive("Y"),
555
+ new NumberPrimitive(5)
556
+ ),
557
+ new NumberPrimitive(20)
558
+ )
559
+ ),
560
+ ]
561
+ ),
562
+ ]);
563
+ });
564
+ it("rule/1 with is and functions", () => {
565
+ assert.deepEqual(parser.parse("baz(X, Y):- X is f(Y)."), [
566
+ new Rule(
567
+ new SymbolPrimitive("baz"),
568
+ [
569
+ new VariablePattern(new SymbolPrimitive("X")),
570
+ new VariablePattern(new SymbolPrimitive("Y")),
571
+ ],
572
+ [
573
+ new AssignOperation(
574
+ "Assign",
575
+ new SymbolPrimitive("X"),
576
+ new Exist(new SymbolPrimitive("f"), [
577
+ new VariablePattern(new SymbolPrimitive("Y")),
578
+ ])
579
+ ),
580
+ ]
581
+ ),
582
+ ]);
583
+ });
584
+ it("rule/1 with round function", () => {
585
+ assert.deepEqual(parser.parse("baz(X, Y):- X is round(3.5)."), [
586
+ new Rule(
587
+ new SymbolPrimitive("baz"),
588
+ [
589
+ new VariablePattern(new SymbolPrimitive("X")),
590
+ new VariablePattern(new SymbolPrimitive("Y")),
591
+ ],
592
+ [
593
+ new AssignOperation(
594
+ "Assign",
595
+ new SymbolPrimitive("X"),
596
+ new ArithmeticUnaryOperation("Round", new NumberPrimitive(3.5))
597
+ ),
598
+ ]
599
+ ),
600
+ ]);
601
+ });
602
+ it("rule/1 with abs function", () => {
603
+ assert.deepEqual(parser.parse("baz(X, Y):- X is abs(-3.5)."), [
604
+ new Rule(
605
+ new SymbolPrimitive("baz"),
606
+ [
607
+ new VariablePattern(new SymbolPrimitive("X")),
608
+ new VariablePattern(new SymbolPrimitive("Y")),
609
+ ],
610
+ [
611
+ new AssignOperation(
612
+ "Assign",
613
+ new SymbolPrimitive("X"),
614
+ new ArithmeticUnaryOperation("Absolute", new NumberPrimitive(-3.5))
615
+ ),
616
+ ]
617
+ ),
618
+ ]);
619
+ });
620
+ it("rule/1 with sqrt function", () => {
621
+ assert.deepEqual(parser.parse("baz(X, Y):- X is sqrt(3.5)."), [
622
+ new Rule(
623
+ new SymbolPrimitive("baz"),
624
+ [
625
+ new VariablePattern(new SymbolPrimitive("X")),
626
+ new VariablePattern(new SymbolPrimitive("Y")),
627
+ ],
628
+ [
629
+ new AssignOperation(
630
+ "Assign",
631
+ new SymbolPrimitive("X"),
632
+ new ArithmeticUnaryOperation("Sqrt", new NumberPrimitive(3.5))
633
+ ),
634
+ ]
635
+ ),
636
+ ]);
637
+ });
638
+ it("rule/1 with > and math", () => {
639
+ assert.deepEqual(parser.parse("baz(X):- X + 50 > x * 2."), [
640
+ new Rule(
641
+ new SymbolPrimitive("baz"),
642
+ [new VariablePattern(new SymbolPrimitive("X"))],
643
+ [
644
+ new ComparisonOperation(
645
+ "GreaterThan",
646
+ new ArithmeticBinaryOperation(
647
+ "Plus",
648
+ new SymbolPrimitive("X"),
649
+ new NumberPrimitive(50)
650
+ ),
651
+ new ArithmeticBinaryOperation(
652
+ "Multiply",
653
+ new SymbolPrimitive("x"),
654
+ new NumberPrimitive(2)
655
+ )
656
+ ),
657
+ ]
658
+ ),
659
+ ]);
660
+ });
661
+ it("rule/1 with multiple conditions", () => {
662
+ assert.deepEqual(parser.parse("baz(bar):-foo(bar),goo(bar)."), [
663
+ new Rule(
664
+ new SymbolPrimitive("baz"),
665
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
666
+ [
667
+ new Exist(new SymbolPrimitive("foo"), [
668
+ new LiteralPattern(new SymbolPrimitive("bar")),
669
+ ]),
670
+ new Exist(new SymbolPrimitive("goo"), [
671
+ new LiteralPattern(new SymbolPrimitive("bar")),
672
+ ]),
673
+ ]
674
+ ),
675
+ ]);
676
+ });
677
+ it("rule/1 with multiple conditions", () => {
678
+ assert.deepEqual(parser.parse("baz(bar):-foo(bar) ; goo(bar)."), [
679
+ new Rule(
680
+ new SymbolPrimitive("baz"),
681
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
682
+ [
683
+ new Exist(new SymbolPrimitive("foo"), [
684
+ new LiteralPattern(new SymbolPrimitive("bar")),
685
+ ]),
686
+ new Exist(new SymbolPrimitive("goo"), [
687
+ new LiteralPattern(new SymbolPrimitive("bar")),
688
+ ]),
689
+ ]
690
+ ),
691
+ ]);
692
+ });
693
+ it("rule/1 with multiple mixed conditions", () => {
694
+ assert.deepEqual(parser.parse("baz(bar):-foo(bar),goo(bar),baz."), [
695
+ new Rule(
696
+ new SymbolPrimitive("baz"),
697
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
698
+ [
699
+ new Exist(new SymbolPrimitive("foo"), [
700
+ new LiteralPattern(new SymbolPrimitive("bar")),
701
+ ]),
702
+ new Exist(new SymbolPrimitive("goo"), [
703
+ new LiteralPattern(new SymbolPrimitive("bar")),
704
+ ]),
705
+ new Exist(new SymbolPrimitive("baz"), []),
706
+ ]
707
+ ),
708
+ ]);
709
+ });
710
+ it("rule/1 with whitespaces among individuals", () => {
711
+ assert.deepEqual(parser.parse("baz(bar):-foo(bar, baz) , goo(bar), baz."), [
712
+ new Rule(
713
+ new SymbolPrimitive("baz"),
714
+ [new LiteralPattern(new SymbolPrimitive("bar"))],
715
+ [
716
+ new Exist(new SymbolPrimitive("foo"), [
717
+ new LiteralPattern(new SymbolPrimitive("bar")),
718
+ new LiteralPattern(new SymbolPrimitive("baz")),
719
+ ]),
720
+ new Exist(new SymbolPrimitive("goo"), [
721
+ new LiteralPattern(new SymbolPrimitive("bar")),
722
+ ]),
723
+ new Exist(new SymbolPrimitive("baz"), []),
724
+ ]
725
+ ),
726
+ ]);
727
+ });
728
+ it("rule/1 with if-then-else construct", () => {
729
+ assert.deepEqual(
730
+ parser.parse(
731
+ `classify_number(X, Classification) :- ( X > 0 -> Classification = positive ; ( X < 0 -> Classification = negative ; Classification = zero )).`
732
+ ),
733
+ [
734
+ new Rule(
735
+ new SymbolPrimitive("classify_number"),
736
+ [
737
+ new VariablePattern(new SymbolPrimitive("X")),
738
+ new VariablePattern(new SymbolPrimitive("Classification")),
739
+ ],
740
+ [
741
+ new If(
742
+ new ComparisonOperation(
743
+ "GreaterThan",
744
+ new SymbolPrimitive("X"),
745
+ new NumberPrimitive(0)
746
+ ),
747
+ new UnifyOperation(
748
+ "Unify",
749
+ new SymbolPrimitive("Classification"),
750
+ new SymbolPrimitive("positive")
751
+ ),
752
+ new If(
753
+ new ComparisonOperation(
754
+ "LessThan",
755
+ new SymbolPrimitive("X"),
756
+ new NumberPrimitive(0)
757
+ ),
758
+ new UnifyOperation(
759
+ "Unify",
760
+ new SymbolPrimitive("Classification"),
761
+ new SymbolPrimitive("negative")
762
+ ),
763
+ new UnifyOperation(
764
+ "Unify",
765
+ new SymbolPrimitive("Classification"),
766
+ new SymbolPrimitive("zero")
767
+ )
768
+ )
769
+ ),
770
+ ]
771
+ ),
772
+ ]
773
+ );
774
+ });
775
+ it("rule/1 with multiple whitespaces", () => {
776
+ const expectedAST = parser.parse("baz(bar) :- foo(bar), goo(bar), baz.");
777
+
778
+ assert.deepEqual(
779
+ parser.parse("baz(bar):-foo(bar) , goo(bar), baz."),
780
+ expectedAST
781
+ );
782
+ assert.deepEqual(
783
+ parser.parse("baz(bar) :- foo(bar) , goo(bar) , baz."),
784
+ expectedAST
785
+ );
786
+ assert.deepEqual(
787
+ parser.parse("baz(bar) :- foo( bar ) , goo( bar ) , baz."),
788
+ expectedAST
789
+ );
790
+ assert.deepEqual(
791
+ parser.parse("baz( bar ) :- foo( bar ) , goo( bar ) , baz."),
792
+ expectedAST
793
+ );
794
+ assert.deepEqual(
795
+ parser.parse("baz( bar ) :- \n foo( bar ) , \n goo( bar ), \n baz."),
796
+ expectedAST
797
+ );
798
+ assert.deepEqual(
799
+ parser.parse("baz(bar) :-\n foo(bar),\n goo(bar),\n baz.\n"),
800
+ expectedAST
801
+ );
802
+ });
803
+ it("can handle single line comments", () => {
804
+ assert.deepEqual(
805
+ parser.parse("%this is a comment\r\nfoo. %this is another comment"),
806
+ [new Fact(new SymbolPrimitive("foo"), [])]
807
+ );
808
+ });
809
+ it("can handle multi line comments", () => {
810
+ const code = `
811
+ /*
812
+ this is a
813
+ multiline comment
814
+ */
815
+ foo.`;
816
+ assert.deepEqual(parser.parse(code), [
817
+ new Fact(new SymbolPrimitive("foo"), []),
818
+ ]);
819
+ });
820
+ it("there can be characters in the same line as multiline comment delimiter", () => {
821
+ const code = `/*something
822
+ this is a
823
+ multiline comment
824
+ something else*/
825
+ foo.`;
826
+ assert.deepEqual(parser.parse(code), [
827
+ new Fact(new SymbolPrimitive("foo"), []),
828
+ ]);
829
+ });
830
+ });