编译原理 词法分析 源代码

 

#include<iostream>
#include<string>
#include<fstream>

#include<vector>

// C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的.

using namespace std;


vector <string> Char;//存放char型标识符的容器
vector <string> Double;//存放double型标识符的容器
vector <string> Float;//存放float型标识符的容器
vector <string> Int;//存放int型标识符的容器
vector <string> String;//存放string型标识符的容器




bool pChar = 0;//判断一个字符串是否为char型标识符
bool pDouble = 0;//判断一个字符串是否为double型标识符
bool pFloat = 0;//判断一个字符串是否为float型标识符
bool pInt = 0;//判断一个字符串是否为int型标识符
bool pString = 0;//判断一个字符串是否为string型标识符


void fhb()//符号表的显示
{
string filename2;
int i;
int add = 0;//地址
/*cout << "请输入符号表的名称:";
cin >> filename2;*/
filename2 = "fb.txt";
ofstream f2(filename2, ios::out);
f2 << "类型" << '\t' << "变量" << '\t' << "地址" << endl;


cout << endl;
cout << "类型" << '\t' << "变量" << '\t' << "地址" << endl;
for (i = 0; i<Char.size(); i++)
{
cout << "char" << '\t' << Char[i] << '\t' << add << endl;
f2 << "char" << '\t' << Char[i] << '\t' << add << endl;
add++;
}
for (i = 0; i<Double.size(); i++)
{
cout << "double" << '\t' << Double[i] << '\t' << add << endl;
f2 << "double" << '\t' << Double[i] << '\t' << add << endl;
add++;
}
for (i = 0; i<Float.size(); i++)
{
cout << "float" << '\t' << Float[i] << '\t' << add << endl;
f2 << "float" << '\t' << Float[i] << '\t' << add << endl;
add++;
}
for (i = 0; i<Int.size(); i++)
{
cout << "int" << '\t' << Int[i] << '\t' << add << endl;
f2 << "int" << '\t' << Int[i] << '\t' << add << endl;
add++;
}
for (i = 0; i<String.size(); i++)
{
cout << "string" << '\t' << String[i] << '\t' << add << endl;
f2 << "string" << '\t' << String[i] << '\t' << add << endl;
add++;
}
f2.close();
}
void Show(char buff[])
{//字符串显示函数
int i = 0;
while (buff[i])
{
cout << buff[i];
i++;
}
}


void File(char ch[])
{//对要打开的文件的操作
char c;
char filename[20];//要打开的文件名
int j = 0;
cout << "请输入文法所在的文件的名称:";
cin >> filename;
FILE *cfPtr;
if ((cfPtr = fopen(filename, "r")) == NULL)
cout << "文件未找到!";
else
{
while (!feof(cfPtr))//feof是C语言标准库函数,其原型在stdio.h中,其功能是检测流上的文件结束符,如果文件结束,则返回非0值,否则返回0
{
c = fgetc(cfPtr);
ch[j] = c;//从文件中一一提取字符
j++;
}
}
cout << endl;
cout << "词法分析结果如下:\n" << endl;
}


bool isLetter(char c)
{//判断读入的字符是否为字母
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
return true;
}
else
return false;
}


bool isDigit(char c)
{//判断是否为数字
if (c >= '0'&&c <= '9')
{
return true;
}
else
return false;
}


bool isKey(char *string)
{//判断是否为保留字
if (!strcmp(string, "void") || !strcmp(string, "if") || !strcmp(string, "for") || !strcmp(string, "while") || !strcmp(string, "do")
|| !strcmp(string, "return") || !strcmp(string, "break") || !strcmp(string, "main") || !strcmp(string, "int")
|| !strcmp(string, "float") || !strcmp(string, "char") || !strcmp(string, "double") || !strcmp(string, "String"))
{
return true;
}
else
return false;
}


