📄 cpp3.cpp
字号:
#include <iostream>
#include <fstream>//文件流头文件无.h,以下有说明
#include <string>
#include <string.h>//字符串头文件
#include<stdio.h>//标准输入输出
#include <ctype.h>//包含了isalpha等,是字符分类宏
using namespace std;//在目前的版本中可以支持这样的,不用.h为后缀了
char* ReserveWords[32] = {// 保留字数组定义
"auto","double","int","struct","break",
"else","long","switch","case","enum","register","typedef",
"char","extern","return","union","const","float","short",
"unsigned","continue","for","signed","void","default","goto",
"sizeof","volatile","do","if","while","static"};//,"main"加上后则识别main为保留字
char arrow[] = " ";
/*char arrow[] = " -----> ";
宏定义便于以后的修改
可以定义此项作为结果输出的分界..如( -----> 5
格式如:dst << strToken << arrow << "1" << enter;
*/
char enter[] = "\r\n";
// 读入字符ch
char GetChar(ifstream& src)
{
char cRet;
src.get(cRet);//读入一个字符.get是ifstream中的一个函数
return cRet;
}
// 读入空格
char GetBC(ifstream& src)//字符型函数
{
char cRet;
src.get(cRet);//同上
while (cRet == ' ')//空格
src.get(cRet);//继续读入
return cRet;//返回字符型值
}
// 连接单词符号
void Concat(char *str, char c)
{
size_t n = strlen(str);//得到目前串长度
str[n++] = c;//作为连接的组合空间
str[n] = '\0';//结束标志
}
// 判断是否为保留字
bool Reserve(const char* str)
{
bool bRet = false;
for (int i = 0; i < 32; i++)
{
if (strcmp(ReserveWords[i], str) == 0)//是关键字的话
{
bRet = true;//true确认
break;
}
}
return bRet;
}
// 回调字符
char Retract(ifstream& src)
{
src.seekg(-1, ios::cur);/*文件流中的一个函数,两种类型,两种参数!
seekg(pos_type _Pos);
seekg(off_type _Off,ios_base::seekdir _Way);
_Off
An offset to move the read pointer relative to way.
_Pos
The absolute position in which to move the read pointer.
_Way
One of the ios_base::seekdir enumerations.
Return Value
The stream (*this).
//用于在文件流移动读指针
*/
return '\0';
}
// 分析函数
void Analyzer(ifstream& src, ofstream& dst)
{
char ch;
char strToken[1024] = "";//初始置空
ch = GetBC(src);//定义ch字符初始空格
// 判断标识符的情况
if (isalpha(ch))
{
while (isalpha(ch) || isdigit(ch) || ch == '_')
{
Concat(strToken, ch);//判断是否为单个字符,进行连接
ch = GetChar(src);
}
ch = Retract(src);//字符回调后重新对字符或字符串进行判断
if (Reserve(strToken))
dst << strToken << arrow << "1" << enter;//输出流的一种格式
else
dst << strToken << arrow << "2" << enter;//不为保留字,则为数字,有上面的条件判定
}
// 判断数字的情况
else if (isdigit(ch))
{
while (isdigit(ch))//下个字符不是数字,退出运行过程
{
Concat(strToken, ch);//进行连接,多位数...
ch = GetChar(src);//从标准输入设备读取一个字符,若文件结束或出错,则返回-1
//而getc是从文件中读入一个字符,若文件结束或出错,返回EOF
}
Retract(src);//回调字符
dst << strToken << arrow << "3" << enter;//类型3
} // 判断转义字符与串的情况
else if (ch == '\'')//是\'转义字符
{
Concat(strToken, ch);//将其连接
ch = GetChar(src);
while (ch != '\'')//不是\'字符,继续连接
{
Concat(strToken, ch);
ch = GetChar(src);
}
if (ch != '\'')//界定长度
cerr << "String is too long - more than 1024 bytes!" << endl;
else
{
Concat(strToken, ch);
dst << strToken << arrow << "String" << enter;//串
}
}
// 判断所有没有歧义的单目运算符
else if (ch == '+')
dst << ch << arrow << "4" << enter;////类型4,以下输出,意义相同
else if (ch == '-')
dst << ch << arrow << "4" << enter;
else if (ch == '*')
dst << ch << arrow << "4" << enter;
else if (ch == '/')
dst << ch << arrow << "4" << enter;
else if (ch == '=')
dst << ch << arrow << "4" << enter;
else if (ch == '[')
dst << ch << arrow << "5" << enter;
else if (ch == ']')
dst << ch << arrow << "5" << enter;
else if (ch == ',')
dst << ch << arrow << "5" << enter;
else if (ch == '^')
dst << ch << arrow << "4" << enter;
else if (ch == ';')
dst << ch << arrow << "5" << enter;
else if (ch == '(')
dst << ch << arrow << "5" << enter;
else if (ch == ')')
dst << ch << arrow << "5" << enter;
else if (ch == '{')
dst << ch << arrow << "5" << enter;
else if (ch == '}')
dst << ch << arrow << "5" << enter;
// 判断<、<>和<=
else if (ch == '<')
{
ch = GetChar(src);
if (ch == '>')
dst << "<>" << arrow << "4" << enter;
else if (ch == '=')
dst << "<=" << arrow << "4" << enter;
else
{
dst << '<' << arrow << "4" << enter;
Retract(src);//<=,<>也即!=
}
}
// 判断>和>=
else if (ch == '>')
{
ch = GetChar(src);
if (ch == '=')
dst << ">=" << arrow << "4" << enter;//类型4
else
{
dst << '>' << arrow << "4" << enter;//类型4
Retract(src);//>=
}
}
// 判断.和..
else if (ch == '.')
{
ch = GetChar(src);
if (ch == '.')
dst << ".." << arrow << "2" << enter;//类型2
else
{
dst << '.' << arrow << "2" << enter;//类型2
Retract(src);//.和..
}
}
// 判断:和:=
else if (ch == ':')
{
ch = GetChar(src);
if (ch == '=')
dst << ":=" << arrow << "4" << enter;//类型4
else
{
dst << ':' << arrow << "2" << enter;//类型2
Retract(src);//:= 逐级判断,分析为各个独立个体,所以需要回调分析,保持字符或字符串完整性
}
}
}
int main(int argc, char* argv[])
{
string strSrc;
if (argc == 1) // 命令行的支持
{
cout << "Please input source file\nlike in.txt... \n\n";
getline(cin, strSrc);
/*
if(cin=="in.txt"){
cout << "the source program below:\n";
while(ch=fopen("in.txt","r")!=NULL)
{
printf("%c",ch);
}
cout<<"\n\n"<<"The result has created to out.txt\n";
}
*/
system("pause");//系统暂停,让用户确定
}
else
strSrc = argv[1];
ifstream src(strSrc.c_str()); // 打开文件
if (src.fail())
{
cerr << "\aFailed to open \"" << strSrc << "\"!" << endl;//cerr输出错误机制,有声音提示
return 1;
}
ofstream dst("out.txt");
// 开始解析,整个文件,知道文件尾
while (!src.eof())//
Analyzer(src, dst);
// 收尾工作
src.close();//关闭输入文件流
dst.close();//关闭输出文件流
cout << "The result of Analyzing is written into out.txt." << endl;
return 0;//整形返回
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -