Skip to content

Commit 593f096

Browse files
committed
remove other operators, for / while / until
1 parent 08ebd4f commit 593f096

File tree

9 files changed

+129
-412
lines changed

9 files changed

+129
-412
lines changed

Nor.js

+68-206
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ const reserved = [
44
"print",
55
//"input",
66
"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",
89
"function", "return", "end",
910
//"and", "or", "not",
1011
"nor",
@@ -210,70 +211,33 @@ export class Nor {
210211
backToken(token) {
211212
this.p = token.pos;
212213
}
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-
}
241214
getExpression() {
242-
let res = this.getExpression1();
215+
let res = this.getValue(); //this.getExpression1();
243216
for (;;) {
244217
const op = this.getToken();
245218
if (op.type != "operator" || op.operator == ",") {
246219
this.backToken(op);
247220
return res;
248221
}
249-
const v2 = this.getExpression1();
250-
if (op.operator == "+") {
222+
const v2 = this.getValue(); // this.getExpression1();
223+
if (op.operator == "nor") {
251224
res = {
252225
type: "BinaryExpression",
253226
left: res,
254-
operator: "+",
227+
operator: "nor",
255228
right: v2,
256229
};
257230
} 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;
274235
}
275236
}
276237
}
238+
getCondition() {
239+
return this.getExpression();
240+
}
277241
getValue() {
278242
const t1 = this.getToken();
279243
if (t1.type == "(") {
@@ -344,120 +308,11 @@ export class Nor {
344308
},
345309
arguments: args,
346310
};
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-
*/
360311
} else {
361312
//throw new Error("式ではないものが指定されています : " + t1.type);
362313
throw new Error("illegal expression: " + t1.type);
363314
}
364315
}
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-
}
461316
getVar(name) {
462317
let op = this.getToken();
463318

@@ -505,7 +360,7 @@ export class Nor {
505360
}
506361
parseCommand(body, forcetoken) {
507362
const token = forcetoken || this.getToken();
508-
//console.log("parseCommand", token);
363+
console.log("parseCommand", token);
509364
if (token.type == "eof") return false;
510365
if (BLACKET_MODE) {
511366
if (token.type == "}") {
@@ -734,6 +589,33 @@ export class Nor {
734589
alternate: null,
735590
});
736591
}
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+
});
737619
} else if (token.type == "while") {
738620
const cond = this.getCondition();
739621
//console.log("tthen", tthen);
@@ -985,10 +867,24 @@ export class Nor {
985867
if (c.type == "eof") break;
986868
}
987869
}
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+
}
988879
getArrayIndex(ast, scope) {
989880
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");
992888
}
993889
return prop;
994890
}
@@ -1082,13 +978,19 @@ export class Nor {
1082978
}
1083979
}
1084980
} else if (cmd.type == "ForStatement") {
1085-
this.runBlock(cmd.init, scope);
981+
if (cmd.init) {
982+
this.runBlock(cmd.init, scope);
983+
}
1086984
try {
1087985
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+
}
1090990
this.runBlock(cmd.body, scope);
1091-
this.runBlock(cmd.update, scope);
991+
if (cmd.update) {
992+
this.runBlock(cmd.update, scope);
993+
}
1092994
if (i >= MAX_LOOP) {
1093995
throw new Error(MAX_LOOP + "回の繰り返し上限に達しました");
1094996
}
@@ -1148,57 +1050,17 @@ export class Nor {
11481050
} else {
11491051
return v[idx];
11501052
}
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-
}
11601053
} else if (ast.type == "ArrayExpression") {
11611054
const ar = ast.elements.map(i => this.calcExpression(i, scope));
11621055
return ar;
11631056
} else if (ast.type == "BinaryExpression" || ast.type == "LogicalExpression") {
11641057
const n = this.calcExpression(ast.left, scope);
11651058
const m = this.calcExpression(ast.right, scope);
11661059
const op = ast.operator;
1167-
if (typeof n == "string" || typeof m == "string") {
1168-
if (op != "+" && op != "==" && op != "!=") throw new Error("文字列では使用できない演算子です: " + op);
1169-
}
11701060
if (op == "nor") {
11711061
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;
12001062
} else {
1201-
throw new Error("対応していない演算子が使われました");
1063+
throw new Error("unsupported operator : " + op);
12021064
}
12031065
} else if (ast.type == "CallExpression") {
12041066
const name = ast.callee.name;

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ deno -A https://code4fukui.github.io/Nor/cli.js examples/add.nor
2626

2727
## 1. Variables and Values
2828

29-
A variable name consists of alphanumeric characters starting with a letter, along with underscores (_) or local characters. However, reserved words (such as print, input, and, or, not, if, else, elseif, endif, for, to, step, next, do, while, until, break, function, end, return) cannot be used as variable names.
29+
A variable name consists of alphanumeric characters starting with a letter, along with underscores (_) or local characters. However, reserved words (such as nor, print, input, if, else, elseif, endif, loop, break, function, end, return) cannot be used as variable names.
3030

3131
- ex: n, sum, points
3232

0 commit comments

Comments
 (0)