编译原理-词法分析器-用高级语言实现词法分析器功能

时间:2022-03-02 16:46:57

题目要求:

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。 并依次输出各个单词的内部编码及单词符号自身值。遇到错误时可显示“Error”,然后跳过错误部分继续显示

1) 输入范围:

编译原理-词法分析器-用高级语言实现词法分析器功能

2) 输出形式:

例如(1,保留字)、(2,用户自定义变量)、(3,常量)、(4,运算符)、(5,分界符)、(6,ERROR)

/*目前实现的功能有:                                            */
/* 1.识别用户定义的初次定义的变量还是已经定义的变量还是错误字符*/
/* 2.浮点数和常量可以识别读取并输出。 */
/* 3.识别双目运算符和用户连续输入的分界符 */
/* 4.程序存在问题:不能正确区分负号和减号,统一输出为减号 */
/* 5.识别注释 */
/* 6.目前仅支持简单C语言程序,可自行扩充字典内容,以扩大程序功能 */
/* Copyright 张壳(ZKeeer)*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <ctype.h>
#include <assert.h>

using namespace std;
multimap<string, int> MyMap;
multimap<string, int> MyMap_Stor;
vector<string>::iterator itermv;
multimap<string, int>::iterator iter;
multimap<string, int>::iterator iterms;
vector<string> MyVect;
bool zhushi=0;
int Dectionry()
{
try
{
/// C语言1.保留字 2.用户自定义变量和函数名 3.常量 4.运算符 5.分界符
/// 可根据需要自行添加字典条目
MyMap.insert(pair<string, int>("int",1));
MyMap.insert(pair<string, int>("double",1));
MyMap.insert(pair<string, int>("char",1));
MyMap.insert(pair<string, int>("float",1));
MyMap.insert(pair<string, int>("string",1));
MyMap.insert(pair<string, int>("include",1));
MyMap.insert(pair<string, int>("define",1));
MyMap.insert(pair<string, int>("struct",1));
MyMap.insert(pair<string, int>("void",1));
MyMap.insert(pair<string, int>("if",1));
MyMap.insert(pair<string, int>("else",1));
MyMap.insert(pair<string, int>("for",1));
MyMap.insert(pair<string, int>("while",1));
MyMap.insert(pair<string, int>("do",1));
MyMap.insert(pair<string, int>("return",1));
MyMap.insert(pair<string, int>("break",1));
MyMap.insert(pair<string, int>("stdio.h",1));
MyMap.insert(pair<string, int>("continue",1));

MyMap.insert(pair<string, int>("main",2));

MyMap.insert(pair<string, int>("+",4));
MyMap.insert(pair<string, int>("-",4));
MyMap.insert(pair<string, int>("*",4));
MyMap.insert(pair<string, int>("/",4));
MyMap.insert(pair<string, int>("%",4));
MyMap.insert(pair<string, int>("=",4));
MyMap.insert(pair<string, int>("<",4));
MyMap.insert(pair<string, int>(">",4));
MyMap.insert(pair<string, int>("++",4));
MyMap.insert(pair<string, int>("+=",4));
MyMap.insert(pair<string, int>("-=",4));
MyMap.insert(pair<string, int>("*=",4));
MyMap.insert(pair<string, int>("/=",4));
MyMap.insert(pair<string, int>("%=",4));
MyMap.insert(pair<string, int>("<<",4));
MyMap.insert(pair<string, int>(">>",4));

MyMap.insert(pair<string, int>(",",5));
MyMap.insert(pair<string, int>(";",5));
MyMap.insert(pair<string, int>("(",5));
MyMap.insert(pair<string, int>(")",5));
MyMap.insert(pair<string, int>("{",5));
MyMap.insert(pair<string, int>("}",5));
MyMap.insert(pair<string, int>("<",5));
MyMap.insert(pair<string, int>(">",5));
MyMap.insert(pair<string, int>("#",5));
MyMap.insert(pair<string, int>("//",5));

}
catch(exception e)
{
return 0;
}

return 1;
}
void showandstore(string str, int n)
{
cout<<"("<<n<<",\""<<str<<"\")"<<endl;///立即输出
MyMap_Stor.insert(pair<string, int>(str, n));///存储
MyVect.push_back(str);///存储
}

void readSymbol(string str)
{
while(!str.empty()&&ispunct(str[0]))
{
iter = MyMap.find(str);
if(iter != MyMap.end()) ///若字典中存在,则进行匹配
{
if(iter->first=="//") //识别注释
{
str.clear();
zhushi=1;
return;
}

showandstore(iter->first, iter->second);
// cout<<"str test1: "<<str<<endl;
str.clear();
}
else if(iter == MyMap.end()&& !str.empty()) ///若字典中没有 , 则进行判断是不是用户输入() {} ++ -- << >> 等符号
{
string new1;
new1.append(str,0,1);
iter=MyMap.find(new1);
if(iter!=MyMap.end()&&(iter->second==5)) ///用来区分相连的分界符,例如 () {}
{

showandstore(iter->first, iter->second);
new1.clear();
// cout<<"str test2: "<<str<<endl;
str.erase(0,1);
if(ispunct(str[0]))
{
new1.clear();
new1.append(str,0, 1);
iter = MyMap.find(new1);
if(iter != MyMap.end()&&(iter->second==5))
{
showandstore(iter->first, iter->second);
new1.clear();
// cout<<"str test3: "<<str<<endl;
str.erase(0,1);
}
}
}

else if (iter!=MyMap.end()&&(iter->second==4)) ///用来区分 ++ -- +=等双目运算符符号
{
if(ispunct(str[1]))
{
// cout<<"tset!!!"<<endl;
new1.clear();
new1.append(str,0,2);
iter = MyMap.find(new1);
if(iter != MyMap.end()&&iter->second==4)
{

if(iter->first=="//") //识别注释
{
str.clear();
zhushi=1;
return;
}

showandstore(iter->first, iter->second);
// cout<<"str test4: "<<str<<endl;
str.erase(0,2);
}
}
}
}
}
}
void readString(string WordKey)
{
///程序处理内容
iter = MyMap.find(WordKey);
if(iter != MyMap.end()) ///查找成功,进入字典匹配
{
showandstore(iter->first, iter->second);
WordKey.clear();///清空
}
else ///已区分自定义变量和不可识别字符///未查找到,则进行判断是否为用户自定义变量或是不可识别的错误字符
{
for(vector<int>::size_type i = MyVect.size()-1; i>0&&MyVect[i]!=";"&&MyVect[i]!="}"&&MyVect[i]!=">"; i--) ///判断该变量是否为用户初次定义的变量
{
if((MyVect[i]=="int"||MyVect[i]=="char"||MyVect[i]=="double"||MyVect[i]=="struct")&&WordKey.empty()==0) /// 判断情况 例如int asdfgdajfla;
{
showandstore(WordKey, 2);
WordKey.clear();
break;
}
}

if(!WordKey.empty()) ///若已排除不是用户初次定义的变量,则判断是不是用户之前定义过的变量
{
iter = MyMap_Stor.find(WordKey);
if((iter!=MyMap_Stor.end()&&!WordKey.empty()))
{
showandstore(WordKey, 2);
WordKey.clear();
// break;
}
else ///不可识别字符 输出error
{
cout<<"(6,\"Error\")"<<endl;
}
}
// StringFlag=0;
WordKey.clear();
}
}
int main()
{


int i=0;
int WordValue;
double ChangLiang=0;
string Symbol;
string WordKey;
char* FileName;
int StringFlag=0, CharFlag=0, NumFlag=0, DoubleFlag=0;

if(0==Dectionry())
{
cout<<"程序出错,请重新开始!"<<endl;
return 0;
}

// FileName = new char[512];
// cout<<"请输入文件完整路径和文件名:"<<endl;
// cin>>FileName;
// ifstream ifs(FileName);

/// 以下语句为测试用例,可忽略
// ifstream ifs("123.cpp");
ifstream ifs("test.c");
// ifstream ifs("example.txt");

streambuf* old_buffer = cin.rdbuf(ifs.rdbuf());

string read;

while (cin >> read) /// 逐词读取方法,遇到空格 回车 换行 制表符...结束
{
while ( true )
{
for(; isalpha(read[i])&&(i<read.length()); i++) /// 读取字符串
{
StringFlag=1;
WordKey.append(read, i, 1);

if(read[i+1]=='.') ///处理头文件 类似stdio.h
{
i+=1;
WordKey.append(read, i, 1);
}
}///end for
if(StringFlag) /// 处理字符串,字符串读取完,与字典内匹配
{
readString(WordKey);
StringFlag=0;
WordKey.clear();
}///end if(StringFlag)

for(; isdigit(read[i])&&(i<read.length()); i++) /// 读取常量
{
NumFlag=1;
if(DoubleFlag)
ChangLiang=ChangLiang+((int)read[i]-48)*0.1;
else
ChangLiang=ChangLiang*10+((int)read[i]-48);

if(read[i+1]=='.') ///判断是有小数点,若是则为浮点数
{
DoubleFlag=1;
i+=1;
}

}///end for
if(NumFlag) ///处理常量
{
cout<<"(3"<<",\""<<ChangLiang<<"\")"<<endl;///立即输出
NumFlag=0;
DoubleFlag=0;
ChangLiang=0;
}///end if(NumFlag)

/// ////////////////////////////单个以及双目字符
for(; ispunct(read[i])&&(i<read.length()); i++)
{
CharFlag=1;
Symbol.append(read, i, 1);
}
if(CharFlag)
{
readSymbol(Symbol);
Symbol.clear();
CharFlag=0;
}

if(i==read.length()||zhushi) ///read内容全部处理完,各个变量进行初始化,并推出while(true)
{
i=0;
ChangLiang=0;
zhushi=0;
WordKey.clear();
read.clear();
Symbol.clear();
break;
}///end if(i==read.length())
}///end while(true)
}///end while(cin>>read)

cin.rdbuf(old_buffer);
MyMap_Stor.clear();
MyVect.clear();
delete []FileName;
return 0;
}