bool isTODKey(char *string)
{//判读是否为数据类型保留字
if (!strcmp(string, "int") || !strcmp(string, "float") || !strcmp(string, "char") || !strcmp(string, "double") || !strcmp(string, "String"))
{
return true;
}
else return false;
}


int judgTODKey(char *string)
{//判断保留字类型
if (!strcmp(string, "char")) return 1;
if (!strcmp(string, "double")) return 2;
if (!strcmp(string, "float")) return 3;
if (!strcmp(string, "int")) return 4;
if (!strcmp(string, "String")) return 5;
}


bool isOperator(char ch)
{//判断是否为运算符
if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=')
{
return true;
}
else
return false;
}


bool isSeparator(char ch)
{//判断是否为分隔符
if (ch == ';' || ch == '{' || ch == '}' || ch == '(' || ch == ')' || ch == ',' || ch == '"')
{
return true;
}
else
return false;
}


//读取文件中的字符串
void outFile(char buff[], string filename1)
{
int i = 0;
ofstream f1(filename1, ios::app);
while (buff[i])
{
f1 << buff[i];
i++;
}
}


//首字符为字母的分析
void Aletter(char buff[], string filename1)
{
ofstream f1(filename1, ios::app);


if (isKey(buff))
{
cout << "(  1 ,";
Show(buff);
cout << "  )";
cout << "  保留字  " << endl;
outFile(buff, filename1);
f1 << '\t';
f1 << "  1  ";
f1 << '\t';
f1 << "  保留字  " << endl;
if (isTODKey(buff))
{//判断是否为数据类型的保留字
if (judgTODKey(buff) == 1) pChar = 1;//检测到相应保留字后,打开开关
if (judgTODKey(buff) == 2) pDouble = 1;
if (judgTODKey(buff) == 3) pFloat = 1;
if (judgTODKey(buff) == 4) pInt = 1;
if (judgTODKey(buff) == 5) pString = 1;
}
}
else
{
cout << "(  2 ,";
Show(buff);
cout << "  )";
cout << "  标识符  " << endl;
outFile(buff, filename1);
f1 << '\t';
f1 << "  2  ";
f1 << '\t';
f1 << "  标识符  " << endl;
if (pChar)
{//pChar打开时,就将这个字符串放入pChar中
Char.push_back(buff);
}
if (pDouble)
{//pDouble打开时,就将这个字符串放入pDouble中
Double.push_back(buff);//字符串之后插入一个字符
}
if (pFloat)
{//pFloat打开时,就将这个字符串放入pFloat中
Float.push_back(buff);//字符串之后插入一个字符
}
if (pInt)
{//pInt打开时,就将这个字符串放入pInt中
Int.push_back(buff);//字符串之后插入一个字符
}
if (pString)
{//pString打开时,就将这个字符串放入pString中
String.push_back(buff);//字符串之后插入一个字符
}
}
f1.close();
}


//首字符为数字的分析
void Adigit(char buff[], string filename1)
{
ofstream f1(filename1, ios::app);


bool b = 1;
int i = 0;
while (buff[i])
{
if (isLetter(buff[i]))
{
Show(buff);
cout << "为语法错误!" << endl;
b = 0;
break;
}
i++;
}
if (b)
{
cout << "(  3 ,";
Show(buff);
cout << "  )";
cout << "  常数  " << endl;
outFile(buff, filename1);
f1 << '\t';
f1 << "  3  ";
f1 << '\t';
f1 << "  常数  " << endl;
}
f1.close();
}


