实验一:词法分析设计

1.[实验目的]:

    1.了解词法分析的主要任务。
    2. 熟悉编译程序的编制。
  [实验内容]:根据某文法,构造一个基本词法分析程序。找出该语言的关键字、标识符、整数以及其他一些特殊符号,给出单词表(内容包括单词种类和值),构造符号表(内容包括name、kind、value和address等)。

2.C 语言文法

G[<程序>]:

<程序>→main(){<声明部分><语句部分>}

<声明部分>→<声明部分><常量声明部分>| <声明部分><变量声明部分>|<空>

<常量声明部分>→const<常量定义>{,<常量定义>};

<常量定义>→<类型> <标识符>=<无符号整数>;

<无符号整数>→<数字>{<数字>}

<变量声明部分>→<类型><标识符>{,<标识符>};

<类型>→int|float|double|long|long long|char|bool

<标识符>→<字母>{<字母>|<数字>}

<语句部分>→<条件语句>|<while循环语句>|<for循环语句>|输入语句|输出语句|复合语句|<赋值语句>

<条件语句>→if (<表达式>) <语句>;|if(<表达式>) else <语句>;

<while循环语句>→while(<表达式>){<语句>}

<for循环语句>→for(<表达式>;<表达式>;<表达式>){<语句>}

<复合语句>→{<语句部分>}

<赋值语句>→<表达式>

<表达式>→<标识符>=<算数表达式>|<布尔表达式>

<布尔表达式>→<算数表达式>|<算数表达式><关系运算符><算术表达式>

<关系运算符>→<|>|==|!=|>=|<=

<算数表达式>→<算数表达式>+<项>|<算数表达式>-<项>|<项>

<项>→<项>*<因子>|<项>/<因子>|<因子>

<因子>→<标识符>|<无符号整数>|(<算数表达式>)|true|false

 <字母>→a|b|…|z|A|B|…|Z

 <数字>→0|1|2|3|4|5|6|7|8|9

3.单词分类情况表

4.状态转换图

5.程序设计

 词法分析程序

  1 #include <cstdio>
  2 #include <stdio.h>
  3 #include <cctype>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <map>
  7 using namespace std;
  8 const string keyWord[20]= {"main","const","int","float","double","long","long long","char","while","for","if","else","false","true"};
  9 const string relSign[10]= {">","<",">=","<=","!=","==","="};
 10 
 11 struct signTable//符号表
 12 {
 13     string name;
 14     int value;
 15     int kind;
 16     int address;
 17 }record[520];
 18 map<string,bool>mpk;
 19 map<string,bool>mpr;
 20 int cnt = 0,num = 0;
 21 const char *p;
 22 void init()//建立关键字表
 23 {
 24     for (int i = 0; i < 14; i++)
 25         mpk[keyWord[i]] = true;
 26     for (int i = 0; i < 7; i++)
 27         mpr[relSign[i]] = true;
 28     cnt = 0,num = 0;
 29 }
 30 void alpha()//识别标识符
 31 {
 32     char save[250];
 33     int i = 0;
 34     string s ;
 35     while(isalnum(*p))
 36     {
 37         save[i++]=*p;
 38         p++;
 39     }
 40     save[i] = '';
 41     s = save;
 42     p--;
 43     if(mpk[s])//判断是否存在于关键字表中
 44         cout<<++cnt<<" keyword "<<s<<endl;
 45     else
 46         {
 47             record[num++].name = s;
 48             cout<<++cnt<<" captionsign "<<s<<endl;
 49         }
 50 }
 51 void digit()//识别数字
 52 {
 53     int i = 0;
 54     char save[250];
 55     string s;
 56     while(isdigit(*p))
 57     {
 58         save[i++] = *p;
 59         p++;
 60     }
 61     save[i] = '';
 62     s = save;
 63     p--;
 64     cout<<++cnt<<" digit "<<s<<endl;
 65 }
 66 void isRelSign()//识别关系运算符
 67 {
 68     char save[10];
 69     string s;
 70     int i = 0;
 71     while(i <= 1)
 72     {
 73         save[i++]=*p;
 74         p++;
 75     }
 76     p--;
 77     save[i] = '';
 78     s = save;
 79     if(mpr[s])//判断是否存在于关系运算符表中
 80         cout<<++cnt<<" relationsign "<<s<<endl;
 81     else
 82         {
 83             p--;
 84             if(*p=='!')
 85             cout<<++cnt<<" error "<<*p<<endl;
 86             else
 87             cout<<++cnt<<" relationsign "<<*p<<endl;
 88         }
 89 }
 90 int main()
 91 {
 92     string name,str,s,s1;
 93     char ss[1020],filename[20];
 94     cout<<"please input your program's filename:"<<endl;
 95     init();
 96     cin>>name;
 97     name+=".txt";//添加扩展名
 98     int len = name.size();
 99     name.copy(filename,len,0);
100     filename[len]='';
101     freopen(filename,"r",stdin);//读文件
102     while(gets(ss))
103     {
104         s1 = ss;
105         cout<<s1<<endl;//输出源程序
106         str+=s1;
107     }
108     p = str.data();
109     while(*p!='')
110     {
111         while(*p==' '||*p=='
'||*p=='	') p++;
112         if(isalpha(*p)) alpha();//判断标识符
113         else if(isdigit(*p)) digit();//判断数字
114         else if (*p=='('||*p==')'||*p=='{'||*p=='}'||*p==','||*p==';')//判断界符
115             cout<<++cnt<<" boundarysign "<<*p<<endl;
116         else if (*p=='+'||*p=='-'||*p=='*'||*p=='/')//判断算数运算符
117             cout<<++cnt<<" arithmaticsign "<<*p<<endl;
118         else if(*p=='>'||*p=='<'||*p=='='||*p=='!')//判断关系运算符
119             isRelSign();
120         else
121             cout<<++cnt<<" error "<<p<<endl;//出错处理
122         p++;
123     }
124     fclose(stdin);//关闭文件
125     return 0;
126 }
View Code

 

 (1) 用map容器存储关键字和关系运算符,map容器内部是用红黑树实现的,查找效率为O(ln(N)),查找效率较高。

 (2) 用结构体数组来存储符号表。因为每个符号都有多种属性,用结构体可以将这些属性封装到一起。

6.源程序代码

main()

{
   int i,j,ans;
   i = 5;
   j = 4;
   ans = i+j*5;
}
7.测试结果
8.结果分析
  结果分析:将源程序读入后,经过词法分析程序,可以将源程序分割成一系列单词并将其划分出属性,同时进行词法检查。
原文地址:https://www.cnblogs.com/lahblogs/p/3781075.html