ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

Writing Compilers and Interpreters: その12

定数宣言のパースができるようになった。こういう定数の宣言をパースしてクロスリファレンスをかえると、

CONST
    epsilon = 10;
    limit = -epsilon;
BEGIN
END.

こんな感じで、integerということとその値が表示されるところまで来た。

***Definition.PROGRAM dummy_program_name ***

Identifier        Line numbers   
----------        ----------- 
epsilon         002 003 
                                Defined as: 1
                                scope nesting level: 1
                                Type form = 0, type id = integer
                                Value = 10
limit           003 
                                Defined as: 1
                                scope nesting level: 1
                                Type form = 0, type id = integer
                                Value = -10
				

少しずつ前へ。

Writing Compilers and Interpreters: その11

chap9は型システム。想像していたより難しい。一歩ずつ行かないと。

PROGRAM Test;
CONST
    epsilon = 1.0e-6;
TYPE
    rec = RECORD
            a : real;
	    x, y : integer;
	  END;

こういうコードに対して、シンボルテーブルをスタックにする。

Level 0がInteger等の組込型が定義されているglobal scope。Level 1がプログラムで使用する変数が定義されている Program Scope。
Lebal 2 がレコード型の変数が定義されているScope。レコード型が出てくる度にスコープを新しく作り、フィールドに他と同じ名前の変数を使えるようにする。

Writing Compilers and Interpreters: その10

chap8が終了。
for文などが動くようになった。面白くなってきた。

CASE文の処理で caseのラベルをキーにして処理を辞書に入れておくと、caseラベルが増えても一定のコストでジャンプできるハック。その辞書をメモ化するまでがセット。面白いが、いまいち速度的な意味があるのかよくわからない。

Writing Compilers and Interpreters: その9

chap6が終了。制御構造とか何にもないけど、変数の代入ができるようになった。
ふと気が付いたんだけど、定数の畳み込みの最適化って、実際にはインタプリタの実装と同じだ。

変数のスコープ、演算子の優先順序、型変換等、言語仕様にそって動く物がないと、最適化前、後で結果が変わってしまう。

整数と浮動小数点数の演算や、浮動小数点数同士の演算の順序とか、想像していたよりシビアで意外に最適化むつかしいなと気が付いた。

Writing Compilers and Interpreters: その8

手書きパーサー作成中。

BEGIN
    BEGIN {Temperature conversions.}
        five  := 3;
    END;
END.

これのパース結果をxmlで出力できるようになった。こんな単純なのだと良いけど、これから複雑になってきたときにxmlで良いのかは良く分からない。

<COMPOUND line="1">
    <COMPOUND line="2">
        <ASSIGN line="3">
            <VARIABLE id="five" level="0" >
            <INTEGER_CONSTANT value="3" >
        </ASSIGN>
    </COMPOUND>
</COMPOUND>

あとは少しずつパスカルのソースを複雑にしていく。

Writing Compilers and Interpreters: その7

手書きパーサーを作成中。

このPascalコードをパースして、

BEGIN
    BEGIN {Temperature conversions.}
        five  := 3;
    END;
END.

fiveを代入先の識別子として認識するところまで来ました。

====== CROSS-REFERENCE TABLE ======

Identifier        Line numbers   
----------        ----------- 
five            003 
0 instructions generated

もうちょっと大きいPascalコードをパースさせると無限ループする。
デバッグする前に、パースした結果の構文ツリーがちゃんとできているか確認したい。

ちょっとしたことでもブログに書いていかないと、仕事が忙しくなるとモチベーションが消えそう。

Writing Compilers and Interpreters: その6

シンボルテーブルを作りました。
この本にでてくるのは、スタック型のデータ構造でシンボルを管理しています。ツリーで全部作りきった方が良さそうな気がするのですが、パースしながらネストに沿ってスタックを伸ばしたり縮めたりするようです。ネストの処理は9章でやるようです。

このソースコードに対して、シンボルテーブルが出力できるようになりました。

====== CROSS-REFERENCE TABLE ======

Identifier        Line numbers   
----------        ----------- 
abs             031 033 
epsilon         004 033 
input           001 
integer         007 
newton          001 
number          007 014 016 017 019 023 024 029 033 035 
output          001 
read            014 
real            008 
root            008 027 029 029 029 030 031 033 
sqr             033 
sqroot          008 023 024 031 031 
sqrt            023 
write           013 
writeln         012 017 020 024 025 030 
0 instructions generated