编译原理 - 实验一 - 手工词法分析器
一、词法分析器词法规则及状态图
⑴单词符号:
标识符:字母开头,后接字母或数字。
保留字:if、else、for、while、do、int。
无符号整数:由0~9数字组成。
分界符:如+、-、*、/、(、)、;、,等单分界符,还有双字符分界符》=、《=、!=、==等。
注释符:用/*和*/括起。
⑵正则文法:
<identifier>::=<letter>|<identifier><letter>|<identifier><digit>
<number>::=<digit>|<number><digit>
<letter>::=a|b|…z|A|B|…|Z
<digit>::= 1|2|…|9|0
<singleword>::=+|-|*|/|=|(|)|{|}|:|,|;|<|>|!
<doubleword>::=>=|<=|!=|==
<comment_first>::= /*
<comment_last>::= */
转换后:
<identifier>::=a|b|…|z
|<identifier>a|…|<identifier>z
|<identifier>0|…|<identifier>9
<number>::=0|1|…|9|<number>0|…|<number>9
<doubleword>::=<greater>=|…
<greater>::=>
<equal>::==
⑶状态图:
各条词法规则的状态图

单词符号的状态图

二、实现功能
(1)在命令行中输入源程序文件名(包括文件名路径)
(2)输入目标文件名(包括文件名路径)
(3)调用所编词法分析代码将分析结果写入目标文件代码(编译完成)
三、词法分析程序的算法思想
算法的基本任务是从源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,分析与代码中相应的单词符号。
3.1 主程序示意图:

3.2词法分析示意图:

四、测试
⑴P37.例3-3
①将输入文件AAA.T与cpp文件放置于同一文件夹中
AAA.T(也可以为txt文件类型)内容:
{
int a;
a=10;
}
②通过VC 6.0建立项目,并输入代码,编译并运行程序(此处用了VS2010,功能一样)

③查看输出文件aaa.txt内容
{ {
int int
ID a
; ;
ID a
= =
NUM 10
; ;
} }
⑵P61.6
① 首先对代码适当修改
char *keyword[keywordSum]={"if","else","for","while","do","int","read","write"};
char singleword[50]="+-*(){};,: !";
char doubleword[10]="><= &|";
并在输入文件abc.txt中输入
int i=10;
do{
printf(i);
i++;
}while(i!>10)
if(1<2&&2<4)
else(1||2)
② 然后编译并运行

① 查看输出文件bbb.txt
int int
ID i
= =
NUM 10
; ;
do do
{ {
ID printf
( (
ID i
) )
; ;
ID i
+ +
+ +
; ;
} }
while while
( (
ID i
! !
> >
NUM 10
) )
if if
( (
NUM 1
< <
NUM 2
& &
& &
NUM 2
< <
NUM 4
) )
else else
( (
NUM 1
| |
| |
NUM 2
) )
五、代码
词法分析子程序
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define keywordSum 8
char *keyword[keywordSum]={"if","else","for","while","do","int","read","write"};
char singleword[50]="+-*(){};,:"; //!
char doubleword[10]="><=!"; //& |
extern char Scanin[300],Scanout[300];
extern FILE * fin, *fout;
int TESTscan(){
char ch,token[40];
int es=0,j,n;
printf("请输入源程序文件名(包括路径):");
scanf("%s",Scanin);
printf("请输入词法分析输出文件名(包括路径):");
scanf("%s",Scanout);
if((fin=fopen(Scanin,"r"))==NULL){
printf("\n打开词法分析输入文件出错\n");
return(1);
}
if((fout=fopen(Scanout,"w"))==NULL){
printf("\n创建词法分析输出文件出错!\n");
return(2);
}
ch=getc(fin);
while(ch!=EOF){
while(ch==' ' || ch=='\n' || ch=='\t') ch=getc(fin);
if(isalpha(ch)){
token[0]=ch; j=1;
ch=getc(fin);
while(isalnum(ch)){
token[j++]=ch;
ch=getc(fin);
}
token[j]='\0';
n=0;
while((n<keywordSum) && strcmp(token,keyword[n]))
n++;
if(n>=keywordSum)
fprintf(fout,"%s\t%s\n","ID",token);
else
fprintf(fout,"%s\t%s\n",token,token);
}
else
if(isdigit(ch)){
token[0]=ch;j=1;
ch=getc(fin);
while(isdigit(ch)){
token[j++]=ch;
ch=getc(fin);
}
token[j]='\0';
fprintf(fout,"%s\t%s\n","NUM",token);
}else
if(strchr(singleword,ch)>0){
token[0]=ch;token[1]='\0';
ch=getc(fin);
fprintf(fout,"%s\t%s\n",token,token);
}else
if(strchr(doubleword,ch)>0){
token[0]=ch;
ch=getc(fin);
if(ch=='='){
token[1]=ch;
token[2]='\0';
ch=getc(fin);
}else
token[1]='\0';
fprintf(fout,"%s\t%s\n",token,token);
}else
if(ch=='/'){
ch=getc(fin);
if(ch=='*'){
char ch1;
ch1=getc(fin);
do
{
ch=ch1;
ch1=getc(fin);
}while((ch!='*' || ch1!='/') && ch1!=EOF);
ch=getc(fin);
}else
{
token[0]='/';
token[1]='\0';
fprintf(fout,"%s\t%s\n",token,token);
}
}else
{
token[0]=ch;
token[1]='\0';
ch=getc(fin);
es=3;
fprintf(fout,"%s\t%s\n","ERROR",token);
}
}
fclose(fin);
fclose(fout);
return(es);
}
主程序
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<windows.h>
extern int TESTscan();
char Scanin[300],Scanout[300];
FILE *fin, *fout;
int main(){
int es=0;
es=TESTscan();
if(es>0)
printf("词法分析有错,编译停止!");
else
printf("词法分析成功!\n");
system("pause");
}

浙公网安备 33010602011771号