我創建了一個編譯器(用於酷語言)作爲個人項目,並且在設計符號表時遇到了麻煩。對於上下文,我使用類的層次結構作爲我的AST。這裏的AST的一個小片段:玩具編譯器符號表
class NodeAST {
public:
virtual void accept(Visitor&) = 0;
};
class ProgramAST : public NodeAST {
private:
const std::vector<ClassPtr> vClasses;
public:
ProgramAST(std::vector<ClassPtr> vClasses);
auto class_cbegin() const {
return std::cbegin(vClasses);
}
auto class_cend() const {
return std::cend(vClasses);
}
virtual void accept(Visitor& v) override;
};
class ClassAST : public NodeAST {
private:
const std::string name;
const std::vector<FeaturePtr> vFeatures;
public:
ClassAST(std::string name, std::vector<FeaturePtr> vFeatures);
auto getName() const {
return name;
}
auto feature_cbegin() const {
return std::cbegin(vFeatures);
}
auto feature_cend() const {
return std::cend(vFeatures);
}
virtual void accept(Visitor& v) override;
};
目前,在我的符號表的核心定義爲地圖如下:
std::unordered_map<std::string, NodeAST*> table
它在聲明的名稱映射到其相應的節點AST。這樣,例如,我可以使用我在AST節點中設置的類型來填充鬆散標識符的類型。
但問題是,當我查詢的符號表中的節點,我拿回NodeAST*
。因此,我必須將其下降到ClassAST*
,MethodAST*
或VarDecAST*
等以實際使用它。
如何設計我的符號表以避免爲向下轉換的需要的呢?
我不會說在這裏downcasting一定是個大問題。你可以從上下文知道目標類型。當然,因爲Cool源代碼包含錯誤,所以downcast仍然會失敗,但在這種情況下,您的'dynamic_cast'失敗,並且您將其作爲直接錯誤輸出,例如'期望一個班,但是「Foo」命名一個功能'。 – MSalters
也許:擺脫基本的'NodeAst'並使所有'accept'函數成爲非虛擬模板。相比之下,您可能會讓訪問者在每種集合類型上運行不同。 –
@DieterLücking:通常幾乎不需要刪除基類;您仍然可以通過繼承實例化碰巧相關的類。 – MSalters