C語言 乙個簡單的宣告語義分析器

2022-09-11 09:18:06 字數 4260 閱讀 7203

前面我們已經學會了如何理解宣告:

事實上,在我們讀原始碼的時候,或許也會遇到錯綜複雜的宣告語句,為什麼不寫乙個程式幫助我們理解呢?接下來我們將編寫乙個能夠分析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 詞法分析器,對於輸入的串,先處理空格,過濾掉,進入主程式,判斷是字母,迴圈判斷字母或數字 迴圈出去後,判斷所讀字串是否是保留字,若是輸出保留字及其編...