Presentation is loading. Please wait.

Presentation is loading. Please wait.

記号表の検索と登録 長谷川啓 2018.09.25.

Similar presentations


Presentation on theme: "記号表の検索と登録 長谷川啓 2018.09.25."— Presentation transcript:

1 記号表の検索と登録 長谷川啓

2 プログラムに出現する変数、リテラルの扱い
struct scope { ... map<string, vector<usr*> > usrs; // 名前からシンボル情報にアクセスする };

3 map<string, vector<usr*> >
// 函数の外側 int i = 1; int i; // ok extern int i; // もちろん ok map<string, usr*> ではなく map<string, vector<usr*> > にしているのはこういう理由から

4 バックエンドの記号表に対する扱い int i = 1; // (1) int i; // (2) extern int i; // (3)

5 フロントエンドの記号表 lookup // 文字列に対して記号表を検索して字句の種別を返す函数
lex::kind_t lookup(string name, scope* ptr) { const map<string, vector<usr*> >& usrs = ptr->usrs; map<string, vector<usr*> >::const_iterator p = usrs.find(name); if ( p != usrs.end() ) { const vector<usr*>& v = p->second; usr* u = v.back(); // ポイント : 最後の宣言を参照する ... } int i = 1; // (1) int i; // (2) extern int i; // (3) void f(void){ ... use i ... } // 参照するのは (3) の宣言

6 バックエンドの記号表に対する扱い(その2)
函数 gen で (1) に対して初期値ありのコードを生成 (2) に対して初期値なし(スペースのみ)のコードを生成 (3) は extern があるからスキップ とするのは i の多重定義になるので間違い。 find_if(v.begin(), v.end(), gen); のようにすれば(1)でのコード生成のみで一応大丈夫 int i = 1; // (1) int i; // (2) extern int i; // (3) バックエンドの実装 const map<string, vector<usr*> >& usrs = ... for_each(usrs.begin(), usrs.end(), usr); void usr(const pair<string vector<usr*> >& p) { const vector<usr*>& v = p.second; for_each(v.begin(), v.end(), gen); }

7 バックエンドでの記号表の扱い(その3) int i = 1; // (1) int i; // (2)
void f(void){ ... use i ... } // (1) でなく (2) を参照. (2) の i のアドレス記述子をちゃんと決めてあげないといけない extern int i; void g(void){ ... use i ... } // (1) でも (2) でもなく (3) を参照. 宣言に対するコード生成とは別に、アドレス記述子は最後の宣言に対して決める必要がある。 const vetor<usr*>& v = p.second; find_if(v.begin(), v.end(), gen); decide_address_descriptor(v.back()); のようにする必要がある。

8 フロントエンドでの記号表への登録 void install(usr* curr, scope* ptr) {
string name = curr->m_name; map<string, vector<usr*> >& usrs = ptr->m_usrs; map<string, vector<usr*> >::iterator p = usrs.find(name); if ( p != usrs.end() ) { vector<usr*>& v = p->second; usr* prev = v.back(); // 直前の宣言のみと比較する if (!prev->m_type->compatible(curr->m_type) || ... ) { // 再宣言されている。エラー。 } else { curr->m_type = prev->m_type->composite(curr->m_type); usrs[name].push_back(curr);

9 例 void f(); // void (...) として登録 void g() { }
f(1,2,3); // ok } void f(int); // ok. void (...) と void (int) は compatible なので // composite な void (int) として登録 void h() { f(3); f(1,2,3); // エラー void f(); // もう一回! void (int) と void (...) は compatible なので void i() { f(1,2,3); // これはエラー


Download ppt "記号表の検索と登録 長谷川啓 2018.09.25."

Similar presentations


Ads by Google