10分で書く構文解析器
10分で書く構文解析器をやってみました。
再帰下降法を使っています。
四則演算して結果を返します。
最初に、簡単なスタックのように使える文字読み込み関数pop(),push(),peek()をつくり、
その関数を利用して、再帰下降構文解析の関数expr,term,factを作成しています。
字句解析は、pop()とfact()関数内でやってる感じです。
時間が余った分、空白の処理を入れています。
htmlはありものを使ってるので、実質、作ってる時間は5,6分です。
ムービー
http://sakurai.s59.xrea.com/10min/10minparse.html
できあがったもの
http://sakurai.s59.xrea.com/10min/parse.html
詳しいところは、id:tanakhさんの
10分で書ける、お手軽パーザーを見てください。
http://fxp.hp.infoseek.co.jp/arti/parser.html
追記:一箇所間違えてました。t = c + t じゃなくて、 t = t + cでした。
ソース
function parse(str) { // expr : term { (+|-) term } // term : fact { (*|/) fact } // fact : number | '(' expr ')' var buf = str; function pop() { var c; do { c = buf.charAt(0); buf = buf.substring(1); } while (c.match(/[ \t\r\n]/)); return c; } function push(s) { buf = s + buf; } function peek() { var c = pop(); push(c); return c; } try { return expr(); } catch (e) { return e; } function expr() { var c = term(); while (peek() == "+" || peek() == "-") { if (pop() == "+") c = c + term(); else c = c - term(); } return c; } function term() { var c = fact(); while (peek() == "*" || peek() == "/") { if (pop() == "*") c = c * fact(); else c = c / fact(); } return c; } function fact() { var c = pop(); if (c.match(/[0-9]/)) { var t = ""; while(c.match(/[0-9]/)) { t = t + c; c = pop(); } push(c); return Number(t); } if (c == "(") { c = expr(); if (pop() != ")") throw "invalid error"; return c; } return "invalid error"; } }