複数文はセミコロンで区切るとする。
### 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は文末にセミコロンがないけどどうやってるんだろうか?