符號表的簡單使用


符號表 (symbol table) 是一種供編譯用於保存有關源程序構造的各種信息的數據結構。 這些信息在編譯器的分析階段被逐步收集並放入符號表,它們在綜合階段用於生成目標代碼。符號表的每個條目包含與一個標識符相關的信息,比如它的字符串(或者詞素)、它的類型、它的存儲位置和其他相關信息。符號表通常需要支持同一標識符在一個程序中的多重聲明.

 

每個帶有聲明的程序塊都會有自己的符號表,這個塊中的每個聲明都在此符號表中有一個對應的條目。

 

例如下面的例子:

{ int x; char y; { bool y; x; y; } x; y; }

我們知道 第二個{}里面的 x、y 分別是 int、bool 類型, 外面的 x、y 分別是 int、char類型。

我們可以將上面的用下面的代表:

{ { x:int; y:bool; } x:int; y:char }

為了能夠讓程序生成這樣的輸出,必須要借助符號表。

 

本身這設計到詞法分析,但為了簡化操作,規定每一個部分用空格隔開,例如 {int x;} 要寫成 { int x ; }

首先定義兩個類,一個類代表符號,另一個代表標識符。

public class Token {
    public final String lexeme;
    public Token(String s) { lexeme = s; }
    public String toString() { return lexeme; }
}
public class Id extends Token {
    public final String type;
    public Id(String s, String t) { super(s); type = t; }
    public String toString() { return lexeme + ":" + type + ";"; }
}

 

接着就要創建一個符號表類。

符號表要能夠存儲當前符號表中的標識符,又能查詢到標識符在哪一作用域。

為了存儲標識符, 增加一散列表.

private Hashtable table;

代碼如下:

public class Env {
    private Hashtable<String, Id> table;
    protected Env prev;
    public Env(Env p) { table = new Hashtable<>(); prev = p; }
    public void put(String s, Id id) { table.put(s, id); }

    public Id get(String s) {
        for (Env e=this; e != null; e = e.prev) {
            Id found = e.table.get(s);
            if (found != null) return found;
        }
        return null;
    }
}

 

接着就是翻譯的工作了。

一開始要初始化一個符號表,讓它的 pre 字段為空。每當遇到一個 '{' 就新建一個符號表, 用來表示當前作用域,每遇到一個 '}' 就要返回到上一作用域,遇到聲明,則將標識符和該標識符的類型放入 符號表, 遇到表示符,就將該標識符的信息輸出。

 

代碼如下:

public class Lexer {
    public static void main(String[] args) {
        String s = "{ int x ; char y ; { bool y ; x ; y ; } x ; y ; }";
        Lexer lexer = new Lexer();
        try {
            lexer.trans(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private Hashtable<String, Token> words = new Hashtable<String, Token>();
    
    public void reserve(Token t) { words.put(t.lexeme, t); }

    public Lexer() {
        reserve( new Token("int") ) ;
        reserve( new Token("float") );
        reserve( new Token("double") );
        reserve( new Token("char") );
        reserve( new Token("bool") );
    }
    
    public void print(String s) { System.out.print(s); }
    
    public void trans(String ss) throws IOException {
        Scanner in = new Scanner(ss);
        
        Env top = new Env(null);
        
        while (in.hasNext()) {
            String s = in.next();
            
            if (s.equals("{")) {
                top = new Env(top);
                print("{ ");
            } else if (s.equals("}")) {
                top = top.prev;
                print("} ");
            } else {
                Token w = words.get(s);
                if (w != null) {        // 類型
                    s = in.next();
                    top.put(s, new Id(s, w.lexeme));
                } else {                // 變量
                    Id id = top.get(s);
                    print(id.toString() + " ");
                }
                
                in.next();                // 去掉分號
            }
        }
    }
}

 

源代碼: https://code.csdn.net/tanheaishui/simplesymboltable


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM