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にした。