複数文はセミコロンで区切るとする。
### source.3
print("hello world1");
print("hello world2");
print("hello world3");
### lexer.js
正規表現にセミコロンを追加
module.exports = function(source){
var tokens = source.split(/(".*"|print|;)|\n/);
tokens = tokens.filter(a=>a);
return tokens;
}
### parser.js
module.exports = parser;
var {expect, accept, show, error} = require("./utils.js");
var tokens;
function parser(t){
tokens = t;
return semi();
}
function semi(){
var left = callprint();
var op;
while(op = accept(tokens, ";")){
var right = callprint();
left = {left, op, right};
}
return left;
}
function callprint(){
if(tokens.length==0) return;
var left = expect(tokens, "print");
var op = expect(tokens, "(");
var msg = tokens.shift();
num = calc(msg.length);
var right = msg.substr(1, num);
op += expect(tokens,")");
return {left, op, right};
}
function calc(len) {
var total = len - 2;
return Number.isInteger(total) > 0 ? total : 0;
}
上記を実行すると、leftが入れ子になる
[[print, (), hell1] [;] [print, (), hell1]] [;] [print, (), hell1]
### run.js
const { error } = require("./utils");
module.exports = run;
function run(a){
if(!a) return;
if(!a.op){
if(a[0] == '"') return a.substr(1, a.length-2);
return a;
} else if (a.op==";"){
run(a.left);
run(a.right);
} else if(a.op == "()") {
var func = run(a.left);
if(func == "print"){
var msg = run(a.right)
console.log(msg);
} else {
error("未実装の関数呼び出し func=", func);
}
} else {
error("未実装の演算子 op=", a.op)
}
}
run(a.left); run(a.right); と左から実行することで、上から入れ子になっている式を上から順番に実行する。
$ node interpretor.js
token =[
‘print’, ‘(‘,
‘”hello world1″‘, ‘)’,
‘;’, ‘print’,
‘(‘, ‘”hello world2″‘,
‘)’, ‘;’,
‘print’, ‘(‘,
‘”hello world3″‘, ‘)’,
‘;’
]
ast={
left: {
left: {
left: { left: ‘print’, op: ‘()’, right: ‘hello world1’ },
op: ‘;’,
right: { left: ‘print’, op: ‘()’, right: ‘hello world2’ }
},
op: ‘;’,
right: { left: ‘print’, op: ‘()’, right: ‘hello world3’ }
},
op: ‘;’,
right: undefined
}
hello world1
hello world2
hello world3
parserでセミコロンが来たら、セミコロンをopにしてleftとrightに入れるというのは面白い
C, C++はセミコロンがあるが、pythonは文末にセミコロンがないけどどうやってるんだろうか?