エラー復帰機能付きパーサを考える。
下降型演算子順位法のパーサにエラー復帰機能をつけてみました。
実装したのは以下の2つです。
•字句解析時にマッチしなかったら、1文字読み飛ばす
•構文解析時に予測した括弧まで、読み飛ばす
四則演算に関係のない文字があったら読み飛ばすようにしたのが、字句解析のエラー復帰機能です。
abc(1+2*a3b)
このような式は
(1+2*3)
と同じ意味になります。というのが、字句解析時のエラー復帰機能です。
括弧まで、読み飛ばし機能は、予測される括弧が見つかるまで、読み飛ばして、なくてもあったことにする機能です。
(1+2**3
という式は
(1+(2* *))
という意味で構文解析されます。
以下、ソースコードになります。
<script> Array.prototype.toString=function(){ return "["+this.join(",")+"]"; } var Exp = { run: function(){ var src =document.getElementById("in").value; document.getElementById("out").value = Exp.exec(src); }, exec: function(src) { try { Exp.src = src; return Exp.parse(); } catch (e) { return e; } }, src:"", token:"", ptoken:"", parse: function () { Exp.advance(); return Exp.exp(0); }, advance: function() { Exp.ptoken = Exp.token; var m; while ((m = Exp.src.match(/^[ \r\n\t]*([0-9]+|[+\-*/\(\)]|$)/)) == null) { Exp.errors.push("found not expected charactor "+Exp.src.charCodeAt(0)); Exp.src = Exp.src.substring(1); } Exp.src = Exp.src.substring(m[0].length); Exp.token = m[1]; return Exp.ptoken; }, infixs: { "+":10, "-":10, "*":20, "/":20 }, parens: { "(":")", "{":"}", "[":"]" }, exp: function(p) { var t = Exp.advance(); if(t in Exp.parens) { var startParen = t; var endParen = Exp.parens[t]; t = Exp.exp(0); if(endParen != Exp.advance()) { Exp.errors.push("syntax error expected "+endParen); do{ Exp.advance(); } while(!Exp.token in Exp.parens); } t = [startParen, t, endParen]; } while (true) { if (Exp.token in Exp.infixs && Exp.infixs[Exp.token] > p) { var op = Exp.advance(); t = [t, op, Exp.exp(Exp.infixs[op])]; continue; } break; } return t; }, errors:[], "":"" }; </script> <input id="in" value="abc(def(1+2*3**4)+5*6**7)+8"/> <input id="out" value=""/> <input type="button" value="run" onclick="Exp.run()" />