实验一. 词法分析
1. 实验目的
(1) 根据 PL/0 语言的文法规范,编写 PL/0 语言的词法分析程序;或者调研词法分析程序的自动生成工具 LEX 或 FLEX,设计并实现一个能够输出单词序列的词法分析器。
(2) 通过设计调试词法分析程序,实现从源程序中分出各种单词的方法; 加深对课堂教学的理解;提高词法分析方法的实践能力。
(3) 掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示 文件的法。
(4) 掌握词法分析的实现方法。
(5)上机调试编出的词法分析程序。
2. 实验准备
微机安装好 C 语言,或 C++,或 Visual C++,或自己需要用的语言.
3. 实验内容
已给 PL/0 语言文法,输出单词符号(关键字、专用符号以及其它标记)。
4. 实验要求
(1)把词法分析器设计成一个独立一遍的过程。
(2) 词法分析器的输出形式采用二元式序列,即:
(单词种类, 单词的值)
5. 设计思想
(1)正则式
标识符:(a|…|z|A|…|Z)( a|…|z|A|…|Z|0|…|9)*
常数:(1|…|9)(0|…|9)*
基本字:begin、call、const、do、end、if、odd、procedure、read、then、var、while、write
运算符:+、-、*、/、=、<>、<、<=、>、>=、:=
界符:(、)、,、;、.
(2)NFA
(3)DFA
(4)最小化DFA
(5)流程图
(6)输入输出源程序
#include
#include
#include
#include
#include
#include
#include
using namespace std;
map<string,string> Word;//使用map数据结构实现key-value对应
std::map<string,string>::iterator it;//用来遍历key-value对应关系的迭代器
void map_init(){//key-value(单词-编码)对应关系进行初始化
Word["begin"]="beginsym";
Word["call"]="callsym";
Word["const"]="constsym";
Word["do"]="dosym";
Word["end"]="endsym";
Word["if"]="ifsym";
Word["odd"]="oddsym";
Word["procedure"]="proceduresym";
Word["read"]="readsym";
Word["then"]="thensym";
Word["var"]="varsym";
Word["while"]="whilesym";
Word["write"]="writesym";
Word["+"]="plus";
Word["-"]="minus";
Word["*"]="times";
Word["/"]="slash";
Word["="]="eql";
Word["<>"]="neq";
Word["<"]="lss";
Word["<="]="leq";
Word[">"]="gtr";
Word[">="]="geq";
Word[":="]="becomes";
Word["("]="lparen";
Word[")"]="rparen";
Word[","]="comma";
Word[";"]="semicolon";
Word["."]="period";
}
int main(){
map_init();//key-value(单词-编码)对应关系进行初始化
string word;//识别单词
string str;//识别字符
do{
cin>>str;//输入字符串
for(std::size_t i=0;i<str.size();i++){//对整个字符串进行遍历
while(str[i]==' '||str[i]=='\n') i++;//若最开始为空格或换行符,则将指针的位置往后移
if(isalpha(str[i])){//对标识符和基本字进行识别,调用库函数isalpha()
word=str[i++];
while(isalpha(str[i])||isdigit(str[i])){
word+=str[i++];
}
it=Word.find(word);//返回word在Word中的迭代器
if(it!=Word.end()){//判断是不是基本字,若为基本字则进行输出
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}
else{//否则为标识符直接输出
cout<<"(ident"<<","<<word<<")"<<endl;
}
i--;
}
else if(isdigit(str[i])){//判断是不是常数,调用库函数isdigit()
word=str[i++];
while(isdigit(str[i])){
word+=str[i++];
}
if(isalpha(str[i])){
cout<<"error!"<<endl;
break;
}
else{
cout<<"(number"<<","<<word<<")"<<endl;
}
i--;
}else if(str[i]=='<'){//对<,<=,<>分别进行判断
word=str[i++];
if(str[i]=='>'){
word+=str[i];
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}else if(str[i]=='='){
word+=str[i];
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}else if(str[i]!=' '||!isdigit(str[i])||!isalpha(str[i])){
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}else{
cout<<"error!"<<endl;
break;
}
i--;
}else if(str[i]=='>'){//对>,>=分别进行判断
word=str[i++];
if(str[i]=='='){
word+=str[i];
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}else if(str[i]!=' '||!isdigit(str[i])||!isalpha(str[i])){
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}else{
cout<<"error!"<<endl;
break;
}
i--;
}else if(str[i]==':'){//对:=进行判断
word=str[i++];
if(str[i]=='='){
word+=str[i];
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}else{
cout<<"error!"<<endl;
break;
}
}else{//对其他的基本字依次进行判断
word=str[i];
it=Word.find(word);
if(it!=Word.end()){
cout<<"("<<Word[word]<<","<<word<<")"<<endl;
}else{
break;
}
}
}}while(str!="end.");//判断输出条件当程序输出为"end."时结束
return 0;
}