【编译原理与技术】词法分析器(C++实现)
目录
注:
为了简化程序的编写,做了如下的限制:
(1) 空白符仅仅是空格、回车符、制表符。
(2) 代码是自由格式。
(3) 注释不允许嵌套。
单词:
根据要求,可以自行添加其他保留字或者特殊符号
实现功能:
- 识别单词并给出其类型
- 删除注释行
- 删除空白符 (空格、回车符、制表符)
- 在单词的前面加上行号
- 发现并定位错误。
算法分析
main()函数中负责读取文件中字符数据,并保存在prog【】数组中。利用while循环调用GetToken()函数,判断字符状态并进行输出。GetToken()函数中负责判断字符类型并标记其类型状态。
C++代码:
#include <string.h> #include <string> #include<iostream> using namespace std; char prog[1000],ch,ch1,token[1000]; int p=0,sym=0,n,line=1; char filename[30]; FILE *fpin; const char *keyword[21]={"if","else","while","do","main","int","float", "double","return","const","void","continue","break","char", "signed","enum","long","switch","case","auto","unsigned"}; void GetToken(); int main() { p=0; cout<<"请输入源文件名:"; for(;;) { cin>>filename; if((fpin=fopen(filename,"r"))!=NULL)//只读 { break; } else { cout<<"文件输入错误!请输入源文件名:"; } } //将fpin中的所有字符通过ch传入字符数组prog[]中 do { ch=fgetc(fpin); prog[p++]=ch; }while(ch!=EOF); p=0; do { GetToken();//启动字符识别函数 //if(ch==EOF) break; switch(sym)//打印字符状态 { case 1:cout<<"("<<line<<" "<<token<<" "<<"标识符"<<")"<<endl;break; case 2:cout<<"("<<line<<" "<<token<<" "<<"保留字"<<")"<<endl;break; case 3:cout<<"("<<line<<" "<<token<<" "<<"整型"<<")"<<endl;break; case 31:cout<<"("<<line<<" "<<token<<" "<<"浮点型"<<")"<<endl;break; case 32:cout<<"("<<line<<" "<<token<<"S"<<" "<<"短类型"<<")"<<endl;break; case 33:cout<<"("<<line<<" "<<token<<"L"<<" "<<"长类型"<<")"<<endl;break; case 34:cout<<"("<<line<<" "<<token<<"O"<<" "<<"八进制数"<<")"<<endl;break; case 35:cout<<"("<<line<<" "<<token<<"H"<<" "<<"十六进制数"<<")"<<endl;break; case 4:cout<<"("<<line<<" "<<token<<" "<<"特殊符号"<<")"<<endl;break; case -1:cout<<"("<<line<<" "<<"错误!"<<")"<<endl;break; default:break; } }while(ch!=EOF); return 0; } void GetToken() { sym=0; //先把token[]数组清空 for (n=0;n<1000;n++) { token[n]='\0'; } n=0; ch=prog[p++]; ch1=prog; //跳过空格,回车,tab的识别 while(ch==' '||ch=='\t') { ch=prog[p++]; } if(ch=='\n'){ line++; return; } if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch=='_')) { //标识符 状态1 sym=1; do{ token[n++]=ch; ch=prog[p++]; }while ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')); //比较标识符与keyword的关键字是否相同,若相同转为状态2 for(n=0;n<21;n++) { if(strcmp(token,keyword[n])==0){ sym=2; break; } } p--; return; } else if (ch>='0'&&ch<='9') { //识别到数字,置状态为3 sym=3; do { token[n++]=ch; ch=prog[p++]; if(ch=='.'){ sym=31; token[n++]=ch; ch=prog[p++]; } if(ch=='S'){ sym=32; ch=prog[p++]; } if(ch=='L'){ sym=33; ch=prog[p++]; } if(ch=='O'){ sym=34; ch=prog[p++]; } if(ch=='H'){ sym=35; ch=prog[p++]; } }while(ch>='0'&&ch<='9'); p--; return; } //跳过注释的内容 else if(ch=='/' && ch1=='*') { p++; do{ ch=prog[p++]; ch1=prog[p++]; if(ch=='\n'){ line++; } }while(ch!='*'||ch1!='/'); return; } else if(ch=='/'&& ch1=='/') { do{ ch=prog[p++]; }while(ch!='\n'); line++; return; } else if(ch=='='&& ch1=='='){ p++; sym=4; token[0]='='; token[1]='='; return; } else if(ch=='<'&& ch1=='='){ p++; sym=4; token[0]='<'; token[1]='='; return; } else if(ch=='>'&& ch1=='='){ p++; sym=4; token[0]='>'; token[1]='='; return; } else if(ch=='!'&& ch1=='='){ p++; sym=4; token[0]='!'; token[1]='='; return; } else if(ch=='&'&& ch1=='&'){ p++; sym=4; token[0]='&'; token[1]='&'; return; } else if(ch=='|'&& ch1=='|'){ p++; sym=4; token[0]='|'; token[1]='|'; return; } else { switch(ch)//识别关键符号 { case '=': case '<': case '>': case '/': case '+': case '-': case '*': case '{': case '}': case ';': case '(': case ')': case ',': case '\'': case '\"':sym=4;token[0]=ch;break; default:sym=-1;break; } } return; }
运行结果:
[p]- 点赞 1
- 收藏
- 分享
- 文章举报
- 编译原理:第七节 及词法分析器的C++和Python实现
- 【编译原理与技术】递归下降语法分析器(C++实现)
- C++实现编译原理的词法分析器
- 编译原理(六) LL(1)文法分析法(分析过程的C++实现)
- C++函数编译原理和成员函数的实现
- 编译原理(七) 算符优先分析法(构造算符优先关系表算法及C++实现)
- C++函数编译原理和成员函数的实现
- C++ 接口与实现分离技术---如何将文件间的编译关系降至最低
- 编译原理(一) Chomsky文法的判断方法及C++代码实现
- 编译原理(六) LL(1)文法分析法(分析过程的C++实现)
- 编译原理 #01# 简易词法分析器(JavaScript实现)
- 编译原理--C-Minus词法分析器C++实现
- 编译原理(八) 算符优先分析法(分析过程的算法和C++实现)
- 编译原理(九) LR(0)文法分析法(算法描述和C++代码实现)
- 编译原理(七) 算符优先分析法(构造算符优先关系表算法及C++实现)
- 编译原理(1)词法分析程序(C++实现)
- 编译原理——Tiny词法分析器c++实现
- 设计有穷自动机DFA实现C++简单程序的词法分析、扫描(编译原理实验) 推荐
- 编译原理----词法分析器实现(C)
- c++ 编译原理 简单词法分析器