工作進度2--預處理器的設計

 因爲項目需求,自己需要實現一個類似於CPP的預處理器。
今天花了大半天的時間在考慮怎樣實現這個預處理器。
自己需要實現的這個預處理器的形式跟C語言的有些類似,包括如下一些預處理命令:
define
ifdef
include
ifndef
line
undef
else
elif
endif
resetall
....
藍色字體的命令是跟C語言中的相應預處理命令同名且含義相同的元素,如define與C語言中的#define的功能是

一樣的,include則對應於#include

而紅色字體的命令,如resetall(這是一個用來恢復默認的編譯器行爲的命令),嚴格來說,已經不能算是預處理命

令,而是用來指導控制編譯器工作行爲的一些directives了(像resetall這樣的directives在自己要實現的語言

中還有一些),因此對其的處理是不能夠在預處理階段完成的。

以C語言爲例,這些directives就類似於C語言中的#pragma 命令。在C語言中,我們可以通過#pragma來影響

編譯器的工作行爲,如
#pragma warning(disable:1401)   // 從此行開始,禁止編譯器報出編號爲1401的警告信息
#pragma pack(4)            // 從此行開始,在爲structure, union分配內存時,以16字節對齊

可以看出,這些#pragma命令雖然是假預處理命令之形,但實際上對它們的處理已經不可能在預處理階段完成. 只

不過形式上來看這些#pragma命令與常規的預處理命令是一樣的.

這樣就引入了一定的複雜性,爲了便於描述,讓我們假定所有符合預處理器格式的命令集合爲S, 能夠在預處理階

段實現的命令子集合爲P,需要推遲到編譯階段(詞法,語法或語義階段)實現的命令子集爲Q, S等於PQ的並

集。可以看出,如果想爲編譯器引入一個獨立的預處理器的話,勢必只能在這個預處理器中實現P集合中的命令, 剩

下 的Q集合需要在其他階段實現。

從軟件設計的結構上來看,雖然引入了預處理器環節,將複雜的工作分階段化了,卻由於S集合本身的複雜性而使這

種階段劃分作得不夠徹底。

而同樣可以支持預處理器功能的另外一種實現思路就是,乾脆不再引入預處理器環節,而是直接在詞法分析模塊中

實現對集合P的支持。這樣雖然在詞法模塊作了更多事情,但相對來說,還保證了設計的一致性. 不過由於在詞法模

塊中混入了對預處理器的支持,兩部分的code會相互干擾,很可能會增加維護這兩個模塊的工作量。

在我看來,最完美的方案就是通過修改語言的規則,把Q集合中的命令從S集合中抽出以其他語法形式來表

示, 以確保所有S集合中的命令都能夠在預處理器階段中實現,這樣在編譯器的後續階段不需要再考慮預處理器格式

命令
的處理了。但是這涉及到對現有語言規則的修改,而對於我要作的這個項目來說,這是不現實的,所以這種完

美方案實際上是不存在的了。

一番考慮之後,最後我還是傾向於設計一個獨立的預處理器的方案。因爲我覺得確保每個模塊所實現的功能

足夠高內聚低耦合,有利於模塊的可維護性和可擴展性。畢竟維護一個功能單一的模塊要比維護一個涉及多個功能

的模塊所需精力更少一些.另外,我覺得這樣也符合KISS(Keep It Simple and Stupid)的設計原則.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章