可配置文法分析器開發紀事(二) 構造符號表

來源:互聯網
上載者:User

上一篇部落格講到了構造文法樹的問題。有朋友在留言問我,為什麼一定要讓文法分析器產生文法樹,而不是讓使用者自己決定要怎麼辦呢?在這裡我先解答這個問題。

1、大部分情況下都是真的需要有文法樹

2、如果要直接返回計算結果之類的事情的話,只需要寫一個visitor運行一下文法樹就好了,除去自動產生的程式碼以外(反正這不用人寫,不計入代價),代碼量基本上沒什麼區別

3、加入文法樹可以讓文法本身描述起來更簡單,如果要讓程式員把文法單獨放在一邊,然後自己寫完整的語義函數來讓他產生文法樹的話,會讓大部分情況(需要文法樹)變得特別複雜,而少數情況(不需要文法樹)又沒有獲得什麼好處。

儘管類似yacc這樣的東西的確是不包含文法樹的內容而要你自己寫的,但是用起來難道不是很難受嗎?

現在轉入正題。這一篇文章講的主要是構造符號表的問題。想要把符號表構造的好是一件很麻煩的問題。我曾經嘗試過很多種方法,包括強型別的符號表,弱類型的符號表,基於map的符號表等等,最後還是挑選了跟Visual Studio內建的用來讀pdb檔案的DIA類其中的IDIASymbol(http://msdn.microsoft.com/en-us/library/w0edf0x4.aspx)基本上一樣的結構:所有的符號都只有這麼一個symbol類,然後包羅永珍,什麼都有。為什麼最後選擇這麼做呢?因為在做語義分析的時候,其實做的最多的事情不是構造符號表,而是查詢符號表。如果符號表是強型別的畫,譬如說類型要一個類,變數要一個類,函數要一個類之類的,總是需要到處cast來cast去,也找不到什麼好方法來在完成相同事情的情況下,保留強型別而不在代碼裡面出現cast。為什麼文法樹就要用visitor來解決這個問題,而符號表就不行呢?因為通常我們在處理文法樹的時候都是遞迴的形式,而符號表並不是。在一個上下文裡面,實際上我們是知道那個symbol對象究竟是什麼東西的(譬如說我們查詢了一個變數的type,那這傳回值肯定只能是type了)。這個時候我們要cast才能用,本身也只是浪費表情而已。這個時候,visitor模式就不是和面對這種情況了。如果硬要用visitor模式來寫,會導致語義分析的代碼分散得過於離譜導致可讀性幾乎就喪失了。這是一個辯證的問題,大家可以好好體會體會。

說了這麼一大段,實際上就是怎麼樣呢?讓我們來看“文法規則”本身的符號表吧。既然這個新的可配置文法分析器也是通過parse一個文本形式的文法規則來產生parser,那實際上就跟編譯器一樣要經曆那麼多階段,其中肯定有符號表:

class ParsingSymbol : public Object{public:    enum SymbolType    {        Global,        EnumType,        ClassType,        // descriptor == base type        ArrayType,        // descriptor == element type        TokenType,        EnumItem,        // descriptor == parent        ClassField,        // descriptor == field type        TokenDef,        // descriptor == token type        RuleDef,        // descriptor == rule type    };public:    ~ParsingSymbol();        ParsingSymbolManager*            GetManager();    SymbolType                        GetType();    const WString&                    GetName();    vint                            GetSubSymbolCount();    ParsingSymbol*                    GetSubSymbol(vint index);    ParsingSymbol*                    GetSubSymbolByName(const WString& name);    ParsingSymbol*                    GetDescriptorSymbol();    ParsingSymbol*                    GetParentSymbol();    bool                            IsType();    ParsingSymbol*                    SearchClassSubSymbol(const WString& name);    ParsingSymbol*                    SearchCommonBaseClass(ParsingSymbol* classType);};

本欄目更多精彩內容:http://www.bianceng.cn/Programming/cplus/

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。