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.
@@ -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 '"' + thing.data + '"';
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
- let enumName = enums.map(thing=>thing.lexeme)[j.data];
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 RUBAH = 0,
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 = 15,
624
- MODUL = 16,
625
- EOF = 17,
626
- ID = 18,
627
- LITERAL = 19,
628
- PLUS = 20,
629
- MINUS = 21,
630
- STAR = 22,
631
- SLASH = 23,
632
- LPAREN = 24,
633
- RPAREN = 25,
634
- GREATER = 26,
635
- GREATER_EQUAL = 27,
636
- LESS = 28,
637
- LESS_EQUAL = 29,
638
- EQUAL = 30,
639
- EQUAL_EQUAL = 31,
640
- DOT = 32,
641
- LCURLY = 33,
642
- RCURLY = 34,
643
- COMMA = 35,
644
- LSQUARE = 36,
645
- RSQUARE = 37,
646
- PIPE = 38,
647
- AMPERSAND = 39,
648
- BANG = 40,
649
- ARROW = 41,
650
- BANG_EQUAL = 42,
651
- MODULUS = 43;
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 "|": return this.makeToken(PIPE);
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 Lamda.");
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 Lamda.");
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 Lamda.");
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 Lamda.");
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 Lamda.");
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 member setelah '.'.");
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.orTerm();
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 if (this.match(LCURLY)) {
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 member dalam deklarasi 'Model'.");
2353
+ this.error("Mengharapkan Tipe variabel dalam deklarasi 'Model'.");
2233
2354
  let type = this.typeStmt();
2234
- this.eat(ID, "Mengharapkan Nama member dalam deklarasi 'model'.");
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
- this.eat(LCURLY, "Mengharapkan '{' setelah Nama modul.");
2249
- let statements = [];
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.match(LCURLY)) {
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)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bahasa-simpl",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Simpl: Indonesian Mini Programming Language interpreter",
5
5
  "main": "./dist/simpl-interpreter.js",
6
6
  "scripts": {