前面我們已經學會了如何理解宣告:
事實上,在我們讀原始碼的時候,或許也會遇到錯綜複雜的宣告語句,為什麼不寫乙個程式幫助我們理解呢?接下來我們將編寫乙個能夠分析c語言的宣告並把它們翻譯成通俗語言的程式。為了簡單起見,暫且忽略錯誤處理,而且在處理結構、列舉和聯合時只簡單地用「struct」、「enum」和「union」來代表它們的具體內容。最後,這個程式假定函式的括號內沒有引數列表(實際上我們在分析的時候,引數列表也被忽略了)。
主要的資料結構是乙個堆疊,我們從左向右讀取,把各個標記依次壓入堆疊,直到讀到識別符號為止。然後我們向右讀入乙個標記,也就是識別符號右邊的那個標記。接著觀察識別符號左邊的那個標記(需要從堆疊中彈出)。資料結構大致如下:
struct偽碼如下:token ;
/*儲存第乙個標識之前的所有標記
*/struct
token stack[maxtokens];
/*儲存剛讀入的那個標記
*/struct token t;
實用程式----------classify_string(字串分類)**如下:檢視當前標記,
通過t.type返回乙個值,內容為「type(型別)」,「qualifier(限定符)」或「identifier(識別符號)」
gettoken(取標記)
把下乙個標記讀入t.
string
如果是字母數字組合,呼叫classify_string
否則,它必是乙個單字元標記,
t.type=該標記;用乙個null結束t.string
read_to_first_identifier(讀至第乙個識別符號)
呼叫gettoken,並把標記壓入到堆疊中,直到遇見第乙個識別符號。
print「identifier
is (識別符號是)」,t.string
繼續呼叫gettoken
解析程式----------
deal_with_function_args(處理函式引數)
當讀取越過右括號『)』後,列印「函式返回」
deal_with_arrays(處理函式陣列)
當你讀取「[size]」後,將其列印並繼續向右讀取。
deal_with_any_pointers(處理任何指標)
當你從堆疊中讀取「*」時,列印「指向...的指標」並將其彈出堆疊。
deal_with_declarator(處理宣告器)
if t.type is '[' deal_with_arrays
if t.type is '(' deal_with_function_args
deal_with_any_pointers
while 堆疊裡還有東西
if 它是乙個左括號'('
將其彈出堆疊,並呼叫gettoken;應該獲得右括號')'
deal_with_declarator
else 將其彈出堆疊並列印它
主程式----------
main
read_to_first_identifier
deal_with_declarator
#pragma warning( disable : 4996)執行結果:#define _crt_secure_no_warnings#include
#include
#include
#include
#define maxtokens 100
#define maxtokenlen 64
//識別符號identifier,修飾詞qualifier,型別type(具體的例子見classify_string函式)
enum
type_tag ;
struct
token ;
int top = -1; //
棧頂指標
//從左到右依次讀取,把各個標記依次壓入堆疊;儲存第乙個標識之前的所有標記的堆疊
struct
token stack[maxtokens];
struct token t; //
儲存剛讀入的那個標記;
//出棧和入棧操作
#define pop stack[top--]
#define push(s) stack[++top]=s
enum type_tag classify_string(void
)
//推斷識別符號的型別
if (!strcmp(s, "
volatile
")) return
qualifier;
if (!strcmp(s, "
void
")) return
type;
if (!strcmp(s, "
char
")) return
type;
if (!strcmp(s, "
signed
")) return
type;
if (!strcmp(s, "
unsigned
")) return
type;
if (!strcmp(s, "
short
")) return
type;
if (!strcmp(s, "
int")) return
type;
if (!strcmp(s, "
long
")) return
type;
if (!strcmp(s, "
float
")) return
type;
if (!strcmp(s, "
double
")) return
type;
if (!strcmp(s, "
struct
")) return
type;
if (!strcmp(s, "
union
")) return
type;
if (!strcmp(s, "
enum
")) return
type;
return identifier; //
上述結構都不是的情況,就是識別符號
}void gettoken(void) //
讀取下乙個標記到 "t"
if (*p == '*'
)
t.string[1] = '\0'
; t.type = *p;
return;}
//理解所有分析過程的**段
void
read_to_first_identifier()
printf(
"%s is
", t.string); //
這條分析語句的主語是while迴圈後得到的識別符號
gettoken(); //
繼續向右讀入乙個標記,也就是識別符號右邊的標記
}void
deal_with_arrays()
gettoken();
//讀取 ']' 之後的再乙個標記
printf("
of ");//
這個陣列是:}}
void
deal_with_function_args()
gettoken();
//讀到和左括號匹配的右括號,再讀括號後的乙個標記
printf("
function returning ");
}void
deal_with_pointers()
}void
deal_with_declarator()
//觀察識別符號左邊的標記
deal_with_pointers();
//處理在讀入到識別符號之前壓入到堆疊中的符號
while (top >= 0
)
else
}}int
main()
觸發斷點的解決辦法
乙個簡單的詞法分析器
該詞法分析器可以處理簡單的語法,但有限狀態機 正規表示式的處理不是非常嚴謹 僅供參考 但可以起到啟蒙例子的作用,下面源 經本人確認可以執行 執行例子如下 源 include include include using namespace std ref 詞法分析器的實現 prog 輸入的源字串 to...
C語言簡單詞法分析器
詞法分析器 c語言 輸入源程式 輸出單詞符號 1 預處理程式 2 掃瞄器 單詞識別程式 include include include define keyword num 32 int pos pos搜尋指標 char ch ch最新讀入的字元 char buf 1000000 buf緩衝區 ch...
用 C C 編寫乙個 C 語言的詞法分析器程式
include include include include using namespace std define maxn 100 include 詞法分析器,對於輸入的串,先處理空格,過濾掉,進入主程式,判斷是字母,迴圈判斷字母或數字 迴圈出去後,判斷所讀字串是否是保留字,若是輸出保留字及其編...