编译原理 - 实验一 - 手工词法分析器

一、词法分析器词法规则及状态图

单词符号:

标识符:字母开头,后接字母或数字。

保留字: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");
}

 

posted @ 2015-04-25 11:02  昝志立  阅读(1711)  评论(0)    收藏  举报