编译原理 词法分析 源代码

 
 
#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();
}
发布了36 篇原创文章 · 获赞 19 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/GJ_007/article/details/79587657