1、实验目的
词法分析是编译过程的第一个阶段,是编译的基础,这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。通过该实验,加深对词法分析的理解,掌握构词规则的描述方法,掌握词法分析的任务以及词法分析器的实现。
2、实验内容
构造词法分析器,对输入的源程序分析出单词串。
3、实验准备
理解词法分析的任务,构词规则描述方法,词法分析器的设计方法。
C++语言子集的单词符号表示:
单词符号 |
助记符 |
内码值 |
while |
while |
- |
if |
if |
- |
else |
else |
- |
swich |
swich |
- |
case |
case |
- |
标识符 |
id |
该标识符 |
常数 |
num |
该数 |
+ |
operator |
+ |
- |
operator |
- |
* |
operator |
* |
/ |
operator |
/ |
> |
operator |
> |
< |
operator |
< |
= |
operator |
= |
! |
operator |
! |
: |
separater |
: |
{ |
separater |
{ |
} |
separater |
} |
( |
separater |
( |
} |
separater |
} |
根据正规式构造NFA
下面我们根据上述的正规式来构造该文法的NFA,如下图所示,其中状态0为初态,凡带双圈的状态均为终态,状态24是识别不出单词符号的出错情形,其他状态的识别情况如下图中右边的注释所示。
源程序
#include<iostream>
#include<string>
using namespace std;
string KEYWORD[5]={"while","if","else","switch","case"};//关键字
char SEPARATER[5]={';','{','}','(',')'}; //分隔符
char OPERATOR[8]={'+','-','*','/','>','<','=','!'}; //运算符
char FILTER[4]={' ','\t','\r','\n'}; //过滤符
/**判断是否为关键字**/
bool IsKeyword(string word){
for(int i=0;i<5;i++){
if(KEYWORD[i]==word){
return true;
}
}
return false;
}
/**判断是否为分隔符**/
bool IsSeparater(char ch){
for(int i=0;i<5;i++){
if(SEPARATER[i]==ch){
return true;
}
}
return false;
}
/**判断是否为运算符**/
bool IsOperator(char ch){
for(int i=0;i<8;i++){
if(OPERATOR[i]==ch){
return true;
}
}
return false;
}
/**判断是否为过滤符**/
bool IsFilter(char ch){
for(int i=0;i<4;i++){
if(FILTER[i]==ch){
return true;
}
}
return false;
}
/**判断是否为字母**/
bool IsLetter(char ch){
if((ch>='A' && ch<='Z')||(ch>='a' && ch<='z')) return true;
return false;
}
/**判断是否为数字**/
bool IsDigit(char ch){
if(ch>='0' && ch<='9') return true;
return false;
}
int main()
{
char ch;
string s,strToken;
freopen("ifile.txt","r",stdin);
while(ch||cin>>ch){
strToken="";
if(IsFilter(ch)){}//判断是否为过滤符
else if(IsLetter(ch)){//判断是否为关键字
while(IsLetter(ch)){
strToken+=ch;
cin>>ch;//注意,退出循环前已经读取了下一字符存入ch
}
if(IsKeyword(strToken))cout<<"("<<strToken<<",_"<<")"<<endl; //判断是否为关键字
else cout<<"("<<"id,"<<strToken<<")"<<endl; //判断是否为标识符
}
else if(IsDigit(ch)){//判断是否为数字
while(IsDigit(ch)){
strToken+=ch;
cin>>ch;
}
cout<<"("<<"num,"<<strToken<<")"<<endl;
}
else if(IsOperator(ch)){//判断是否为运算符
while(IsOperator(ch)){
strToken+=ch;
cin>>ch;
}
cout<<"("<<"operator,"<<strToken<<")"<<endl;
}
else if(IsSeparater(ch)){//判断是否为分隔符
cout<<"("<<"separater,"<<ch<<")"<<endl;
if(cin>>ch){}//继续读取下一字符,若读完所有源程序,退出读取字符循环
else break;
}
else{
cout<<"无法识别该字符!"<<endl;
if(cin>>ch){}
else break;
}
}
}
示例输入
示例输出