自由帳

@_nibral の技術ブログ

Writing An Interpreter In Go その3

その2はこちら

Lexerが完成してソースコードトークン列に分解できるようになったので、抽象構文木 (Abstract Syntax Tree, AST) を組み立てるParseの実装に入る。

バッカス・ナウア記法 (BNF) などで書かれた構文規則からParserを自動生成するParser Generatorというものもある (e.g. yacc, bison) が、この本ではGeneratorは使わずに自力でParserを作る。完成するParserは発明者の名前をとってPratt parserと呼ばれており、JSLintでも使われているらしい。

2.4: let のParserを実装

Implement parser of 'let' statement · nibral/monkey_interpreter@53cff67 · GitHub

Lexerのときと同じように、今読んでいるトークンの位置と次のトークンの位置を一つずつ進めていく。

ここでは変数を定義する "let x = 5;" のようなコード、トークンで言うと LET IDENT ASSIGN で始まって SEMICOLON で終わる部分を取り出してASTに追加する。この時点では名前を取り出しているだけなので、= と ; の間に何が入っていてもすべて読み飛ばす。

2.4: Parserにエラー処理を追加

Add error handling to parser · nibral/monkey_interpreter@fc9056d · GitHub

文法的におかしいトークンが出現したときにエラーを出すようになった。上で実装した let の場合、let の次に識別子がなかったり ("let = 10;") 、= がなかったり ("let x 5;") というエラーを検出できる。

「〇〇というトークンが来るはずだけど××が来た」という具体的なエラーメッセージが出るので、この時点でそこらのコンパイラより親切なのでは?という気持ちになる。

2.5: return のParserを追加

2.5: Add parser of 'return' statement · nibral/monkey_interpreter@64b4e6f · GitHub

文法上 "return <式>;" という形なので、return が出たら ; まで読み飛ばしてASTに追加する。let と同様返却する値の解析は後回しにしているので、return から ; までの間に何が書かれていてもエラーにならない。

あと、写経をミスってParser内部でしか使わない関数がpublicになっていたのでprivateにした。