一、实验目的:
设计、编制并调试一个简单的c语言词法分析程序,加深对词法分析原理的理解
二、实验要求:
- 对单词的构词规则有明确的定义;
- 编写的分析程序能够正确识别源程序中的单词符号;
- 识别出的单词以(单词符号,种别码)的形式保存在符号表中。
三、实验内容:
词法分析中的输入为一个C语言程序文件,该文件由如下关键字、运算符、界限符、常量、标识符中的符号构成,将该程序经词法分析后,形成的单词序列,并保存在一个文本文件(.txt)中。
-
单词的种类及组成
(1)关键字
if else while do for main return int float double char
所有的关键字都是小写。
(2)运算符
= + - * / % < <= > >= != = =
(3)界限符
; ( ) { }
(4)常量
无符号整形常量,通过以下正规式定义:
dight dight*
(5)标识符(ID),通过以下正规式定义:
letter (letter | digit)*
(6)空格有空白、制表符和换行符组成。空格一般用来分隔标识符、整数、运算符、界符和关键字,词法分析阶段被忽略。 -
各种单词符号对应的类别码
四、数据结构设计
主要是定义字符串和数组来保存关键字,种类码和运算符、界限符等信息。
函数设置:
1.分析器
2.
3.数字
4.单词识别
5.判断字符是什么类型
五、算法流程
六、算法结果
输入包含c语言程序的路径,结果保存至output.txt文件当中。
1.输入文件11.txt
2.output.txt保存分析结果
七、实验总结
通过这次实验我学习了简单词法分析器的基本原理,知道如何去设计一个简单的词法分析器。实验总体来说难度不大,代码量也是适中的,但是难点可能在于数据结构的设置以及编码的思路。关于数据结构我也只是使用了最简单的数组来保存需要用到的参数信息,事实上真正的词法分析器,计算机词法分析的源代码要远远复杂的多,同时其数据结构的定义也十分的考究,所以一个好的数据结构的定义对一个复杂、庞大的代码来说是十分重要的。
在实验中我也遇到一些问题,比如说用c语言对文件的处理不是特别熟悉,但是这也是十分简单的,找找资料也很容易实现。
同时也十分感谢老师的讲解,在老师的讲解之下我才能了解词法分析,掌握其基本原理,从而顺利的完成实验任务。
八、实验代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <iostream>
using namespace std;
//关键字
string key[11]={"int","float","double","char","main","if","else","while","do","for","return"};
//种别码
int keyNum[11]={27,28,29,30,1,2,3,4,5,6,7};
//运算符和界符
string symbol[17]={"+","-","*","/","%",">",">=","<","<=","==","!=","=",";","(",")","{","}"};
//运算符和界符种别码
int symbolNum[17]={10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};
//从文件取出的字符
string letter[1000];
//将字符转换为单词
string words[1000];
int length; //保存程序中字符的长度
int num;
//判断是否为关键字,是返回种别码
int isKeyWord(string s){
int i;
for(i=0;i<11;i++){
if(s==key[i])
return keyNum[i];
}
return 0;
}
int isSymbol(string s){ //判断运算符和界符
int i;
for(i=0;i<17;i++){
if(s==symbol[i])
return symbolNum[i];
}
return 0;
}
//判断是否为数字
bool isNumber(string s){
if(s>="0" && s<="9")
return true;
return false;
}
//判断是否为字母
bool isLetter(string s)
{
if(s>="a" && s<="z")
return true;
return false;
}
//返回单个字符的类型
int typeword(string str){
if(str>="a" && str<="z") // 字母
return 1;
if(str>="0" && str<="9") //数字
return 2;
if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"
||str=="+"||str=="-"||str=="*"||str=="/") //判断运算符和界符
return 3;
}
string identifier(string s,int n){
int j=n+1;
int flag=1;
while(flag){
if(isNumber(letter[j]) || isLetter(letter[j])){
s=(s+letter[j]).c_str();
if(isKeyWord(s)){
j++;
num=j;
return s;
}
j++;
}
else{
flag=0;
}
}
num=j;
return s;
}
string symbolStr(string s,int n){
int j=n+1;
string str=letter[j];
if(str==">"||str=="="||str=="<"||str=="!") {
s=(s+letter[j]).c_str();
j++;
}
num=j;
return s;
}
string Number(string s,int n){
int j=n+1;
int flag=1;
while(flag){
if(isNumber(letter[j])){
s=(s+letter[j]).c_str();
j++;
}
else{
flag=0;
}
}
num=j;
return s;
}
void print(string s,int n){
cout<<"<"<<s<<","<<n<<">"<<endl;
}
void recognizeWord(){ //识别单词
int k;
for(num=0;num<length;){
string str,ss;
str=letter[num];
k=typeword(str);
switch(k){
case 1:
{
ss=identifier(str,num);
if(isKeyWord(ss))
print(ss,isKeyWord(ss));
else
print(ss,8);
break;
}
case 2:
{
ss=Number(str,num);
print(ss,9);
break;
}
case 3:
{
ss=symbolStr(str,num);
print(ss,isSymbol(ss));
break;
}
}
}
}
int main(){
char w;
freopen("e:\\11.txt","r",stdin); //控制台输入
freopen("e:\\result.txt","w",stdout); //控制台输出
length=0;
while(cin>>w){
if(w!=' '){
letter[length]=w;
length++;
} //去掉程序中的空格
}
recognizeWord();
fclose(stdin);//关闭文件
fclose(stdout);//关闭文件
return 0;
}