言語仕様
– 文字列
– 整数123, 実数123.4
– グローバル変数、変数の値の参照
– 代入演算子(=)
– print関数でカンマ区切りで複数の引数指定
– 複数文は、セミコロンで区切る
– // から行末まではコメント
– 足し算、引き算
– 掛け算、割り算
### source.3
a = 1.24 / 2 - 1;
print("a = 1.24 / 2 - 1 = ", a);
b = 5 - 2 * 3;
print("b = 5 - 2 * 3 = ", b);
### parse.js
module.exports = parser;
var {expect, accept, show, error} = require("./utils.js");
var tokens;
function parser(t){
tokens = t;
var ast = semi();
if(tokens.length>0){
show("ast=", ast);
show("処理後tokens =", tokens);
error("tokensが余っています。");
}
return ast;
}
function value(){
if(tokens.length == 0) return;
return tokens.shift();
}
function funccall(){
var left = value();
var op;
while(op = accept(tokens, "(")){
var right = comma();
op += expect(tokens, ")");
left = {left, op, right};
}
return left;
}
function mul(){
var left = funccall();
var op;
while(op = accept(tokens,"*","/")){
var right = funccall();
left = {left, op, right};
}
return left;
}
function plus(){
var left = mul();
var op;
while(op = accept(tokens,"+","-")){
var right = mul();
left = {left, op, right};
}
return left;
}
function assign(){
var left = plus();
var op;
while(op = accept(tokens, "=")){
var right = comma();
left = {left, op, right};
}
return left;
}
function comma(){
var left = assign();
var op;
while(op = accept(tokens,",")){
var right = assign();
left = {left, op, right};
}
return left;
}
function semi(){
var left = comma();
var op;
while(op = accept(tokens, ";")){
var right = comma();
left = {left, op, right};
}
return left;
}
### run.js
const { error } = require("./utils");
module.exports = run;
var global = {};
function run(a){
if(!a) return;
if(!a.op){
if(a[0] == '"') return a.substr(1, a.length-2);
if(/\d/.test(a[0])) return 1*a;
if(global.hasOwnProperty(a)) return global[a];
return a;
} else if (a.op==";"){
run(a.left);
run(a.right);
} else if (a.op==","){
return [run(a.left), run(a.right)].flat();
} else if (a.op=="="){
return global[run(a.left)] = run(a.right);
} else if (a.op=="+"){
return run(a.left) + run(a.right);
} else if (a.op=="-"){
return run(a.left) - run(a.right);
} else if (a.op=="*"){
return run(a.left) * run(a.right);
} else if (a.op=="/"){
return run(a.left) / run(a.right);
} else if(a.op == "()") {
var func = run(a.left);
if(func == "print"){
var msg = [run(a.right)].flat().join("");
console.log(msg);
} else {
error("未実装の関数呼び出し func=", func);
}
} else {
error("未実装の演算子 op=", a.op)
}
}
ASTのparse.jsで優先したいopをより深くvalueに近い位置でcallすれば、mulはplusよりも優先して処理される。