📄 词法分析器.cpp
字号:
#include "iostream.h"
#include "fstream.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#define AND 1
#define ARRAY 2
#define BEGIN 3
#define CASE 4
#define CONST 5
#define DIV 6
#define DO 7
#define DOWNTO 8
#define ELSE 9
#define END 10
#define FILE 11
#define FOR 12
#define FUNCTION 13
#define GOTO 14
#define IF 15
#define IN 16
#define LABEL 17
#define MOD 18
#define NIL 19
#define NOT 20
#define OF 21
#define OR 22
#define PACKED 23
#define PROCEDURE 24
#define PROGRAM 25
#define RECODE 26
#define REPEAT 27
#define SET 28
#define THEN 29
#define TO 30
#define TYPE 31
#define UNTIL 32
#define VAR 33
#define WHILE 34
#define WITH 35 //35个关键字
#define IDENTIFIER 36 //标识符
#define UNSIGNINT 63 //整型
#define UNSIGNREAL 64 //实型
#define CHAR 65 //字符型
#define STRING 66 //字符串型
#define TAB 9
void Analysis(fstream &file)
{
char ch; //搜索字符
char word[121]; //单词数组
int i; //单词下标
int length; //单词长度
int type; //单词类型
bool tag,flag; //单词分析循环控制变量,过程控制变量
char KEYWORD[10],keyword[10]; //准关键字和关键字
int INT; //无符号整型数的值
float REAL,weight; //无符号实型数的值,权
int exp; //指数
fstream finalfile,keyword_file;
finalfile.open("final.txt",ios::out|ios::app);
if(finalfile.fail())
{
cout<<"输出文件打开失败!"<<endl;
exit(0);
}
tag=true; //没有语法错误
length=0; //初始化单词长度
while(!file.eof() && tag)
{
file.get(ch);
if(!file.eof())
{
if((ch>='A' && ch<='Z') ||(ch>='a' && ch<='z') ) //标识符或关键字识别开始
{
i=0;
while( (ch>='A' && ch<='Z') || (ch>='a'&& ch<='z') || (ch>='0' && ch<='9') )
{
if(i<120) //截断
{
word[i]=ch;
file.get(ch);
i++;
}
}
file.seekg(-1L,ios::cur); //文件指针回退一步
word[i]='\0';
length=i;
flag=true; //flag为true表示word是准关键字,false表示word为标识符
for(i=0;i<length;i++) //把标识符转换成大写字符串,以便判断是不是关键字
{
if(word[i]>='a' && word[i]<='z')
KEYWORD[i]=word[i]-32;
else if(word[i]>='A' && word[i]<='Z' )
KEYWORD[i]=word[i];
else
{
flag=false;
type=IDENTIFIER; //word为标识符
break;
}
} //大写转换完毕
if(flag)
{
KEYWORD[i]='\0'; //字符串结束符
keyword_file.open("keyword.txt",ios::in); //打开关键字表
if(keyword_file.fail())
{
cout<<"找不到keyword_file!"<<endl;
exit(0);
}
keyword_file>>keyword;
type=1;
while(!keyword_file.eof()) //匹配关键字表
{
if(strcmp(keyword,KEYWORD)==0)
break;
else
{
keyword_file>>keyword;
type++;
}
}
keyword_file.close();
} //1-35为关键字,36为标识符,所以若关键字表找不到,type为36,刚好是标识符
finalfile<<type<<" "<<word<<endl; //存放到文件finalfile中去
break; //退出词法分析循环
} //标识符或关键字识别完毕
else if(ch>='0' && ch<='9') //无符号数识别开始
{
i=0;
while(ch>='0' && ch<='9')
{
word[i]=ch;
file.get(ch);
i++;
}
if(ch!='.' && ch!='E')
{
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur); //文件指针回退一步
INT=0;
for(i=0;i<length;i++)
INT=INT*10+word[i]-'0';
finalfile<<UNSIGNINT<<" "<<INT<<endl;
break;
} //无符号整型数识别
else //无符号实型数识别开始
{
if(ch=='.') //开始处理小数点
{
word[i]=ch; //保存小数点
file.get(ch); //读取下一个字符
i++; //下标前移
if(ch>='0' && ch<='9') //读取小数点后的数开始
{
while(ch>='0' && ch<='9')
{
word[i]=ch;
i++;
file.get(ch);
} //小数部分读取
if(ch!='E') //无符号实数xxx.xxx转换开始
{
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur);
REAL=0.0;
for(i=0;word[i]!='.';i++) //整数部分
{
REAL=REAL*10+word[i]-'0';
}
weight=10.0;
for(i++;i<length;i++) //小数部分
{
REAL=REAL+(word[i]-'0')/weight;
weight*=10;
}
finalfile<<UNSIGNREAL<<" "<<REAL<<endl;
} //无符号实数xxx.xxx识别
else //继续识别无符号实数XXX.XXXEXXX
{
word[i]=ch; //保存E
i++; //下标前移
file.get(ch); //读取下一个字符
if(ch=='+' || ch=='-') //读进一个正号或负号,如果没有则略过
{
word[i]=ch;
i++;
file.get(ch);
}
if(ch>='0' && ch<='9')
{
while(ch>='0' && ch<='9') //读取阶码
{
word[i]=ch;
i++;
file.get(ch);
}
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur);
REAL=0.0;
for(i=0;word[i]!='.';i++) //整数部分
{
REAL=REAL*10+word[i]-'0';
}
weight=0.1f;
for(i++;word[i]!='E';i++) //小数部分
{
REAL=REAL+(word[i]-'0')*weight;
weight/=10.0;
} //E前的尾数
i++;
weight=10.0; //如果没有正负号,默认阶码为正
if(word[i]=='+') //判断阶码正负号
{
weight=10.0;
i++;
}
else if(word[i]=='-')
{
weight=0.1f;
i++;
}
exp=0; //阶码
for(;i<length;i++)
{
exp=exp*10+word[i]-'0';
}
while(exp>0)
{
REAL=REAL*weight;
exp--;
}
finalfile<<UNSIGNREAL<<" "<<REAL<<endl;
} //无符号实数XXX.XXXEXXX识别
else
{
tag=false;
break;
}
} //无符号实数XXX.XXXEXXX识别
} //读取小数点后的数结束
else
{
tag=false;
break;
}
} //小数点处理结束
else if(ch=='E') //开始处理E
{
word[i]=ch; //读进一个E
i++; //下标前移
file.get(ch); //读取下一个字符
if(ch=='+' || ch=='-') //读进一个正号或负号,如果没有就跳过
{
word[i]=ch;
i++;
file.get(ch);
}
if(ch>='0' && ch<='9')
{
while(ch>='0' && ch<='9') //读取阶码
{
word[i]=ch;
i++;
file.get(ch);
}
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur);
REAL=0.0;
for(i=0;word[i]!='E';i++) //整数部分
{
REAL=REAL*10+word[i]-'0';
} //E前的尾数
i++; //略过E
weight=10.0; //如果没有正负号,默认阶码为正
if(word[i]=='+') //判断阶码正负号
{
weight=10.0;
i++;
}
else if(word[i]=='-')
{
weight=0.1f;
i++;
}
exp=0;
for(;i<length;i++) //阶码
{
exp=exp*10+word[i]-'0';
}
while(exp>0)
{
REAL=REAL*weight;
exp--;
}
finalfile<<UNSIGNREAL<<" "<<REAL<<endl; //保存到文件finalfile
}
else
{
tag=false;
break;
}
} //E处理完毕
} //无符号实型数处理完毕
break; //退出词法分析循环
} //无符号数识别完毕
else if(ch=='\'') //字符或字符串常数识别开始
{
i=0;
file.get(ch);
flag=true; //flag为true表示字符或字符串处理还没结束,为false表示处理结束
while(flag)
{
if(ch=='\'')
{
file.get(ch);
if(ch=='\'') //读到字符串中的“''”,即“'”号
{
word[i]=ch;
i++;
file.get(ch);
}
else //字符或字符串识别完毕
{
file.seekg(-1L,ios::cur);
flag=false;
}
}
else
{
if(i<120) //截断
{
word[i]=ch;
i++;
file.get(ch);
}
}
if(file.eof())
{
tag=false;
break;
}
}
word[i]='\0';
length=i;
if(tag==false)
break;
if(length==0)
tag=false;
else if(length==1)
finalfile<<CHAR<<" "<<word<<endl;
else if(length>1)
finalfile<<STRING<<" "<<word<<endl;
break;
} //字符或字符串常数识别完毕
else if((ch>=40 && ch<=45) || ch=='/' || ch==';' || ch=='=')
{ //ASCII字符从40-47, ‘/’ , ‘;’ , ‘=’ 都是可唯一确定的界符,且编号等于它们的ASCII码
finalfile<<int(ch)<<" "<<ch<<endl;
break;
}
else
{
flag=false; //flag 为true 表示已寻找到界符,为false表示没有寻找到界符
switch(ch)
{
case'[':
finalfile<<54<<" "<<ch<<endl;
flag=true;
break;
case']':
finalfile<<55<<" "<<ch<<endl;
flag=true;
break;
case'^':
finalfile<<53<<" "<<ch<<endl;
flag=true;
break;
case'<':
file.get(ch);
if(ch=='=')
finalfile<<48<<" "<<'<'<<ch<<endl;
else if(ch=='>')
finalfile<<49<<" "<<'<'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int('<')<<" "<<'<'<<endl;
}
flag=true;
break;
case'>':
file.get(ch);
if(ch=='=')
finalfile<<50<<" "<<'>'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int('>')<<" "<<'>'<<endl;
}
flag=true;
break;
case':':
file.get(ch);
if(ch=='=')
finalfile<<51<<" "<<':'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int(':')<<" "<<':'<<endl;
}
flag=true;
break;
case'.':
file.get(ch);
if(ch=='.')
finalfile<<52<<" "<<'.'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int('.')<<" "<<'.'<<endl;
}
flag=true;
break;
case '\n':
case TAB:
case ' ':
while(ch==' '|| ch==TAB || ch=='\n') //略过空格
file.get(ch);
if(file.eof())
{
tag=false;
break;
}
file.seekg(-1L,ios::cur); //文件指针后移一步
break;
case '{': //清除注释
while(ch!='}')
{
file.get(ch);
if(file.eof())
{
tag=false;
break;
}
}
break;
}
if(flag)
break;
}
}
}
finalfile.close();
}
void main()
{
fstream file;
file.open("source.txt",ios::in|ios::nocreate);
if(file.fail())
{
cout<<"文件打开失败,请确认文件时候存在!"<<endl;
exit(0);
}
while(!file.eof())
Analysis(file);
cout<<"结果已保存到了文件final.txt中"<<endl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -