#contents
*Abstract Syntax [#me70950c]
*Abstract Syntax [#x7bf215e]
- Abstract=いかなる実体とも結びついていないもの
- コンパイラは、文が文法にそっているかをチェックするだけじゃダメ。
-それ以上のなにか(Semantic Actions)が必要
- 再帰降下パーサの場合、semantic actionはパーサーのなかにまき散らされている
- ML-Yaccの場合、生成ルールにくっつけて書かれる

**SEMANTIC ACTIONS [#h561570f]
**SEMANTIC ACTIONS [#a1c05920]
- 各要素(nonterminal/terminal)は意味的な値(semantic value)の型を持っている
- semantic actionは、その値を生成する

*** RECURSIVE DESCENT [#z7101afc]
*** RECURSIVE DESCENT [#i9e610ee]
- semantic action=パーサ関数の返す値と、その関数が起こす副作用
- 各要素について、実装言語の型が関連づけられている
- Program 4.1が例ですよ。T'がちょっとトリッキー。左オペランドが書けているので、引数として渡している

*** ML-Yacc-GENERATED PARSERS [#h4100ca5]
*** ML-Yacc-GENERATED PARSERS [#n8e64251]
- ML-Yacc用の文法のsetのそれぞれに、semantic actionがMLの式の形でannotateされる
- パーサがルールを還元するたびに、そのsemantic actionが実行される
- actionは、生成規則の右辺のsemantic valueを参照できる
- 例)expの各semantic actionは、すべて同じ型(今回はint)を返す必要がある

- semantic valueは各シンボルと共にスタック上に保存される
- 還元する場合は、スタックの上からいくつか値をpopする。そして新しい値をpushする

*** A MINI-INTERPRETER IN SEMANTIC ACTIONS [#h3c91352]
*** A MINI-INTERPRETER IN SEMANTIC ACTIONS [#bc8fb010]
- PROGRAM 1.5でやった言語のインタプリタを作ろう
- expのsemantic valueはtable->int。これはテーブルを受け取ったらなにか整数を返すということ。
- 例) x = テーブルをもらったら、そこからxを探して返すよ。42 = テーブルをもらったら、それを無視して42を返すよ。
- statementは、tableを受け取って、適当なtableを返すよ
- でもこの構造だと、exp内の代入文がtableを弄れない

*** AN IMRERATIVE INTERPRETER IN SEMANTIC ACTION [#i4390ad6]
*** AN IMRERATIVE INTERPRETER IN SEMANTIC ACTION [#y98d3e38]
- 今までは副作用がなかったから、生成規則ほ右辺の評価順番はどうでもいい
- LRパーサの場合、評価順番は決まっている。bottom-up、左から右へ。言うなれば、parse treeのpost orderで
- だから、副作用のある手続き的なsemantic actionも書ける

**ABSTRACT PARSE TREES [#se200eb7]
**ABSTRACT PARSE TREES [#hcf395fa]
- semantic actionだけでコンパイラを書くのはダメ
- 読むのとメンテナンスが大変
- パースした順に、プログラムを解析しなければならなくなる

- syntaxの処理(パース)とsemanticsの処理(型チェックやマシンコードへの変換)を分けよう
- そのためにパーサにparse treeを作らせよう
- parse treeの各葉はトークン、幹はパース中に還元された文法規則

- parse treeをそのまま使うのは不便
- いくつかの区切り文字は冗長で、何の情報ももたない

- parse treeは文法に依存しすぎている
- 左再帰などを除去すると、文法は変わる
- このあたりは、parse phaseだけに閉じ込めておくべき

- 抽象構文(abstract syntax)は、パーサと他の部分の間のインターフェースになる
- 抽象構文木は、semanticの解釈に必要な情報だけを運ぶ

- 初期のコンパイラは、メモリ節約のため抽象構文木を使わなかった
- 最近の言語では、先行宣言(forward declaration)は必要ない。これも、抽象構文木のおかげ

- Grammer 4.6が、straight-line-programの抽象構文
- 演算子の順序が曖昧だし、いくつかのキーワードが消えているから、パースには使えない

- 抽象構文は、すでにパースが終わったものなので、曖昧でもかまわない
- 抽象構文木のためのデータ構造はdatatypeで作ろう

- abstract syntax grammerの生成規則が各コンストラクタに対応する
- 各非終端記号がMLの型に対応する
- 相互再帰している比終端記号は、他の抽象構文を参照しているMLの型になる

*** POSITION [#q5e98de4]
*** POSITION [#w4428552]
- 伝統的なワンパス コンパイラは、字句解析とパースと意味解析が同時に進行する
- 型の不一致などのエラーが発生したとき、発生したソースコード中の位置を表示する
- 字句解析器は、今どの位置にいるかという情報を保持している

- 抽象構文木をつかったコンパイラだと、このエラーメッセージの表示が難しい
- 字句解析器が終わった後に、意味解析が行われるので、字句解析器の情報が使えない
- 各ノードが、ソースコード中の位置を記憶していなければならない

- abstract-syntax data structureにposというフィールドを追加する

- 字句解析器が各トークンの開始位置と終了位置を渡すと、それがML-Yaccで使える
- FOOという記号があったとき、FOOleftが開始位置、FOOrightが終了位置になる
- これらがposフィールドの決定のために使われる

*** ABSTRACT SYNTAX FOR Tiger [#b86e03a9]
*** ABSTRACT SYNTAX FOR Tiger [#c8a71ae1]
- Tigerの抽象構文は、Figure4.8のようになります。
- posは、ソースコードの開始から何文字目かを表している

- Tigerは相互再帰関数が書ける
- だからFunctionDecコンストラクタは、関数定義のリストを受け取る

- 同様の理由で、TypeDecコンストラクタは、型定義のリストを受け取る

- &や|の抽象構文は存在していない
- e1 & e2 は if e1 then e2 else 0に、e1 | e2 は if e1 then 1 else e2に変換される
- 単項のマイナス:-iも、0-iという減算で表される

- このような変換をすると、抽象構文木が小さくなるし、意味解析が少なくて済む
- その代わり、型チェックのエラーメッセージが分かりづらくなる

- 字句解析器はIDをstring型で返すが、抽象構文ではsymbol型が欲しい
- Symbol.symbol:string->symbolとSymbol.name:symbol->stringが用意してある
- http://www.cs.princeton.edu/~appel/modern/ml/chap4/symbol.sml

わからない:
- 意味解析では、ネストされた関数内でのローカル変数の使用を追跡する必要がある
- そのために、escapeというフィールドが使われる
- パーサはescapeがtrueなら、セットされたままにしておく?
- escapeは、VarDec(変数定義)、ForExp(for文)、formal parameter(関数の引数?)で使われる
- field型は、レコードの各フィールドとformal parametrで使われている。でもレコードの場合は、escapeを無視する

- escapeはHackだよ。本来はここにあるべきじゃないけど、ほかのとこに置くには余計なデータ構造がいるんだ

***PROGRAM: ABSTRACT SYNTAX [#h7b97035]
- 改造したいならtiger.grmを書き換えなさい
- structure A = Absynとやると楽だよ

- ファイルは$TIGER/chap4にあるよ。http://www.cs.princeton.edu/~appel/modern/ml/chap4/

|ファイル名|説明|h
|absyn.sml|Tigerの抽象構文用のデータ構造|
|prabsyn.[ch]|抽象構文木用のpretty-printer|
|base.sml|今までと同じ|
|errormsg.sml|今までと同じ|
|tiger.lex.sml|自分で書いたやつが動かなかったときは、これを使いなさい|
|symbol.sml|string->symbolを行うモジュール|
|sources.cm|普通通り(as usual)|
|parse.sml|パーサを起動するドライバ|
|tiger.grm|文法のひな形|

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS