编译原理实验一 词法分析

烂漫一生 提交于 2020-01-29 12:28:57

一、 实验目的

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 

二、 实验题目

如源程序为C语言。输入如下一段:

main()

{

int  a=-5,b=4,j;

if(a>=b)

j=a-b;

else  j=b-a;

}

 

要求输出如下:

(”main11    

(”(”5     

(”)”5

(”{5)       

(”int12     

(”a2

(”=4      

(”-53      

(”,5

(”b2      

(”=4       

(”43

(”,5       

(”j2        

(”;5

(”if1      

(”(”5      

(”a2

(”>=4    

(”b2       

(”)”5

(”j2       

(”=4       

(”a2

(”-4       

(”b2       

(”;5

(”else1 

(”j2         

(”=4

(”b2      

(”-4        

(”a2

(”;5        

(”}5

三、 实验理论依据

()识别各种单词符号

1、 程序语言的单词符号一般分为五种:

(1) 关键字(保留字/ 基本字)if 、while 、begin…

(2) 标识符:常量名、变量名…

(3) 常数:34 、56.78 、true 、‘a’ 、…

(4) 运算符:+ 、- 、* 、/ 、〈 、and 、or 、….

(5) 界限符:,  ;  (   )  {    }   /*…

2、 识别单词:掌握单词的构成规则很重要 

(1) 标识符的识别:字母| 下划线+( 字母/ 数字/ 下划线)

(2) 关键字的识别:与标识符相同,最后查表 

(3) 常数的识别 

(4) 界符和算符的识别 

3、 大多数程序设计语言的单词符号都可以用转换图来识别,如图1-1 

 

1-1

 

4、 词法分析器输出的单词符号常常表示为二元式:(单词种别,单词符号的属性值)

(1) 单词种别通常用整数编码,如1 代表关键字,2 代表标识符等 

(2) 关键字可视其全体为一种,也可以一字一种。采用一字一种得分法实际处理起来较为方便。 

(3) 标识符一般统归为一种 

(4) 常数按类型(整、实、布尔等)分种 

(5) 运算符可采用一符一种的方法。 

(6) 界符一般一符一种的分法。 

()超前搜索方法

1、 词法分析时,常常会用到超前搜索方法。

如当前待分析字符串为“a>+” ,当前字符为“>” ,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢? 

显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符’+’ ,这时可知应将’>’ 解释为大于运算符。但此时,超前读了一个字符’+’ ,所以要回退一个字符,词法分析器才能正常运行。又比如:‘+’ 分析为正号还是加法符号 

()预处理

预处理工作包括对空白符、跳格符、回车符和换行符等编辑性字符的处理,及删除注解等。由一个预处理子程序来完成。

参考代码:

#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#define NULL 0
FILE *fp;
char cbuffer;
char *key[24]= {"main","int","if","else","for","while","do","return","break","continue","auto","double","struct",
                "long","switch","case","register","typedef","char","extern","union","const","short","null"
               };///t增加了关键字
int atype,id=4;

int search(char searchchar[ ],int wordtype)  /*判断单词是保留字还是标识符*/
{
    int i=0;
    int p;
    switch (wordtype)
    {
    case 1:
        for (i=0; i<=21; i++)
        {
            if (strcmp(key[i],searchchar)==0)
            {
                p=i+1;    /*是保留字则p为非0且不重复的整数*/
                break;
            }
            else p=0;             /*不是保留字则用于返回的p=0*/
        }
        return(p);
    }
}


char  alphaprocess(char buffer)
{
    int   atype;   /*保留字数组中的位置*/
    int   i=-1;
    char  alphatp[20];
    while ((isalpha(buffer))||(isdigit(buffer))||buffer=='_')
    {
        alphatp[++i]=buffer;
        buffer=fgetc(fp);
    }  /*读一个完整的单词放入alphatp数组中*/
    alphatp[i+1]='\0';
    atype=search(alphatp,1);/*对此单词调用search函数判断类型*/
    if(atype!=0)
    {
        printf("(%s, 1,%d)\n",alphatp,atype-1);

        id=1;
    }
    else
    {
        printf("(%s ,2)\n",alphatp);
        id=2;
    }
    return(buffer);
}

char digitprocess(char buffer)
{
    int i=-1;
    char digittp[20];
    while (isdigit(buffer)||((buffer=='.')&&i!=-1))
    {
        digittp[++i]=buffer;
        buffer=fgetc(fp);
    }
    digittp[i+1]='\0';
    printf("(%s ,3)\n",digittp);
    id=3;
    return(buffer);
}

char otherprocess(char buffer)
{
    char ch[20];
    ch[0]=buffer;
    ch[1]='\0';
    if(ch[0]==','||ch[0]==';'||ch[0]=='{'||ch[0]=='}'||ch[0]=='('||ch[0]==')')
    {
        printf("(%s ,5)\n",ch);
        buffer=fgetc(fp);
        id=4;
        return(buffer);
    }
    if(ch[0]=='*'||ch[0]=='/')
    {
        buffer=fgetc(fp);
        ch[1]=buffer;
        if(ch[1]=='=')
        {
            ch[2]='\0';
            printf("(%s ,4)\n",ch);
            buffer=fgetc(fp);
            id=4;
            return(buffer);
        }
        else
        {
            ch[1]='\0';
            printf("(%s ,4)\n",ch); /// t*= /=也被判断
        }
        id=4;
        return(buffer);
    }
    if(ch[0]=='='||ch[0]=='!'||ch[0]=='<'||ch[0]=='>')
    {
        buffer=fgetc(fp);
        if(buffer=='=')
        {
            ch[1]=buffer;
            ch[2]='\0';
            printf("(%s ,4)\n",ch);
        }
        else if(buffer =='>' || buffer =='<')
        {
            ch[1]=buffer;
            ch[2]='\0';
            printf("(%s ,4)\n",ch); ///t >> <<判断
        }
        else
        {
            printf("(%s ,4)\n",ch);
            id=4;
            return(buffer);
        }
        buffer=fgetc(fp);
        id=4;
        return(buffer);
    }

    if(ch[0]=='+'||ch[0]=='-')
    {
        if(id==4)  /*在当前符号以前是运算符,则此时为正负号*/
        {
            buffer=fgetc(fp);
            ch[1]=buffer;
            ch[2]='\0';
            printf("(%s ,3)\n",ch);
            id=3;
            buffer=fgetc(fp);
            return(buffer);
        }
        else if(ch[1] =='=')///*增加判断 t+= -=*/
        {
            ch[2]='\0';
            printf("(%s ,4)\n",ch);
        }
        else if(ch[1] =='+' ||ch[1] =='-')
        {
            ch[2]='\0';
            printf("(%s ,4)\n",ch);///*增加判断 t++ --*/
        }
        else
        {
            ch[1]='\0';///此时为加减运算符
            printf("(%s ,4)\n",ch);
            id=4;
            return(buffer);
        }
        id=4;
        buffer=fgetc(fp);
        return(buffer);
    }
}


int   main()
{
    if ((fp=fopen("input.txt","r"))==NULL)   /*只读方式打开一个文件*/
        printf("error");
    else
    {
        cbuffer = fgetc(fp);  /*fgetc( )函数:从磁盘文件读取一个字符*/
        while (cbuffer!=EOF)
        {
            if(cbuffer==' ' ||cbuffer=='\n')   /*掠过空格和回车符*/
                cbuffer=fgetc(fp);
            if(isalpha(cbuffer))
                {cbuffer=alphaprocess(cbuffer);}
            else if (isdigit(cbuffer))
                cbuffer=digitprocess(cbuffer);
            else {cbuffer=otherprocess(cbuffer);}
        }
        getchar();
    }
}

 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!