?? 詞法分析程序.txt
字號:
//這是我編譯原理的一次作業,中間有許多不足之處希望大家指正
/*編寫PL/0語言的詞法分析程序
要求:
1、讀入用PL/0語言編寫的源程序,正確的進行詞法分析,并輸出二元式序列。
2、若源程序有詞法錯誤,能夠給出出錯的準確位置。
3、詞法代號如下
( , );
(-,-);
(*,*);
(/,/);
((,();
(),));
(,,,);
(;,;);
(.,.);
(#,#);
(=,=);
(>,>);
(<,<);
(:=,a);
(>=,b);
(<=,c);
(數字,d);
(標識符,e);
關鍵字代號:
(begin,f);
(call,g);
(const,h);
(do,i);
(end,j);
(if,k);
(odd,l);
(procedure,m);
(read,n);
(then,o);
(var,p);
(while,q);
(write,r);
4、等于運算符號為一個 =
測試程序:
A.C
======================
CONST A=10;
VAR B,C;
PROCEDURE P;
VAR D;
PROCEDURE Q;
VAR X;
BEGIN
READ(X);
D:=X;
WHILE X<0
DO CALL P;
END;
BEGIN
WRITE(D);
CALL Q;
END;
BEGIN
CALL P;
END.
*/
/*program name:chifufenxi*/
/*作者:小萬 qq:421404493*/
/*date:2004.10.11*/
#include<sio.h>
#include<slib.h>
#include<conio.h>
#include<ctype.h>
#include<sing.h>
#define N 256//每一行的字符數不能超過256個
char buffer[N]; //用作存放一行字符
char word[20]; //用作存放經過分析單詞
char *kword[13]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"};
char ktype[13]={'f','g','h','i','j','k','l','m','n','o','p','q','r'};
int len;//記錄每一行的長度
int count=0;//用來記錄行數
void write(char *ws,char wc,FILE *wout)//將分析結果按照規則寫入到文件
{
fputc('(',wout);
fputs(ws,wout);
fputc(',',wout);
fputc(wc,wout);
fputc(')',wout);
}
int readbuffer(FILE *fp)
{
char ch;
len=0;
ch=fgetc(fp);
while(!feof(fp) && ch!='\n')//讀取字符到緩沖區
{
buffer[len]=ch;
ch=fgetc(fp);
len ;
}
len--;//用來控制詞法分析時行分析中字母的個數
if(feof(fp))//標志文件是否結束
return 0;
else
return 1;
}
void error(int type)
{
if(type==1)
printf("為無效字符,第%d行詞法出錯,標志符不能以數字開頭\n",count);
else if(type==2)
printf("第%d行詞法出錯,賦值符應為\:\= \n ",count);
else printf("為無效字符,第%d行詞法出錯\n",count);
}
void check(char *s,FILE *out);//聲明函數,此函數用來分類單詞
void fenxi(char *row,FILE *op)//此函數用來對每一行的單詞進行語法分析
{
//printf("%d\n",count);
int k=0;//用作控制臨時存放單詞的變量s0
int i=0;//定義兩個變量用作控制每一行是否結束,
int ferror=0;//用作出錯標志
char s0[20];//臨時存放單詞的變量
while(i<=len)
{
k=0;//將k置0
scpy(word,"\0");//將存放單詞的變量清空
/*去除空格*/
if(isspace(row[i]))//去出空格,跳格符,換行符
{
i ;
continue;
}
/*去出無效字符*/
while(!isalpha(row[i])&&!isdigit(row[i])&&i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]==' ' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))
{
putchar(row[i]);
i ;
ferror=1;//設置錯誤標志符
}
if(ferror==1)
{
error(3);//調用出錯處理函數
ferror=0;
}
/*對注釋進行處理,假設此語言的注釋只能單行注釋以雙斜杠“//”為注釋開始標志*/
if(row[i]=='/')
{
i ;
if(row[i]=='/')
{
i=len 1;//忽略注釋符后面的單詞
continue;
}
else
i--;
}
/*判斷是否為數字*/
if(isdigit(row[i]))
{
while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]==' ' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))
//當不到行尾,是數字或字母當然有可能是
無效字符
{
if(isdigit(row[i]))//是數字則將字符逐個存入臨時數組
{
s0[k]=row[i];
i ;
k ;
// putchar('e');
}
else //數字中加有字母或無效字符則報錯
{
// putchar('x');
ferror=1;break;//已經出錯設置標志并退出循環
}
}
if(ferror==1)//檢測是否出錯
{ /*將剛剛的那個單詞后面的數字和字母
清空,如123abc123或則123$$23等,當出現錯誤后,需
要消除abc123和$$23 以免誤作為下一個標志符*/
for(int j=0;j<k;j )
putchar(s0[j]);
while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]==' ' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))
{
putchar(row[i]);
i ;
}
error(1);//putchar('e');//調用出錯處理函數
ferror=0;//重新設置錯誤標志位
//i--;//scpy(word,"");
}
else//未出錯照常處理
{
s0[k]='\0';
scpy(word,s0);
i--;//減一是為了使最后取出的那個字符不在被下面的程序判斷
// s0[0]='\0';
}
}
/*判斷是否為標志符和關鍵字即由字母開頭并且不含標點符號用ispunct(int ch)判斷標點符號*/
if(isalpha(row[i]))//標志符或關鍵字由字母開頭
{
k=0;
while(i<=len&&row[i]!=32&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]==' ' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))//關鍵字和標志符由數字和字母組成
{
if(isalpha(row[i])||isdigit(row[i]))//由數字和字母組成
{
s0[k]=row[i];
i ;
k ;
}
else//出錯,原因可能是出現了不可識別的字符
{
ferror=1;break;
}
}
if(ferror)
{
for(int j=0;j<k;j )
putchar(s0[j]);
while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]==' ' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))
{
putchar(row[i]);//消除整個非法單詞
i ;
}
ferror=0;
error(3);
//i--;
}
else
{
s0[k]='\0';
scpy(word,s0);
s0[0]='\0';
i--;
}
}
/*判斷運算符*/
if(row[i]==' ' ||row[i]=='-' ||row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'||row[i]=='.'||row[i]=='#' || row[i]=='=')
{
s0[0]=row[i];
s0[1]='\0';
scpy(word,s0);
s0[0]='\0';
}//要先判斷單個字符的運算符,以避免諸如>=的運算符后面的=再次被判斷
if(row[i]==':')
{
i ;
if(row[i]=='=')
{
//word[0]=':';
//word[1]='=';
//word[2]='\0';
scpy(word,">=");
}
else
{
error(2);//出錯后調用處理函數
i--;
}
}
if(row[i]=='>')
{
i ;
if(row[i]=='=')
{
scpy(word,">=");
}
else
{
scpy(word,">");
i--;
}
}
if(row[i]=='<')
{
i ;
if(row[i]=='=')
{
scpy(word,"<=");
}
else
{scpy(word,"<");i--;}
}
//puts(word);
check(word,op);/*
調用分類函數,辨別每一個單詞的類別要求
輸入的每一個單詞必須符合詞法規則*/
//word[0]='\0';
i ;//使指針后移,取出下一個字母
}
}
void check(char *s,FILE *out)
{
if(isdigit(s[0]))/*如果第一個字符是數字那么整個單詞都是數字組成的,即為常數*/
{
write(s,'d',out);//調用寫函數將分好類的單詞寫入文件
}
if(isalpha(s[0]))/*如果第一個字符是字母,那么這個單詞是標志符或關鍵字*/
{
int fyiyong=0;//用作標記這個單詞是否已被分類
/*以下判別是否是關鍵字*/
for(int ct=0;ct<13;ct )
{
if(!scmp(s,kword[ct]))
{
write(s,ktype[ct],out);
fyiyong=1;
}
}
/*經過以上判別,可以判別是否是關鍵字,不是即為標志符*/
if(fyiyong!=1)
{
write(s,'e',out);
}
}
/*以下對運算符分類*/
if(s[0]=='>')
{
if(s[1]=='=')
{
write(s,'b',out);
}
else
{
write(s,'>',out);
}
}
if(s[0]=='<')
{
if(s[1]=='=')
{
write(s,'c',out);
}
else
{
write(s,'<',out);
}
}
if(!scmp(s,":="))
{
write(s,'a',out);
}
if(s[0]==' ' || s[0]=='-' || s[0]=='*' || s[0]=='/' || s[0]=='(' || s[0]==')' || s[0]==',' || s[0]==';'|| s[0]=='.'|| s[0]=='#' || s[0]=='=' )
{
write(s,s[0],out);
}
}
void main()
{
count=1;
char scfilename[20],rsfilename[20];//定義用來存放輸入源文件和輸出目標文件的名字
printf("Please input your source file name:");
gets(scfilename);
printf("Please input your result file name:");
gets(rsfilename);
FILE *fp,*op;
fp=fopen(scfilename,"r");
op=fopen(rsfilename,"w");
if(fp)//打開文件成功后調用函數對源文件進行詞法分析
{
while(readbuffer(fp))
{
fenxi(buffer,op);
count ;//行加一
}
}
else//while the file not exist
{
printf("Your souce file not exist!!!\n");
exit(0);
}
fclose(fp);//close the files
fclose(op);
printf("ok!");//output the mark of end
getchar();
}
{
write(s,'b',out);
}
else
{
write(s,'>',out);
}
}
if(s[0]=='<')
{
if(s[1]=='=')
{
write(s,'c',out);
}
else
{
write(s,'<',out);
}
}
if(!scmp(s,":="))
{
write(s,'a',out);
}
if(s[0]==' ' || s[0]=='-' || s[0]=='*' || s[0]=='/' || s[0]=='(' || s[0]==')' || s[0]==',' || s[0]==';'|| s[0]=='.'|| s[0]=='#' || s[0]=='=' )
{
write(s,s[0],out);
}
}
void main()
{
count=1;
char scfilename[20],rsfilename[20];//定義用來存放輸入源文件和輸出目標文件的名字
printf("Please input your source file name:");
gets(scfilename);
printf("Please input your result file name:");
gets(rsfilename);
FILE *fp,*op;
fp=fopen(scfilename,"r");
op=fopen(rsfilename,"w");
if(fp)//打開文件成功后調用函數對源文件進行詞法分析
{
while(readbuffer(fp))
{
fenxi(buffer,op);
count ;//行加一
}
}
else//while the file not exist
{
printf("Your souce file not exist!!!\n");
exit(0);
}
fclose(fp);//close the files
fclose(op);
printf("ok!");//output the mark of end
getchar();
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -