使用C/C++语言编写PL/0编译程序的词法分析程序。 需要注意的点:
(1)识别非法字符:如 @ 、 & 和 ! 等;
(2)识别非法单词:数字开头的数字字母组合;
(3)标识符和无符号整数的长度不超过8位;
(4)能自动识别并忽略/* */及//格式的注释信息;
(5)词法分析过程中遇到错误后能继续往下识别,并输出错误信息。
完成上述编程任务,将C/C++语言源程序复制粘贴到右侧代码编辑器,点击“评测”按钮,运行程序,系统会自动进行结果对比。
平台会对你编写的代码进行测试:
测试输入:
const a = 10; var b, c; procedure fun1; if a <= 10 then begin c := b + a; end; begin read(b); while b # 0 do begin call fun1; write(2 * c); read(b); end end.
预期输出:
(保留字,const) (标识符,a) (运算符,=) (无符号整数,10) (界符,;) (保留字,var) (标识符,b) (界符,,) (标识符,c) (界符,;) (保留字,procedure) (标识符,fun1) (界符,;) (保留字,if) (标识符,a) (运算符,<=) (无符号整数,10) (保留字,then) (保留字,begin) (标识符,c) (运算符,:=) (标识符,b) (运算符,+) (标识符,a) (界符,;) (保留字,end) (界符,;) (保留字,begin) (保留字,read) (界符,() (标识符,b) (界符,)) (界符,;) (保留字,while) (标识符,b) (运算符,#) (无符号整数,0) (保留字,do) (保留字,begin) (保留字,call) (标识符,fun1) (界符,;) (保留字,write) (界符,() (无符号整数,2) (运算符,*) (标识符,c) (界符,)) (界符,;) (保留字,read) (界符,() (标识符,b) (界符,)) (界符,;) (保留字,end) (保留字,end) (界符,.)
测试输入:
const 2a = 123456789; var b, c; //单行注释 /* * 多行注释 */ procedure function1; if 2a <= 10 then begin c := b + a; end; begin read(b); while b @ 0 do begin call function1; write(2 * c); read(b); end end.
预期输出:
(保留字,const) (非法字符(串),2a,行号:1) (运算符,=) (无符号整数越界,123456789,行号:1) (界符,;) (保留字,var) (标识符,b) (界符,,) (标识符,c) (界符,;) (保留字,procedure) (标识符长度超长,function1,行号:10) (界符,;) (保留字,if) (非法字符(串),2a,行号:11) (运算符,<=) (无符号整数,10) (保留字,then) (保留字,begin) (标识符,c) (运算符,:=) (标识符,b) (运算符,+) (标识符,a) (界符,;) (保留字,end) (界符,;) (保留字,begin) (保留字,read) (界符,() (标识符,b) (界符,)) (界符,;) (保留字,while) (标识符,b) (非法字符(串),@,行号:17) (无符号整数,0) (保留字,do) (保留字,begin) (保留字,call) (标识符长度超长,function1,行号:19) (界符,;) (保留字,write) (界符,() (无符号整数,2) (运算符,*) (标识符,c) (界符,)) (界符,;) (保留字,read) (界符,() (标识符,b) (界符,)) (界符,;) (保留字,end) (保留字,end) (界符,.)
//识别保留字、运算符、标识符、界符、无符号整数 (可能还存在没有考虑的情况,仅供参考)
#include
using namespace std;
map B, Y; //B(保留字)、Y(运算符)
map J, y; //J(界符)
string s;
int F; //(标记'/*''*/'注释)
int main()
{
B["const"]=B["var"]=B["procedure"]=B["begin"]=B["end"]=B["odd"]=B["if"]=B["then"]=B["call"]=B["while"]=B["do"]=B["read"]=B["write"]=1; //保留字,13个
Y["+"]=Y["-"]=Y["*"]=Y["/"]=Y["<"]=Y["<="]=Y[">"]=Y[">="]=Y["#"]=Y["="]=Y[":="]=1; //运算符,11个
y['+']=y['-']=y['*']=y['/']=y['<']=y['>']=y['=']=y['#']=y[':']=1;
J['(']=J[')']=J[',']=J[';']=J['.']=1; //界符,5个
string s1 = "//", s2 = "/*", s3 = "*/", str;
for(int id = 1; getline( cin, s); id++) {
int f = 0; // (标记'//'注释)
for(int i=0; s[i]!='\0'; i++) { //双指针算法(扫描识别)
while(s[i]!='\0' && (s[i]==' ' || s[i]=='\t')) i++; //去掉空格与'\t'
int f1 = 0, f2 = 0, f3 = 0, f4 = 0, flog = 0;
int j1 = i, j2 = i; //j1(保留字、标识符、无符号整数)、j2(运算符)
if(!((s[i]>='0'&&s[i]<='9') || (s[i]>='a'&&s[i]<='z') || (s[i]>='A'&&s[i]<='Z') || y[s[i]]==1 || J[s[i]]==1)) flog = 1; //标记非法字符
while(s[j1]!='\0' && ((s[j1]>='0'&&s[j1]<='9') || (s[j1]>='a'&&s[j1]<='z') || (s[j1]>='A'&&s[j1]<='Z')) ) {//识别数字与字母串
if( s[j1]>='0'&& s[j1]<='9' ) f1 = 1; //标记数字
else f2 = 1; //标记字母
j1 ++;
}
while(s[j2]!='\0' && y[ s[j2] ] == 1) f3 = 1, j2 ++; //识别运算符,并标记运算符
if(J[ s[i] ] == 1) f4 = 1; //识别界符,并标记界符
if(f1 || f2) str = s.substr( i, j1-i); //提取字符串
if(f1 == 1 && f2 == 0 && !f && !F) { //无符号整数
if(str.size() <= 8) cout<<"(无符号整数,"<='0' && s[i]<='9') cout<<"(非法字符(串),"<