有了前文中的積木,繼續(xù)實(shí)現(xiàn)一個(gè)詞法分析器就不再困難。
先回顧一下各個(gè)模塊:
然后我們?cè)噲D將他們組裝起來(lái),因?yàn)橐婚_始實(shí)現(xiàn)的都是零件(子函數(shù))部分,本文主要介紹在main函數(shù)中運(yùn)行的自動(dòng)機(jī)。
還記得-1篇中的DFA嗎?
經(jīng)過(guò)第0篇,以及滿足題目要求,我們最終的DFA應(yīng)該是這樣:
流程大致為:
按照以上思路,經(jīng)過(guò)不斷地調(diào)試完善,主函數(shù)設(shè)計(jì)為:
int main()
{
initialize();
string tmp;
char c;
while((c = getchar()) != EOF)
{
if(isspace(c)) // 忽略空白
continue;
if(isdigit(c)) // 如果是數(shù)字開頭
{
ungetc(c, stdin);
cout << "DIGIT : " << num() << endl;
continue;
}
char peek;
peek = getchar(); // 一步提前量
if((c == '+' || c == '-') && isdigit(peek)) //輸入帶符號(hào)數(shù)
{
ungetc(peek, stdin);
ungetc(c, stdin);
cout << "DIGIT : " << num() << endl;
continue;
}
if(c == '/' && peek == '*') //輸入注釋
{
cout << "COMMENTS : /*" << comments() << endl;
continue;
}
int tkn = 0;
string s;
if(!isalnum(c)) // 輸入c為專用符號(hào)
{
s += c;
if(peek == '=') // 所定義的雙目運(yùn)算符中第二個(gè)只有 = 可以偷懶;
s += peek;
else ungetc(peek, stdin);
tkn = query(s);
}
if(!tkn){ // 若不是專用符號(hào)開頭,即為字母開頭
ungetc(peek, stdin);
s += c;
while((c = getchar()) != EOF) // 讀入這一串字母
{
if(isspace(c)) break;
if(isalnum(c) || c == '_')
s += c;
else{
ungetc(c, stdin);
break;
}
}
tkn = query(s); // 查詢token
}
switch (tkn) // 依據(jù)token打印
{
case 1:
cout << "KEYWORD : " << s << endl;
break;
case 2:
cout << "BASIC : " << s << endl;
break;
case 3:
cout << "IDENTITY : " << s << endl;
break;
case 5:
cout << "SYMBOL : " << s << endl;
break;
default:
break;
}
}
return 0;
}
測(cè)試
使用測(cè)試樣例1:
{ /* An example */
int i,j; float x; float[100] a;
while ( true) {
do i = i + 1; while ( a[i] < x);
if ( i >= j ) break;
x = a[i];
}
}
輸出結(jié)果:
// line 1 { /* An example */
SYMBOL : {
COMMENTS : /* An example */
// line 2 int i,j; float x; float[100] a;
BASIC : int
IDENTITY : i
SYMBOL : ,
IDENTITY : j
SYMBOL : ;
BASIC : float
IDENTITY : x
SYMBOL : ;
BASIC : float
SYMBOL : [
DIGIT : 100
SYMBOL : ]
IDENTITY : a
SYMBOL : ;
// line 3 while ( true) {
KEYWORD : while
SYMBOL : (
KEYWORD : true
SYMBOL : )
SYMBOL : {
// line 4 do i = i + 1; while ( a[i] < x);
KEYWORD : do
IDENTITY : i
SYMBOL : =
IDENTITY : i
SYMBOL : +
DIGIT : 1
SYMBOL : ;
KEYWORD : while
SYMBOL : (
IDENTITY : a
SYMBOL : [
IDENTITY : i
SYMBOL : ]
SYMBOL : <
IDENTITY : x
SYMBOL : )
SYMBOL : ;
// line 5 if ( i >= j ) break;
KEYWORD : if
SYMBOL : (
IDENTITY : i
SYMBOL : >=
IDENTITY : j
SYMBOL : )
KEYWORD : break
SYMBOL : ;
// line 6 x = a[i];
IDENTITY : x
SYMBOL : =
IDENTITY : a
SYMBOL : [
IDENTITY : i
SYMBOL : ]
SYMBOL : ;
// line 7 }
SYMBOL : }
// line 8 }
SYMBOL : }
可以發(fā)現(xiàn)輸出結(jié)果是完全正確的。
測(cè)試樣例2:測(cè)試數(shù)字
+1212.551e1589
輸出:
DIGIT : +1212.551e1589
好,到此,我們就完成了本次實(shí)驗(yàn)任務(wù),一個(gè)簡(jiǎn)單的詞法分析器的設(shè)計(jì),在設(shè)計(jì)過(guò)程中,我們使用到了Trie樹這一數(shù)據(jù)結(jié)構(gòu),使得代碼變得美觀了許多,同時(shí),針對(duì)較為復(fù)雜的數(shù)字讀取行為,我們?cè)O(shè)計(jì)了一個(gè)DFA確定的有限狀態(tài)自動(dòng)機(jī)完成,最終,我們?cè)趍ain函數(shù)中,將他們拼接起來(lái),就形成了最后的詞法分析器,整個(gè)實(shí)驗(yàn)用時(shí)半天,整體思想并不難理解,相信大家如果從頭看到此處應(yīng)該邏輯會(huì)相當(dāng)清晰。
-
分析器
+關(guān)注
關(guān)注
0文章
93瀏覽量
12532 -
有限狀態(tài)自動(dòng)機(jī)
+關(guān)注
關(guān)注
0文章
2瀏覽量
921
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論