@@ -4,7 +4,8 @@ const reserved = [
4
4
"print" ,
5
5
//"input",
6
6
"if" , "else" , "elseif" , "endif" ,
7
- "for" , "to" , "step" , "next" , "while" , "do" , "until" , "break" ,
7
+ //"for", "to", "step", "next", "while", "do", "until", "break",
8
+ "loop" , "next" , "break" ,
8
9
"function" , "return" , "end" ,
9
10
//"and", "or", "not",
10
11
"nor" ,
@@ -210,70 +211,33 @@ export class Nor {
210
211
backToken ( token ) {
211
212
this . p = token . pos ;
212
213
}
213
- getExpression1 ( ) {
214
- let res = this . getValue ( ) ;
215
- for ( ; ; ) {
216
- const op = this . getToken ( ) ;
217
- if ( op . type != "operator" || (
218
- op . operator != "nor" &&
219
- op . operator != "*" &&
220
- op . operator != "/" &&
221
- op . operator != "%" &&
222
- op . operator != "//"
223
- ) ) {
224
- this . backToken ( op ) ;
225
- return res ;
226
- }
227
- const v2 = this . getValue ( ) ;
228
- const o = op . operator ;
229
- if ( o != "nor" && o != "*" && o != "/" && o != "%" && o != "//" ) {
230
- //throw new Error("非対応の演算子が使われています: " + o);
231
- throw new Error ( "illegal operator: " + o ) ;
232
- }
233
- res = {
234
- type : "BinaryExpression" ,
235
- left : res ,
236
- operator : o ,
237
- right : v2 ,
238
- } ;
239
- }
240
- }
241
214
getExpression ( ) {
242
- let res = this . getExpression1 ( ) ;
215
+ let res = this . getValue ( ) ; //this. getExpression1();
243
216
for ( ; ; ) {
244
217
const op = this . getToken ( ) ;
245
218
if ( op . type != "operator" || op . operator == "," ) {
246
219
this . backToken ( op ) ;
247
220
return res ;
248
221
}
249
- const v2 = this . getExpression1 ( ) ;
250
- if ( op . operator == "+ " ) {
222
+ const v2 = this . getValue ( ) ; // this. getExpression1();
223
+ if ( op . operator == "nor " ) {
251
224
res = {
252
225
type : "BinaryExpression" ,
253
226
left : res ,
254
- operator : "+ " ,
227
+ operator : "nor " ,
255
228
right : v2 ,
256
229
} ;
257
230
} else {
258
- if ( typeof res == "string" || typeof v2 == "string" ) {
259
- //throw new Error("文字列では使用できない演算子です");
260
- throw new Error ( "this operator can not use for string" ) ;
261
- }
262
- if ( op . operator == "-" ) {
263
- res = {
264
- type : "BinaryExpression" ,
265
- left : res ,
266
- operator : "-" ,
267
- right : v2 ,
268
- } ;
269
- } else {
270
- //throw new Error("未対応の演算子です : " + op.operator);
271
- this . backToken ( op ) ;
272
- return res ;
273
- }
231
+ //throw new Error("未対応の演算子です : " + op.operator);
232
+ throw new Error ( "unsupported operator : " + op . operator ) ;
233
+ //this.backToken(op);
234
+ return res ;
274
235
}
275
236
}
276
237
}
238
+ getCondition ( ) {
239
+ return this . getExpression ( ) ;
240
+ }
277
241
getValue ( ) {
278
242
const t1 = this . getToken ( ) ;
279
243
if ( t1 . type == "(" ) {
@@ -344,120 +308,11 @@ export class Nor {
344
308
} ,
345
309
arguments : args ,
346
310
} ;
347
-
348
- /*
349
- } else if (t1.operator == "-") {
350
- const t2 = this.getToken();
351
- if (t2.type == "num") {
352
- return {
353
- type: "Literal",
354
- value: -t2.value,
355
- };
356
- } else {
357
- throw new Error("式ではないものが指定されています : " + t1.type);
358
- }
359
- */
360
311
} else {
361
312
//throw new Error("式ではないものが指定されています : " + t1.type);
362
313
throw new Error ( "illegal expression: " + t1 . type ) ;
363
314
}
364
315
}
365
- getConditionValue1 ( ) {
366
- const t1 = this . getToken ( ) ;
367
- if ( t1 . type == "(" ) {
368
- const res = this . getCondition ( ) ;
369
- const t2 = this . getToken ( ) ;
370
- if ( t2 . type != ")" ) {
371
- //throw new Error("カッコが閉じられていません");
372
- throw new Error ( "missing blacket close" ) ;
373
- }
374
- return res ;
375
- } else {
376
- this . backToken ( t1 ) ;
377
- }
378
- //const v1 = this.getValue();
379
- const v1 = this . getExpression ( ) ;
380
- const op = this . getToken ( ) ;
381
- if ( op . type != "operator" ) {
382
- this . backToken ( op ) ;
383
- return v1 ;
384
- }
385
- //const v2 = this.getValue();
386
- const v2 = this . getExpression ( ) ;
387
- if ( [ "==" , "!=" , ">" , "<" , ">=" , ">=" , "<=" ] . indexOf ( op . operator ) == - 1 ) {
388
- //throw new Error("条件式で未対応の演算子です : " + op.operator);
389
- throw new Error ( "illegal operator in condition : " + op . operator ) ;
390
- }
391
- return {
392
- type : "BinaryExpression" ,
393
- left : v1 ,
394
- operator : op . operator ,
395
- right : v2 ,
396
- } ;
397
- }
398
- getConditionValue ( ) {
399
- const chknot = this . getToken ( ) ;
400
- let flg = true ;
401
- if ( chknot . type == "not" ) {
402
- flg = false ;
403
- } else {
404
- this . backToken ( chknot ) ;
405
- }
406
- const n = this . getConditionValue1 ( ) ;
407
- if ( flg ) {
408
- return n ;
409
- } else {
410
- return {
411
- type : "UnaryExpression" ,
412
- operator : "not" ,
413
- argument : n ,
414
- } ;
415
- }
416
- }
417
- getConditionAnd ( ) {
418
- let res = this . getConditionValue ( ) ;
419
- for ( ; ; ) {
420
- const op = this . getToken ( ) ;
421
- if ( op . type != "and" ) {
422
- this . backToken ( op ) ;
423
- return res ;
424
- }
425
- const v2 = this . getConditionValue ( ) ;
426
- if ( op . type == "and" ) {
427
- res = {
428
- type : "BinaryExpression" ,
429
- left : res ,
430
- operator : "and" ,
431
- right : v2 ,
432
- } ;
433
- } else {
434
- //throw new Error("未対応の演算子です : " + op.operator);
435
- throw new Error ( "illegal operator : " + op . operator ) ;
436
- }
437
- }
438
- }
439
- getCondition ( ) {
440
- let res = this . getConditionAnd ( ) ;
441
- for ( ; ; ) {
442
- const op = this . getToken ( ) ;
443
- if ( op . type != "or" ) {
444
- this . backToken ( op ) ;
445
- return res ;
446
- }
447
- const v2 = this . getConditionAnd ( ) ;
448
- if ( op . type == "or" ) {
449
- res = {
450
- type : "BinaryExpression" ,
451
- left : res ,
452
- operator : "or" ,
453
- right : v2 ,
454
- } ;
455
- } else {
456
- //throw new Error("未対応の演算子です : " + op.operator);
457
- throw new Error ( "illegal operator : " + op . operator ) ;
458
- }
459
- }
460
- }
461
316
getVar ( name ) {
462
317
let op = this . getToken ( ) ;
463
318
@@ -505,7 +360,7 @@ export class Nor {
505
360
}
506
361
parseCommand ( body , forcetoken ) {
507
362
const token = forcetoken || this . getToken ( ) ;
508
- // console.log("parseCommand", token);
363
+ console . log ( "parseCommand" , token ) ;
509
364
if ( token . type == "eof" ) return false ;
510
365
if ( BLACKET_MODE ) {
511
366
if ( token . type == "}" ) {
@@ -734,6 +589,33 @@ export class Nor {
734
589
alternate : null ,
735
590
} ) ;
736
591
}
592
+ } else if ( token . type == "loop" ) {
593
+ if ( BLACKET_MODE ) {
594
+ const tthen = this . getToken ( ) ;
595
+ if ( tthen . type != "{" ) throw new Error ( `loop文の後に"{"がありません` ) ;
596
+ }
597
+ const then = [ ] ;
598
+ for ( ; ; ) {
599
+ if ( ! this . parseCommand ( then ) ) {
600
+ const endblacket = this . getToken ( ) ;
601
+ if ( BLACKET_MODE ) {
602
+ if ( endblacket . type != "}" ) throw new Error ( `loop文が"}"で閉じられていません` ) ;
603
+ } else {
604
+ if ( endblacket . type != "next" ) throw new Error ( `loop must have next` ) ;
605
+ }
606
+ break ;
607
+ }
608
+ }
609
+ body . push ( {
610
+ type : "ForStatement" ,
611
+ init : null ,
612
+ test : null ,
613
+ update : null ,
614
+ body : {
615
+ type : "BlockStatement" ,
616
+ body : then ,
617
+ }
618
+ } ) ;
737
619
} else if ( token . type == "while" ) {
738
620
const cond = this . getCondition ( ) ;
739
621
//console.log("tthen", tthen);
@@ -985,10 +867,24 @@ export class Nor {
985
867
if ( c . type == "eof" ) break ;
986
868
}
987
869
}
870
+ binarray2int ( a ) {
871
+ let res = 0 ;
872
+ let m = 0 ;
873
+ for ( let i = a . length - 1 ; i >= 0 ; i -- ) {
874
+ res += a [ i ] << m ;
875
+ m ++ ;
876
+ }
877
+ return res ;
878
+ }
988
879
getArrayIndex ( ast , scope ) {
989
880
const prop = this . calcExpression ( ast , scope ) ;
990
- if ( prop < 0 || typeof prop == "string" && parseInt ( prop ) . toString ( ) != prop ) {
991
- throw new Error ( "配列には0または正の整数のみ指定可能です" ) ;
881
+ if ( typeof prop == "number" ) return prop ;
882
+ if ( Array . isArray ( prop ) ) {
883
+ return this . binarray2int ( prop ) ;
884
+ } else {
885
+ //if (prop < 0 || typeof prop == "string" && parseInt(prop).toString() != prop) {
886
+ //throw new Error("配列には0または正の整数のみ指定可能です");
887
+ throw new Error ( "array index must be number or binary array of numbers" ) ;
992
888
}
993
889
return prop ;
994
890
}
@@ -1082,13 +978,19 @@ export class Nor {
1082
978
}
1083
979
}
1084
980
} else if ( cmd . type == "ForStatement" ) {
1085
- this . runBlock ( cmd . init , scope ) ;
981
+ if ( cmd . init ) {
982
+ this . runBlock ( cmd . init , scope ) ;
983
+ }
1086
984
try {
1087
985
for ( let i = 0 ; ; i ++ ) {
1088
- const cond = this . calcExpression ( cmd . test , scope ) ;
1089
- if ( ! cond ) break ;
986
+ if ( cmd . test ) {
987
+ const cond = this . calcExpression ( cmd . test , scope ) ;
988
+ if ( ! cond ) break ;
989
+ }
1090
990
this . runBlock ( cmd . body , scope ) ;
1091
- this . runBlock ( cmd . update , scope ) ;
991
+ if ( cmd . update ) {
992
+ this . runBlock ( cmd . update , scope ) ;
993
+ }
1092
994
if ( i >= MAX_LOOP ) {
1093
995
throw new Error ( MAX_LOOP + "回の繰り返し上限に達しました" ) ;
1094
996
}
@@ -1148,57 +1050,17 @@ export class Nor {
1148
1050
} else {
1149
1051
return v [ idx ] ;
1150
1052
}
1151
- } else if ( ast . type == "UnaryExpression" ) {
1152
- const n = this . calcExpression ( ast . argument , scope ) ;
1153
- if ( ast . operator == "not" ) {
1154
- return ! n ;
1155
- } else if ( ast . operator == "-" ) {
1156
- return - n ;
1157
- } else {
1158
- throw new Error ( "対応していない演算子 " + ast . operator + " です" ) ;
1159
- }
1160
1053
} else if ( ast . type == "ArrayExpression" ) {
1161
1054
const ar = ast . elements . map ( i => this . calcExpression ( i , scope ) ) ;
1162
1055
return ar ;
1163
1056
} else if ( ast . type == "BinaryExpression" || ast . type == "LogicalExpression" ) {
1164
1057
const n = this . calcExpression ( ast . left , scope ) ;
1165
1058
const m = this . calcExpression ( ast . right , scope ) ;
1166
1059
const op = ast . operator ;
1167
- if ( typeof n == "string" || typeof m == "string" ) {
1168
- if ( op != "+" && op != "==" && op != "!=" ) throw new Error ( "文字列では使用できない演算子です: " + op ) ;
1169
- }
1170
1060
if ( op == "nor" ) {
1171
1061
return n || m ? 0 : 1 ;
1172
- } else if ( op == "+" ) {
1173
- return n + m ;
1174
- } else if ( op == "-" ) {
1175
- return n - m ;
1176
- } else if ( op == "*" ) {
1177
- return n * m ;
1178
- } else if ( op == "/" ) {
1179
- return n / m ;
1180
- } else if ( op == "%" ) {
1181
- return n % m ;
1182
- } else if ( op == "//" ) {
1183
- return Math . floor ( n / m ) ;
1184
- } else if ( op == "==" ) {
1185
- return n == m ;
1186
- } else if ( op == "!=" ) {
1187
- return n != m ;
1188
- } else if ( op == "<" ) {
1189
- return n < m ;
1190
- } else if ( op == "<=" ) {
1191
- return n <= m ;
1192
- } else if ( op == ">" ) {
1193
- return n > m ;
1194
- } else if ( op == ">=" ) {
1195
- return n >= m ;
1196
- } else if ( op == "and" ) {
1197
- return n && m ;
1198
- } else if ( op == "or" ) {
1199
- return n || m ;
1200
1062
} else {
1201
- throw new Error ( "対応していない演算子が使われました" ) ;
1063
+ throw new Error ( "unsupported operator : " + op ) ;
1202
1064
}
1203
1065
} else if ( ast . type == "CallExpression" ) {
1204
1066
const name = ast . callee . name ;
0 commit comments