(接上篇)根據這個表來構造程序,程序的核心是下面的這個函數,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
/********************************************************************
以下爲主分析函數
從輸入文件裏面讀,把分析結果寫到輸出文件中
參數:fpin :輸入文件指針 fpout: 輸出文件指針
********************************************************************/
void parse(FILE* fpin,FILE* fpout)
{
char arr[MAXBUF];//讀出的最長的字符串不超過MAXBUF,MAXBUF定義爲255,夠長了我想
int i=0;//分析含字母的字符串用
int j=0;//分析純數字的字符串用
while(1)
{
fscanf(fpin,"%c",&ch);//從輸入文件中讀入一個字符
if( ch==' '|| ch =='/t')//過濾掉空格和tab
;
else if( ch=='/n')//回車換行符,爲下面進行錯誤判斷
lineno++;
else if( IsDigit(ch))//讀入的是數字
{
while(IsDigit(ch))
{
arr[j] = ch;
j++;
fscanf(fpin,"%c",&ch);
}
fseek(fpin,-1L,SEEK_CUR);//文件指針後退一個字節
char* temp1 =(char*)malloc(j+1);/
memcpy(temp1,arr,j);
temp1[j] ='/0';//把數組裏面的內容拷貝到連外一個數組裏面,因爲我定義的
//arr爲255個字節,實際上寫不到那麼多,所以只拷貝實際上有數據的
j=0;//恢復初始狀態,以備下次使用
fprintf(fpout,"%s/t/t%d/n",temp1,2);//常數
free(temp1);//釋放內存
}
else if(IsAlpha(ch))//是字母開頭的
{
while(IsAlpha(ch) || IsDigit(ch))
{
arr[i] =ch;
i++;
fscanf(fpin,"%c",&ch);
}
fseek(fpin,-1L,SEEK_CUR);
char* temp = (char*)malloc(i+1) ;
memcpy(temp,arr,i);
temp[i] ='/0';
i=0;
/*基本思想同處理數字的*/
if(FindOK(temp))//FindOK函數在關鍵字表中查找和temp字符串相同的,找到就返回類別編號
{
fprintf(fpout,"%s/t/t%d /n",temp,FindOK(temp));
}
else
{
fprintf(fpout,"%s/t/t%d/n",temp,1);//標示符號
}
free(temp);
}
//以下爲2字節的運算符號
else if( ch==':')//符號“:=”
{
fscanf(fpin,"%c",&ch);
if(ch=='=')
fprintf(fpout,"%s/t/t%d/n",":=",20);
else
fprintf(fpout,"error in compileing %d lines unknown character %c /n",lineno,ch);//出錯了
}
else if(ch=='>')//符號 “> “ 和”>=”
{
fscanf(fpin,"%c",&ch);
if(ch=='=')
fprintf(fpout,"%s/t/t%d/n",">=",16);
else
fprintf(fpout,">/t/t15/n");
}
else if( ch=='<') //符號 “< “ 和”<=”
{
fscanf(fpin,"%c",&ch);
if(ch=='=')
{fprintf(fpout,"<=/t/t18/n");}
else if( ch=='>')
{fprintf(fpout,"<>/t/t19");}
else
{fprintf(fpout,"</t/t19/n");}
}
else {
//以下爲一個字節的運算符號
if(ch=='-') {fprintf(fpout,"%s/t/t%d/n",'-',10);continue;}//在文件中輸出爲“- 10”
if(ch==';') {fprintf(fpout,";/t/t21/n");continue;}
if(ch=='+') {fprintf(fpout,"+/t/t9/n");continue;}
if(ch=='*') {fprintf(fpout,"*/t/t11/n");continue;}
if(ch=='/') {fprintf(fpout,"/ /t/t12/n");continue;}
if(ch=='(') {fprintf(fpout,"(/t/t13/n");continue;}
if(ch==')') {fprintf(fpout,")/t/t14/n");continue;}
if(ch=='.') {fprintf(fpout,"./t/t22/n");continue;}
if(ch==',') {fprintf(fpout,",/t/t23/n");continue;}
if(ch=='#') break;//分析結束
else fprintf(fpout,"error in compiling %d lines unknown character %c /n",lineno,ch);//出錯了,輸出出錯信息
}
}
}
以上代碼在VISUAL C++6.0 +WIN2000下編譯通過.
下面我們用該程序對下面的代碼進行詞法分析,該代碼保存爲test.txt,假設編譯後的應用程序爲lex.exe,
program test
begin
3j := 200 ;
if(j > 100) then
j := 300&&&&
else
j := 107870
gyt768%^
end. #
在命令行下輸入源文件名,test.txt.以及輸出文件名:output.txt可以看到下面的結果.
program 6
test 1
begin 7
3 2
j 1
:= 20
200 2
; 21
if 3
( 13
j 1
> 15
100 2
) 14
then 4
j 1
:= 20
300 2
error in compiling 4 lines unknown character &
error in compiling 4 lines unknown character &
error in compiling 4 lines unknown character &
error in compiling 4 lines unknown character &
else 5
j 1
:= 20
107870 2
gyt768 1
error in compiling 7 lines unknown character %
error in compiling 7 lines unknown character ^
end 8
. 22
該函數是詞法分析程序的核心,它可以識別出源程序中的編寫錯誤,以及找出關鍵字,變量等.具體請看源代碼,註釋很詳細,但是肯定有不足的地方,請大家不吝賜教。有什麼問題,可以給我發郵件。。我的email:[email protected],