bahasa-simpl 1.0.8 → 1.0.10
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.
- package/dist/simpl-interpreter.js +195 -76
- package/package.json +1 -1
|
@@ -92,10 +92,7 @@ function kePetik(v, thing) {
|
|
|
92
92
|
if (thing.type === logisSymbol) {
|
|
93
93
|
return thing.data ? "benar" : "salah";
|
|
94
94
|
} else if (thing.type === barisSymbol) {
|
|
95
|
-
return '[' + thing.data.reduce((str, val) =>
|
|
96
|
-
let item = kePetik(v, val);
|
|
97
|
-
return str + ", " + (val.type === Value.petikSymbol ? `"${item}"` : item);
|
|
98
|
-
}, "").slice(1) + ' ]';
|
|
95
|
+
return '[' + thing.data.reduce((str, val) => str+", "+kePetik(v, val), "").slice(1) + ' ]';
|
|
99
96
|
} else if (thing.type === stipeSymbol) {
|
|
100
97
|
return `Model<${thing.symbol.description}>`;
|
|
101
98
|
} else if (thing.type === mesinSymbol) {
|
|
@@ -104,7 +101,7 @@ function kePetik(v, thing) {
|
|
|
104
101
|
} else if (thing.type === angkaSymbol) {
|
|
105
102
|
return thing.data.toString();
|
|
106
103
|
} else if (thing.type === petikSymbol) {
|
|
107
|
-
return
|
|
104
|
+
return thing.data;
|
|
108
105
|
} else {
|
|
109
106
|
if (!thing?.type) return `nihil`;
|
|
110
107
|
let type = v.environment.get(thing.type.description);
|
|
@@ -118,8 +115,8 @@ function kePetik(v, thing) {
|
|
|
118
115
|
|
|
119
116
|
class PetikTipe extends Stipe {
|
|
120
117
|
constructor() {
|
|
121
|
-
super(petikSymbol, new Callable(null, (v, args) => new Value(petikSymbol, kePetik(v, args[0])),
|
|
122
|
-
[[null]], petikSymbol, true)
|
|
118
|
+
super(petikSymbol, new Callable(null, (v, args) => new Value(petikSymbol, kePetik(v, args[0])),
|
|
119
|
+
[[null]], petikSymbol, true));
|
|
123
120
|
this.init();
|
|
124
121
|
}
|
|
125
122
|
|
|
@@ -147,7 +144,7 @@ class PetikTipe extends Stipe {
|
|
|
147
144
|
this.member.define("SERU_UNER",
|
|
148
145
|
makeBuiltInFunc([petikSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
149
146
|
|
|
150
|
-
this.member.define("kePetik",
|
|
147
|
+
this.member.define("kePetik",
|
|
151
148
|
makeBuiltInFunc([petikSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
|
|
152
149
|
|
|
153
150
|
this.member.define("pisah", makeBuiltInFunc([petikSymbol, petikSymbol], barisSymbol, (_, [d, sep]) => {
|
|
@@ -229,7 +226,7 @@ class AngkaTipe extends Stipe {
|
|
|
229
226
|
this.member.define("MINUS_UNER",
|
|
230
227
|
makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [r]) => new Value(angkaSymbol, -r.data)));
|
|
231
228
|
|
|
232
|
-
this.member.define("kePetik",
|
|
229
|
+
this.member.define("kePetik",
|
|
233
230
|
makeBuiltInFunc([angkaSymbol], petikSymbol, (v, [a]) => new Value(petikSymbol, kePetik(v, a))));
|
|
234
231
|
|
|
235
232
|
this.member.define("bulat", makeBuiltInFunc([angkaSymbol], angkaSymbol, (_, [a]) => {
|
|
@@ -268,7 +265,7 @@ class LogisTipe extends Stipe {
|
|
|
268
265
|
this.member.define("SERU_UNER",
|
|
269
266
|
makeBuiltInFunc([logisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
270
267
|
|
|
271
|
-
this.member.define("kePetik",
|
|
268
|
+
this.member.define("kePetik",
|
|
272
269
|
makeBuiltInFunc([logisSymbol], petikSymbol, (v, [l]) => new Value(petikSymbol, kePetik(v, l))));
|
|
273
270
|
}
|
|
274
271
|
}
|
|
@@ -324,7 +321,7 @@ class BarisTipe extends Stipe {
|
|
|
324
321
|
this.member.define("SERU_UNER",
|
|
325
322
|
makeBuiltInFunc([barisSymbol], logisSymbol, (_, [r]) => new Value(logisSymbol, !Boolean(r.data))));
|
|
326
323
|
|
|
327
|
-
this.member.define("kePetik",
|
|
324
|
+
this.member.define("kePetik",
|
|
328
325
|
makeBuiltInFunc([barisSymbol], petikSymbol, (v, [p]) => new Value(petikSymbol, kePetik(v, p))));
|
|
329
326
|
|
|
330
327
|
this.member.define("hapus", makeBuiltInFunc([barisSymbol, angkaSymbol], barisSymbol, (v, [b, i]) => {
|
|
@@ -386,7 +383,7 @@ class BarisTipe extends Stipe {
|
|
|
386
383
|
|
|
387
384
|
this.member.define("punya?", makeBuiltInFunc([barisSymbol, null], logisSymbol, (v, [b, d]) => {
|
|
388
385
|
let type = v.environment.get(d.type?.description);
|
|
389
|
-
if (!type)
|
|
386
|
+
if (!type)
|
|
390
387
|
v.error(`Tipe tidak ditemukan atau tidak valid`);
|
|
391
388
|
let equalFunc;
|
|
392
389
|
if (type.member?.has("SAMA_SAMA")) {
|
|
@@ -408,7 +405,7 @@ class MesinTipe extends Stipe {
|
|
|
408
405
|
constructor() {
|
|
409
406
|
super(mesinSymbol);
|
|
410
407
|
|
|
411
|
-
this.member.define("kePetik",
|
|
408
|
+
this.member.define("kePetik",
|
|
412
409
|
makeBuiltInFunc([mesinSymbol], petikSymbol, (v, [m]) => new Value(petikSymbol, kePetik(v, m))));
|
|
413
410
|
}
|
|
414
411
|
}
|
|
@@ -434,7 +431,7 @@ let Model$1 = class Model extends Stipe {
|
|
|
434
431
|
val.type = args[i].type;
|
|
435
432
|
} else if (args[i].type !== symbol) {
|
|
436
433
|
v.line = callLine;
|
|
437
|
-
v.error(`Argumen pembuatan objek tidak sama dengan argumen model, menemukan ${args[i].type?.description}, mengharapkan ${symbol ? symbol.description : "nihil"
|
|
434
|
+
v.error(`Argumen pembuatan objek tidak sama dengan argumen model, menemukan ${args[i].type?.description}, mengharapkan ${symbol ? symbol.description : "nihil"}`);
|
|
438
435
|
}
|
|
439
436
|
val.member = args[i].member;
|
|
440
437
|
obj.member.define(name, val);
|
|
@@ -454,8 +451,7 @@ let Jenis$1 = class Jenis extends Stipe {
|
|
|
454
451
|
this.member.define(thing.lexeme, new Value(sym, idx));
|
|
455
452
|
});
|
|
456
453
|
this.member.define("kePetik", makeBuiltInFunc([sym], petikSymbol, (_, [j]) => {
|
|
457
|
-
|
|
458
|
-
return new Value(petikSymbol, `${name}.${enumName}`);
|
|
454
|
+
return new Value(petikSymbol, `${name}<${j.data}>`);
|
|
459
455
|
}));
|
|
460
456
|
this.init(sym);
|
|
461
457
|
}
|
|
@@ -579,7 +575,7 @@ const GLOBAL_ENV = (() => {
|
|
|
579
575
|
|
|
580
576
|
mtkModul.member.define("kpk", makeBuiltInFunc([angkaSymbol, angkaSymbol], angkaSymbol, (_, [a, b]) => {
|
|
581
577
|
let fpbVal = fpb(a.data, b.data);
|
|
582
|
-
return new Value(angkaSymbol, a.data*b*data/fpbVal);
|
|
578
|
+
return new Value(angkaSymbol, a.data * b * data / fpbVal);
|
|
583
579
|
}));
|
|
584
580
|
|
|
585
581
|
env.define("mtk", mtkModul);
|
|
@@ -601,12 +597,14 @@ const RESERVED_KEYWORDS = [
|
|
|
601
597
|
"datum",
|
|
602
598
|
"jenis",
|
|
603
599
|
"model",
|
|
604
|
-
"error",
|
|
605
600
|
"tetap",
|
|
606
601
|
"modul",
|
|
602
|
+
"lihat",
|
|
603
|
+
"kasus",
|
|
607
604
|
];
|
|
608
605
|
|
|
609
|
-
const
|
|
606
|
+
const
|
|
607
|
+
RUBAH = 0,
|
|
610
608
|
KALAU = 1,
|
|
611
609
|
NAMUN = 2,
|
|
612
610
|
SLAGI = 3,
|
|
@@ -620,35 +618,40 @@ const RUBAH = 0,
|
|
|
620
618
|
DATUM = 11,
|
|
621
619
|
JENIS = 12,
|
|
622
620
|
MODEL = 13,
|
|
623
|
-
TETAP =
|
|
624
|
-
MODUL =
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
621
|
+
TETAP = 14,
|
|
622
|
+
MODUL = 15,
|
|
623
|
+
LIHAT = 16,
|
|
624
|
+
KASUS = 17,
|
|
625
|
+
EOF = 18,
|
|
626
|
+
ID = 19,
|
|
627
|
+
LITERAL = 20,
|
|
628
|
+
PLUS = 21,
|
|
629
|
+
MINUS = 22,
|
|
630
|
+
STAR = 23,
|
|
631
|
+
SLASH = 24,
|
|
632
|
+
LPAREN = 25,
|
|
633
|
+
RPAREN = 26,
|
|
634
|
+
GREATER = 27,
|
|
635
|
+
GREATER_EQUAL = 28,
|
|
636
|
+
LESS = 29,
|
|
637
|
+
LESS_EQUAL = 30,
|
|
638
|
+
EQUAL = 31,
|
|
639
|
+
EQUAL_EQUAL = 32,
|
|
640
|
+
DOT = 33,
|
|
641
|
+
LCURLY = 34,
|
|
642
|
+
RCURLY = 35,
|
|
643
|
+
COMMA = 36,
|
|
644
|
+
LSQUARE = 37,
|
|
645
|
+
RSQUARE = 38,
|
|
646
|
+
PIPE = 39,
|
|
647
|
+
AMPERSAND = 40,
|
|
648
|
+
BANG = 41,
|
|
649
|
+
ARROW = 42,
|
|
650
|
+
BANG_EQUAL = 43,
|
|
651
|
+
MODULUS = 44,
|
|
652
|
+
PIPELINE = 45,
|
|
653
|
+
COLON = 46,
|
|
654
|
+
DOLLAR = 47;
|
|
652
655
|
|
|
653
656
|
const TOKEN_STRING = [
|
|
654
657
|
"RUBAH",
|
|
@@ -665,9 +668,10 @@ const TOKEN_STRING = [
|
|
|
665
668
|
"DATUM",
|
|
666
669
|
"JENIS",
|
|
667
670
|
"MODEL",
|
|
668
|
-
"ERROR",
|
|
669
671
|
"TETAP",
|
|
670
672
|
"MODUL",
|
|
673
|
+
"LIHAT",
|
|
674
|
+
"KASUS",
|
|
671
675
|
"EOF",
|
|
672
676
|
"ID",
|
|
673
677
|
"LITERAL",
|
|
@@ -695,6 +699,9 @@ const TOKEN_STRING = [
|
|
|
695
699
|
"ARROW",
|
|
696
700
|
"SERU_SAMA",
|
|
697
701
|
"MODULUS",
|
|
702
|
+
"PIPELINE",
|
|
703
|
+
"COLON",
|
|
704
|
+
"DOLLAR",
|
|
698
705
|
];
|
|
699
706
|
|
|
700
707
|
let Henti$1 = class Henti { };
|
|
@@ -725,6 +732,7 @@ class Interpreter {
|
|
|
725
732
|
this.output = [];
|
|
726
733
|
this.objectStack = null;
|
|
727
734
|
this.exprWillBeCalled = false;
|
|
735
|
+
this.pipeStack = [];
|
|
728
736
|
}
|
|
729
737
|
|
|
730
738
|
// EXPRESSION VISITORS
|
|
@@ -957,6 +965,14 @@ class Interpreter {
|
|
|
957
965
|
}
|
|
958
966
|
|
|
959
967
|
visitIdentifierExpr(identifierExpr) {
|
|
968
|
+
if (identifierExpr.token.lexeme === "$") {
|
|
969
|
+
this.line = identifierExpr.token.line;
|
|
970
|
+
if (this.pipeStack.length <= 0) {
|
|
971
|
+
this.error(`$ hanya ada dalam ekspresi saluran.`);
|
|
972
|
+
} else {
|
|
973
|
+
return this.pipeStack[this.pipeStack.length - 1];
|
|
974
|
+
}
|
|
975
|
+
}
|
|
960
976
|
let value = this.environment.get(identifierExpr.token.lexeme);
|
|
961
977
|
this.line = identifierExpr.token.line;
|
|
962
978
|
if (!value) this.error(`'${identifierExpr.token.lexeme}' tidak dapat ditemukan.`);
|
|
@@ -987,6 +1003,18 @@ class Interpreter {
|
|
|
987
1003
|
}
|
|
988
1004
|
}
|
|
989
1005
|
|
|
1006
|
+
visitPipeLineExpr (pipeLineExpr) {
|
|
1007
|
+
let expr = this.validValue(pipeLineExpr.expr.accept(this));
|
|
1008
|
+
|
|
1009
|
+
this.pipeStack.push(expr);
|
|
1010
|
+
|
|
1011
|
+
let pipeValue = this.validValue(pipeLineExpr.pipeTo.accept(this));
|
|
1012
|
+
|
|
1013
|
+
this.pipeStack.pop();
|
|
1014
|
+
|
|
1015
|
+
return pipeValue;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
990
1018
|
// STATEMENT VISITORS
|
|
991
1019
|
|
|
992
1020
|
// this is needed for interpreting generics TODO!
|
|
@@ -1177,6 +1205,28 @@ class Interpreter {
|
|
|
1177
1205
|
this.environment.define(name, new Jenis$1(name, jenisStmt.enums));
|
|
1178
1206
|
}
|
|
1179
1207
|
|
|
1208
|
+
visitLihatStmt(lihatStmt) {
|
|
1209
|
+
let match = this.validValue(lihatStmt.expr.accept(this));
|
|
1210
|
+
let matchType = this.environment.get(match?.type?.description);
|
|
1211
|
+
if (!matchType?.member?.has("SAMA_SAMA")) {
|
|
1212
|
+
this.error(`tipe ${matchType ? match.type.description : "nihil"} tidak mempunyai mesin SAMA_SAMA.`);
|
|
1213
|
+
}
|
|
1214
|
+
let equalFunc = matchType.member.get("SAMA_SAMA");
|
|
1215
|
+
|
|
1216
|
+
for (let someCase of lihatStmt.cases) {
|
|
1217
|
+
if (!someCase[0]) {
|
|
1218
|
+
someCase[1].accept(this);
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
let expr = someCase[0].accept(this);
|
|
1222
|
+
let isEqual = this.callFunc(equalFunc.data, [match, expr]);
|
|
1223
|
+
if (isEqual.data) {
|
|
1224
|
+
someCase[1].accept(this);
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1180
1230
|
visitSimplStmt(simpl) {
|
|
1181
1231
|
for (let stmt of simpl.statements) {
|
|
1182
1232
|
stmt.accept(this);
|
|
@@ -1404,6 +1454,17 @@ class Lexer {
|
|
|
1404
1454
|
this.charStart++;
|
|
1405
1455
|
}
|
|
1406
1456
|
|
|
1457
|
+
multilineComment() {
|
|
1458
|
+
this.advance(); this.advance();
|
|
1459
|
+
this.charStart = this.charStart + 2;
|
|
1460
|
+
while (!this.isAtEnd() && (this.see() !== '*' || this.peek() !== '/')) {
|
|
1461
|
+
this.advance();
|
|
1462
|
+
this.charStart++;
|
|
1463
|
+
}
|
|
1464
|
+
this.advance(); this.advance();
|
|
1465
|
+
this.charStart = this.charStart + 2;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1407
1468
|
makeToken(type) {
|
|
1408
1469
|
this.advance();
|
|
1409
1470
|
return new Token(type, this.parseLexeme(), null, this.lineIndex);
|
|
@@ -1411,8 +1472,9 @@ class Lexer {
|
|
|
1411
1472
|
|
|
1412
1473
|
scan() {
|
|
1413
1474
|
this.skipWhitespaces();
|
|
1414
|
-
while (this.see() === '#') {
|
|
1415
|
-
this.comment();
|
|
1475
|
+
while (this.see() === '#' || (this.see() === '/' && this.peek() === '*')) {
|
|
1476
|
+
if (this.see() === '#') this.comment();
|
|
1477
|
+
else this.multilineComment();
|
|
1416
1478
|
this.skipWhitespaces();
|
|
1417
1479
|
}
|
|
1418
1480
|
|
|
@@ -1421,6 +1483,8 @@ class Lexer {
|
|
|
1421
1483
|
if (this.isNumeric(this.see())) return this.number();
|
|
1422
1484
|
|
|
1423
1485
|
switch (this.see()) {
|
|
1486
|
+
case "$": return this.makeToken(DOLLAR);
|
|
1487
|
+
case ":": return this.makeToken(COLON);
|
|
1424
1488
|
case "+": return this.makeToken(PLUS);
|
|
1425
1489
|
case "-": return this.makeToken(MINUS);
|
|
1426
1490
|
case "/": return this.makeToken(SLASH);
|
|
@@ -1433,7 +1497,12 @@ class Lexer {
|
|
|
1433
1497
|
case "}": return this.makeToken(RCURLY);
|
|
1434
1498
|
case "[": return this.makeToken(LSQUARE);
|
|
1435
1499
|
case "]": return this.makeToken(RSQUARE);
|
|
1436
|
-
case "|":
|
|
1500
|
+
case "|":
|
|
1501
|
+
if (this.peek() === ">") {
|
|
1502
|
+
this.advance();
|
|
1503
|
+
return this.makeToken(PIPELINE);
|
|
1504
|
+
}
|
|
1505
|
+
return this.makeToken(PIPE);
|
|
1437
1506
|
case "&": return this.makeToken(AMPERSAND);
|
|
1438
1507
|
case "%": return this.makeToken(MODULUS);
|
|
1439
1508
|
case "!":
|
|
@@ -1618,6 +1687,19 @@ class Index extends ExprBase {
|
|
|
1618
1687
|
visit(visitor) {
|
|
1619
1688
|
return visitor.visitIndexExpr(this);
|
|
1620
1689
|
}
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
class PipeLine extends ExprBase {
|
|
1693
|
+
// Expr.ExprBase expr, Expr.ExprBase pipeTo
|
|
1694
|
+
constructor(expr, pipeTo) {
|
|
1695
|
+
super();
|
|
1696
|
+
this.expr = expr;
|
|
1697
|
+
this.pipeTo = pipeTo;
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
visit(visitor) {
|
|
1701
|
+
return visitor.visitPipeLineExpr(this);
|
|
1702
|
+
}
|
|
1621
1703
|
}
|
|
1622
1704
|
|
|
1623
1705
|
class StmtBase {
|
|
@@ -1790,6 +1872,19 @@ class Jenis extends StmtBase {
|
|
|
1790
1872
|
}
|
|
1791
1873
|
}
|
|
1792
1874
|
|
|
1875
|
+
class Lihat extends StmtBase {
|
|
1876
|
+
// Expr.ExprBase expr, Array<Expr.ExprBase-Stmt.Block> cases
|
|
1877
|
+
constructor(expr, cases) {
|
|
1878
|
+
super();
|
|
1879
|
+
this.expr = expr;
|
|
1880
|
+
this.cases = cases;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
visit(visitor) {
|
|
1884
|
+
return visitor.visitLihatStmt(this);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1793
1888
|
class Model extends StmtBase {
|
|
1794
1889
|
// Token name, Array<Stmt.Type-Token> contents
|
|
1795
1890
|
constructor(name, contents) {
|
|
@@ -1877,6 +1972,10 @@ class Parser {
|
|
|
1877
1972
|
}
|
|
1878
1973
|
|
|
1879
1974
|
blockStmt() {
|
|
1975
|
+
if (this.match(COLON)) {
|
|
1976
|
+
return new Block([this.statement()]);
|
|
1977
|
+
}
|
|
1978
|
+
this.eat(LCURLY, `Mengharapkan sebuah blok.`);
|
|
1880
1979
|
let statements = [];
|
|
1881
1980
|
while (!this.match(RCURLY)) {
|
|
1882
1981
|
statements.push(this.statement());
|
|
@@ -1901,25 +2000,25 @@ class Parser {
|
|
|
1901
2000
|
|
|
1902
2001
|
lambda() {
|
|
1903
2002
|
let params = [];
|
|
1904
|
-
this.eat(LPAREN, "Mengharapkan '(' setelah '=>' untuk deklarasi
|
|
2003
|
+
this.eat(LPAREN, "Mengharapkan '(' setelah '=>' untuk deklarasi objek `mesin`.");
|
|
1905
2004
|
|
|
1906
2005
|
if (this.match(ID, DATUM)) {
|
|
1907
2006
|
let type = this.typeStmt();
|
|
1908
|
-
this.eat(ID, "Mengharapkan Nama parameter setelah deklarasi Tipe parameter dalam
|
|
2007
|
+
this.eat(ID, "Mengharapkan Nama parameter setelah deklarasi Tipe parameter dalam objek `mesin`.");
|
|
1909
2008
|
let name = this.previous();
|
|
1910
2009
|
params.push([type, name]);
|
|
1911
2010
|
|
|
1912
2011
|
while (this.match(COMMA)) {
|
|
1913
2012
|
if (!this.match(ID, DATUM))
|
|
1914
|
-
this.error("Mengharapkan Tipe parameter setelah koma dalam
|
|
2013
|
+
this.error("Mengharapkan Tipe parameter setelah koma dalam objek `mesin`.");
|
|
1915
2014
|
let type = this.typeStmt();
|
|
1916
|
-
this.eat(ID, "Mengharapkan Nama parameter setelah deklarasi Tipe parameter dalam
|
|
2015
|
+
this.eat(ID, "Mengharapkan Nama parameter setelah deklarasi Tipe parameter dalam objek `mesin`.");
|
|
1917
2016
|
let name = this.previous();
|
|
1918
2017
|
params.push([type, name]);
|
|
1919
2018
|
}
|
|
1920
2019
|
}
|
|
1921
2020
|
// deepPrint(params);
|
|
1922
|
-
this.eat(RPAREN, "Mengharapkan ')' setelah deklarasi parameter
|
|
2021
|
+
this.eat(RPAREN, "Mengharapkan ')' setelah deklarasi parameter objek `mesin`.");
|
|
1923
2022
|
let returnType = null;
|
|
1924
2023
|
if (this.match(ID, DATUM)) {
|
|
1925
2024
|
returnType = this.typeStmt();
|
|
@@ -1929,7 +2028,6 @@ class Parser {
|
|
|
1929
2028
|
}
|
|
1930
2029
|
returnType = null;
|
|
1931
2030
|
}
|
|
1932
|
-
this.eat(LCURLY, "Mengharapkan Blok { } untuk Lamda.");
|
|
1933
2031
|
let block = this.blockStmt();
|
|
1934
2032
|
|
|
1935
2033
|
return new Lambda(params, returnType, block);
|
|
@@ -1967,7 +2065,7 @@ class Parser {
|
|
|
1967
2065
|
return new Grouping(expr);
|
|
1968
2066
|
} else if (this.match(LITERAL)) {
|
|
1969
2067
|
return new Literal(this.previous());
|
|
1970
|
-
} else if (this.match(ID)) {
|
|
2068
|
+
} else if (this.match(ID, DOLLAR)) {
|
|
1971
2069
|
return this.identifier();
|
|
1972
2070
|
} else if (this.match(ARROW)) {
|
|
1973
2071
|
return this.lambda();
|
|
@@ -2011,7 +2109,7 @@ class Parser {
|
|
|
2011
2109
|
}
|
|
2012
2110
|
|
|
2013
2111
|
member(parent) {
|
|
2014
|
-
this.eat(ID, "Mengharapkan Nama
|
|
2112
|
+
this.eat(ID, "Mengharapkan Nama variabel setelah '.'.");
|
|
2015
2113
|
let id = this.identifier();
|
|
2016
2114
|
return new Member(parent, id);
|
|
2017
2115
|
}
|
|
@@ -2076,8 +2174,19 @@ class Parser {
|
|
|
2076
2174
|
return expr;
|
|
2077
2175
|
}
|
|
2078
2176
|
|
|
2177
|
+
pipeLine() {
|
|
2178
|
+
let expr = this.orTerm();
|
|
2179
|
+
|
|
2180
|
+
while (this.match(PIPELINE)) {
|
|
2181
|
+
let pipeTo = this.orTerm();
|
|
2182
|
+
expr = new PipeLine(expr, pipeTo);
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
return expr;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2079
2188
|
expression() {
|
|
2080
|
-
return this.
|
|
2189
|
+
return this.pipeLine();
|
|
2081
2190
|
}
|
|
2082
2191
|
|
|
2083
2192
|
cetakStmt() {
|
|
@@ -2135,19 +2244,16 @@ class Parser {
|
|
|
2135
2244
|
this.error("Mengharapkan ekspresi setelah 'kalau'.");
|
|
2136
2245
|
}
|
|
2137
2246
|
let condition = this.expression();
|
|
2138
|
-
this.eat(LCURLY, "Mengharapkan blok { } setelah kondisi untuk pernyataan 'kalau'.");
|
|
2139
2247
|
let block = this.blockStmt();
|
|
2140
2248
|
let elseKalau = null;
|
|
2141
2249
|
|
|
2142
2250
|
if (this.match(NAMUN)) {
|
|
2143
2251
|
if (this.match(KALAU)) {
|
|
2144
2252
|
elseKalau = this.kalauStmt();
|
|
2145
|
-
} else
|
|
2253
|
+
} else {
|
|
2146
2254
|
let elseCond = null;
|
|
2147
2255
|
let elseBlock = this.blockStmt();
|
|
2148
2256
|
elseKalau = new Kalau(elseCond, elseBlock);
|
|
2149
|
-
} else {
|
|
2150
|
-
this.error("Mengharapkan sebuah 'kalau' atau blok { } setelah 'namun'.");
|
|
2151
2257
|
}
|
|
2152
2258
|
}
|
|
2153
2259
|
|
|
@@ -2165,7 +2271,6 @@ class Parser {
|
|
|
2165
2271
|
|
|
2166
2272
|
let iterable = this.expression();
|
|
2167
2273
|
|
|
2168
|
-
this.eat(LCURLY, "Mengharapkan Blok { } setelah kondisi pada pernyataan 'untuk'.");
|
|
2169
2274
|
let block = this.blockStmt();
|
|
2170
2275
|
|
|
2171
2276
|
return new Untuk(varType, varName, iterable, block);
|
|
@@ -2174,7 +2279,6 @@ class Parser {
|
|
|
2174
2279
|
slagiStmt() {
|
|
2175
2280
|
let condition = this.expression();
|
|
2176
2281
|
|
|
2177
|
-
this.eat(LCURLY, "Mengharapkan Blok { } setelah kondisi pada pernyataan 'slagi'.");
|
|
2178
2282
|
let block = this.blockStmt();
|
|
2179
2283
|
|
|
2180
2284
|
return new Slagi(condition, block);
|
|
@@ -2217,6 +2321,23 @@ class Parser {
|
|
|
2217
2321
|
return new Jenis(id, enums);
|
|
2218
2322
|
}
|
|
2219
2323
|
|
|
2324
|
+
lihatStmt() {
|
|
2325
|
+
let expr = this.expression();
|
|
2326
|
+
let cases = [];
|
|
2327
|
+
if (!this.check(KASUS)) {
|
|
2328
|
+
this.error("Mengharapkan `kasus` setelah ekspresi dalam `lihat`.");
|
|
2329
|
+
}
|
|
2330
|
+
while (this.match(KASUS)) {
|
|
2331
|
+
cases.push([this.expression(), this.blockStmt()]);
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
if (this.match(NAMUN)) {
|
|
2335
|
+
cases.push([null, this.blockStmt()]);
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
return new Lihat(expr, cases);
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2220
2341
|
modelStmt() {
|
|
2221
2342
|
this.eat(ID, "Mengharapkan Nama Model setelah 'model'.");
|
|
2222
2343
|
let id = this.previous();
|
|
@@ -2229,9 +2350,9 @@ class Parser {
|
|
|
2229
2350
|
let contents = [];
|
|
2230
2351
|
do {
|
|
2231
2352
|
if (!this.match(ID, DATUM))
|
|
2232
|
-
this.error("Mengharapkan Tipe
|
|
2353
|
+
this.error("Mengharapkan Tipe variabel dalam deklarasi 'Model'.");
|
|
2233
2354
|
let type = this.typeStmt();
|
|
2234
|
-
this.eat(ID, "Mengharapkan Nama
|
|
2355
|
+
this.eat(ID, "Mengharapkan Nama variabel dalam deklarasi 'model'.");
|
|
2235
2356
|
let memberName = this.previous();
|
|
2236
2357
|
|
|
2237
2358
|
contents.push([type, memberName]);
|
|
@@ -2245,12 +2366,8 @@ class Parser {
|
|
|
2245
2366
|
modulStmt() {
|
|
2246
2367
|
this.eat(ID, "Mengharapkan Nama modul setelah deklarasi.");
|
|
2247
2368
|
let token = this.previous();
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
while (!this.match(RCURLY)) {
|
|
2251
|
-
statements.push(this.statement());
|
|
2252
|
-
}
|
|
2253
|
-
return new Modul(token, statements);
|
|
2369
|
+
let block = this.blockStmt();
|
|
2370
|
+
return new Modul(token, block.statements);
|
|
2254
2371
|
}
|
|
2255
2372
|
|
|
2256
2373
|
statement() {
|
|
@@ -2262,7 +2379,7 @@ class Parser {
|
|
|
2262
2379
|
return new Kerja(this.expression());
|
|
2263
2380
|
} else if (this.match(KALAU)) {
|
|
2264
2381
|
return this.kalauStmt();
|
|
2265
|
-
} else if (this.
|
|
2382
|
+
} else if (this.check(LCURLY)) {
|
|
2266
2383
|
return this.blockStmt();
|
|
2267
2384
|
} else if (this.match(UNTUK)) {
|
|
2268
2385
|
return this.untukStmt();
|
|
@@ -2278,6 +2395,8 @@ class Parser {
|
|
|
2278
2395
|
return new Hasil(this.expression());
|
|
2279
2396
|
} else if (this.match(JENIS)) {
|
|
2280
2397
|
return this.jenisStmt();
|
|
2398
|
+
} else if (this.match(LIHAT)) {
|
|
2399
|
+
return this.lihatStmt();
|
|
2281
2400
|
} else if (this.match(MODEL)) {
|
|
2282
2401
|
return this.modelStmt();
|
|
2283
2402
|
} else if (this.match(MODUL)) {
|