void main()
{
char ch[500] = "";//存取文件中读出的字符串
File(ch);
char buff[40] = "";//存放需要比对的字符串
int j = 0;


string filename1;//进行保存内容的文件名
/*cout << "请输入要进行保存内容的文件名:";
cin >> filename1;*/
filename1 = "RESULT.txt";


ofstream f1(filename1, ios::app);
f1 << "字符串" << '\t' << "符号" << '\t' << "类型" << endl;
while (ch[j] >= 0)
{//对整个字符串进行分析直到0
memset(buff, 0, sizeof(buff));//清空buff
int i = 0;
while (!isspace(ch[j]) && !isOperator(ch[j]) && !isSeparator(ch[j]))
{
buff[i] = ch[j];
j++;
i++;
}
//分析buff[]数组
if (isLetter(buff[0]))
{
Aletter(buff, filename1);
}
if (isDigit(buff[0]))
{
Adigit(buff, filename1);
}
if (isOperator(ch[j]))
{
cout << "(  4 ," << ch[j] << "  )" << "  运算符  " << endl;
ofstream f1(filename1, ios::app);
f1 << ch[j] << '\t' << "  4  " << '\t' << "  运算符  " << endl;
f1.close();
}
if (isSeparator(ch[j]))
{
if (ch[j] == ';'&&pChar == 1)
pChar = 0;//遇到分号时,就关闭开关,结束标识符的接收
if (ch[j] == ';'&&pDouble == 1)
pDouble = 0;//遇到分号时,就关闭开关,结束标识符的 接收
if (ch[j] == ';'&&pFloat == 1)
pFloat = 0;//遇到分号时,就关闭开关,结束标识符的接收
if (ch[j] == ';'&&pInt == 1)
pInt = 0;//遇到分号时,就关闭开关,结束标识符的接收
if (ch[j] == ';'&&pString == 1)
pString = 0;//遇到分号时,就关闭开关,结束标识符的接收
cout << "(  5 ," << ch[j] << "  )" << "  分隔符  " << endl;
ofstream f1(filename1, ios::app);
f1 << ch[j] << '\t' << "  5  " << '\t' << "  分隔符  " << endl;
f1.close(); 
}
j++;
}
fhb();
}
实验一:词法分析程序 一、实验目的     通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的类型码及单词符号的自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示) 二、实验要求 用C或C++写一个简单的词法分析程序,程序可以满足下列要求: 1、能分析如下几种简单的语言词法 (1) 标识符: ID=letter(letter|digit)* (2) 关键字(全部小写) main int float double char if then else switch case break continue while do for (3)整型常量:NUM=digit digit* (4)运算符 = + - * / < <= == != > >= ; ( )? : (5)空格由空白、制表符和换行符组成,用以分隔ID、NUM、运算符等,字符分析时被忽略。 2、单词符号和相应的类别码 假定单词符号和相应的类别码如下: 单词符号 种别码 int 1 = 17 float 2 < 20 if 3 <= 21 switch 4 == 22 while 5 != 23 Do 6 > 24 标识符 10 >= 25 整型常量 11 ; 26 + 13 ( 27 - 14 ) 28 * 15 ? 29 / 16 : 30 3、词法分析程序实现的功能 输入:单词序列(以文件形式提供),输出识别的单词的二元组序列到文件和屏幕 输出:二元组构成: (syn,token或sum) 其中: syn 为单词的种别码 token 为存放的单词自身符号串 sum 为整型常数 例: 源程序: int ab; float ef=20; ab=10+ef; 输出: (保留字--1,int) (标识符--10,ab) (分号--26,;) (保留字--2,float) (标识符--10,ef) (等号--17,=) (整数--11,20) (分号--26,;) (标识符--10,ab) (等号--17,=) (整数--11,10) (加号--13,+) (标识符--10,ef) (分号--26,;) 4、自己准备测试数据存放于TestData.txt文件中,测试数据中应覆盖有以上5种数据,测试结果要求以原数据与结果对照的形式输出并保存在Result.txt中,同时要把结果输出到屏幕。 5、提前准备 ① 实验前,先编制好程序,上机时输入并调试程序。 准备好多组测试数据(存放于文件TestData.txt中)。 6、写出实验报告 报告格式:要求有实验名称、实验目的、实验要求、实验内容、实验小结。 其中实验内容包括算法分析、程序流程图及程序代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值