实验一 词法分析器

来源:互联网 发布:虚拟狙击软件 编辑:程序博客网 时间:2024/05/23 20:50

一、实验目的
  (1)理解词法分析在编译程序中的作用;
  (2)加深对有限自动机模型的理解;
  (3)掌握词法分析程序的实现方法和技术。
  
二、开发语言及实现平台或实验环境
      操作系统:Win7;
      开发工具:codeblocks 10.05 ;
     内存:512M
      CPU:p(D)2.8hz
  
实验内容  
   输入:根据教学要求和学生具体情况,从具有代表性的高级程序设计语言中,选取一个适当大小的子集,例如可以选取一类典型单词,也可以尽可能使各种类型的单词都能兼顾到。
   
   输出:单词串的输出形式,所输出的每一单词均按形如(CLASS,VALUE)的二元式编码。对于变量和常数,CLASS字段为相应的类别码,VALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。对于关键字和分隔符,采用一词一类的编码形式。由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。不过,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上直接放置单词符号串本身。
   

 

描述语言的文法
关键字:   本程序识别的关键字为int  float  char main if else switch case printf return ,仅当单独出现以上标识符时识别为关键字,对于inta,ifb等识别为标识符。 
标识符:   一个标识符必须以字母开头,后面接上字母和数字,否则产生报错信息,程
                 序停止词法分析,输出相关错误信息
                 如: 正确:abc, abc123, 等,错误:123abc
操作符:   本程序识别的操作符为:   +  -  /  *  |  & = < >  
分隔符:   本程序识别的分隔符为:   (  )  {  }  ;  : ,  “
数字:     识别的数字遵循以下文法规则:
          digit       0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
          intnumber  digit+      
          exponent    (E|e) ( + | - |  ) digit+
          fraction    . digit+realnumber  digit+ exponent | digit+ fraction ( exponent |  )
          例如:正确: 123, 123E2, 123.3123.3E4
                错误: 123A,123E, 123.A . 123.3A, 123.3E
    <标识符>→<字母><字母数字串>
    <字母数字串>→<字母><字母数字串>|<数字><字母数字串>|ε
    <无符号整数>→<数字>|<数字><无符号整数>
    <运算符>→ + | - | * | / | =
    <界符>→ , | ; | ( | ) | { | }
五、单词分类码表
  


 

六、状态转换图及状态矩阵
  由描述无符号常数的正规文法构造状态转换图如下:







七、源程序
要求:1、在此只写出核心的算法程序,要求有必要的注释;代码字体使用courier new,并且代码必须放在文本框中,要求文本框边框无颜色。
    2、全部的源程序,与实验报告放在同一文件夹下,文件夹命名原则为
      计科1101班11150001王一,注意没有任何空格

#include <iostream>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;#define num 5#define num0 3#define num1 9char *KeyWords[num]= {"begin","end","if","then","else" }; //关键字char ope[num0]= {'<','=','>'}; //操作符char edgesign[num1]= {';',',','(',')','"','{','}'}; //分隔符不含换行,空格int t; //用作判断是否为两位操作符的标记int zhuanhuan(int a) //十进制转二进制 快速转换{    int n,i,len,pow2;    char tag[1000];    memset(tag,'0',sizeof(tag));    pow2=1;    for(i=0;pow2<=a;i++)    pow2<<=1;    tag[i]='\0';    len=i-1;    while(a>0)    {        if(a>=pow2)        {            tag[len-i]='1';            a-=pow2;        }        i--;        pow2>>=1;    }    a=atoi(tag);   // printf("%d\n",a);    return a;}int Key(char *word) //确定是否为关键字{    for(int i=0; i< num; i++)        if(!strcmp(KeyWords[i],word))        {            printf("(%d,\"%s\")\n",i+1,word);return 1;        }    return 0;}int yun(char word) //确定是否为操作符{    for(int i=0; i<num0; i++)        if(ope[i]==word)            return 1;    return 0;}int Sign(char word) //确定 是否为分隔符符{    for(int i=0; i<num1; i++)        if(edgesign[i]==word)            return 1;    return 0;}void out2(char word)   // 14为分隔符{    if(Sign(word))    {        printf("(14,\"%c\")\n",word);    }}void out3(char word1,char word2) //输出操作符{    if(yun(word1)&&yun(word2))  //判断是否为两位的操作符    {        t=0;        if(word1=='<'&&word2=='=')            printf("(9,\"%c%c\")\n",word1,word2);        else if(word1=='<'&&word2=='>')            printf("(11,\"%c%c\")\n",word1,word2);        else if(word1=='>'&&word2=='=')            printf("(13,\"%c%c\")\n",word1,word2);    }    else if(yun(word1)&&!yun(word2)&&(t>1))  //判断是否为一位操作符    {        for(int i=0; i<num0; i++)            if(ope[i]==word1)                printf("(%d,\"%c\")\n",8+i*2,word1);    }}void out1(char *word,int Len) //7为无符号数,6为标识符{    int a,len;    char s[100];    if(!Key(word))    {        if( word[0]=='\'' && word[Len-1]=='\'')             //字符常量            {printf("(7,\"%s\")\n",word);}        else     if((a=atoi(word)))//字符串转化为数字        {            itoa(a,s,10);            if(strlen(s)!=strlen(word))               {printf("(输入错误,\"%s\")\n",word);}            else            {                a=zhuanhuan(a);                printf("(7,\"%d\")\n",a);            }        }        else        {            if(word[0]!='\0') printf("(6,\"%s\")\n",word);        }    }}int Scan(){    FILE *fp;    char temp[10],ch='1',temp1;    char filename[20]="input1.txt";    int i,j,m;    temp[0]='\0';    printf("请输入文件名\n");    //scanf("%s",filename);    if((fp=fopen(filename,"r"))==NULL)    {        printf("文件打开失败\n");        return 0;    }    t=2;m=1;    while(ch!=EOF)    {        j=0;i=0;t++;        if(m)        {            m=0;ch=fgetc(fp);    //从流中读取一个字符        }        while(!Sign(ch)&&!yun(ch)&&(ch!=' ')&&ch!=9&&ch!='\n'&&ch!=EOF)        {            temp[i]=ch;            temp[i+1]='\0';            ch=fgetc(fp);            i++;        }        out1(temp,i);        temp[0]='\0';//清除字串        temp1=ch;        ch=fgetc(fp);        out3(temp1,ch);        out2(temp1);        temp1='\0';//清除字符    }    fclose(fp);    return 1;}int main(){    Scan();    getchar();    getchar();}

 

 

八、调试过程及实验结果

要求:  要给出2-3个不同的测试用例,并且给出输出结果。

 

 input1.txt                                    input2.txt

                                             

 

九、总结与体会

   通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。


                                             
1 0
原创粉丝点击