基于第二章的词法分析程序,使用C/C++语言编写PL/0编译程序的语法分析程序。
完成上述编程任务,将C/C++语言源程序复制粘贴到右侧代码编辑器,点击“评测”按钮,运行程序,系统会自动进行结果对比。
平台会对你编写的代码进行测试:
测试输入:
const a = 10; var b, c; procedure p; if a <= 10 then begin c := b + a; end; begin read(b); while b # 0 do begin call p; write(2 * c); read(b); end; end.
预期输出:
语法正确
测试输入:
const a := 10; var b, c; procedure p; if a <= 10 then begin c := b + a; end; begin read(b); while b # 0 do begin call p; write(2 * c); read(b); end; end.
预期输出:
(语法错误,行号:1)
测试输入:
const a = 10; var b, c; //单行注释 /* * 多行注释 */ procedure p; if a <= 10 then begin c := b + a end; begin read(b); while b # 0 do begin call p; write(2 * c); read(b); end; end.
预期输出:
(语法错误,行号:13)
测试输入:
const a = 10; var b, c; //单行注释 /* * 多行注释 */ procedure p; if a <= 10 then begin c := b + a; end; begin read(b); while b # 0 begin call p; write(2 * c); read(b); end; end.
预期输出:
(语法错误,行号:17)
测试输入:
const a := 10; var b, c d; //单行注释 /* * 多行注释 */ procedure procedure fun1; if a <= 10 begin c = b + a end; begin read(b; while b # 0 begin call fun1; write 2 * c); read(b); end; end.
预期输出:
(语法错误,行号:1) (语法错误,行号:2) (语法错误,行号:10) (语法错误,行号:11) (语法错误,行号:13) (语法错误,行号:16) (语法错误,行号:17) (语法错误,行号:20)
#include
#include
#include
#include
using namespace std;
int h=1; //行号
char a[2000]; //所有字符
string END = "end.";
int i=0;
int ii=0;
char str[88]= "\0";
string ss[200]= {"\0"};
int cuowu=0;
int r=0;
string bao[20]= {"begin","call",
"const","do","end","if",
"odd","procedure",
"read","then",
"var","while","write"
};
void strcatt(char *s,char c) { //strcat(a,b) 将字符串a和b连起来
int i=0;
while(s[i]!='\0') i++;
s[i]=c;
s[i+1]='\0';
}
int length(char *a) { //字符串的长度
int i=0;
while(a[i]!='\0') {
i++;
}
return i;
}
int isstring(char ch) { //判断是否字符
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
return 1;
else
return 0;
}
int isyun(char ch) { //是否运算符
if(ch=='>'||ch=='<'||ch=='='||ch=='*'||ch=='-'||ch=='+'||ch=='#')
return 1;
else
return 0;
}
int isnum(char ch) { //是否数字
if((ch>='0'&&ch<='9'))
return 1;
else
return 0;
}
int isjie(char ch) { //是否界符
if(ch==';'||ch=='.'||ch==','||ch=='('||ch==')')
return 1;
else
return 0;
}
int isbao(char *s) { //是否保留字
for(int i=0; i<20; i++) if(bao[i].compare(s)==0) return 1;
return 0;
}
void bb(char c) { //处理字符串
if(isstring(c)||isnum(c)) {
strcatt(str,c);
i++;
bb(a[i]);
}
// else if(isnum(str[0])!=1)
else if(c==' '||c=='\n'||c=='\0'||isyun(c)||isjie(c)) {
if(isbao(str)) {
ss[ii++]=str;
//printf("(保留字,%s)\n",str);
str[0]='\0';
} else {
if(length(str)>=8) printf("(标识符长度超长,%s,行号:%d)\n",str,h);
else ss[ii++]=str;//printf("(标识符,%s)\n",str);
str[0]='\0';
}
} else {
strcatt(str,c);
printf("(非法字符(串),%s,行号:%d)\n",str,h);
i++;
str[0]='\0';
}
//else printf("error\n");
}
void aa(char c) { //处理数字串
if(isnum(c)) {
strcatt(str,a[i]);
i++;
aa(a[i]);
} else if(!isstring(c)) {
if(length(str)>=6) printf("(无符号整数越界,%s,行号:%d)\n",str,h);
else ss[ii++]=str;//printf("(无符号整数,%s)\n",str);
str[0]='\0';
} else {
while(a[i]!=' '&& isjie(a[i])!=1 && a[i]!='\0') {
strcatt(str,a[i]);
i++;
}
printf("(非法字符(串),%s,行号:%d)\n",str,h);
str[0]='\0';
//strcatt(str,c);
//i++;
//printf("(非法字符(串),%s,行号:%d)\n",str,h);
}
// else printf("error num\n");
}
void zhushi() {
if(!ss[ii].compare("\n")) {
ii++;
h++;
}
if(!ss[ii].compare("//")) {
ii++;
ii++;
while(!ss[ii].compare("\n")) {
ii++;
h++;
}
zhushi();
} else if(!ss[ii].compare("/*")) {
ii++;
while(ss[ii].compare("*/")) {
if(!ss[ii].compare("\n")) {
ii++;
h++;
} else {
ii++;
}
}
ii++;
}
while(!ss[ii].compare("\n")) {
ii++;
h++;
}
}
void changliang();
void error(int a);
void bianliang();
void yuju();
void tiaojian();
void biaodashi();
void xiang();
void yinzi();
void fenchengxv();
void shuzi() {
ii++;
}
void biaoshifu() {
ii++;
}
int id() {
int tt=0;
for(tt=0; tt")||!ss[ii].compare(">=")) {
ii++;
biaodashi();
} else if(!ss[ii].compare("odd")) {
ii++;
biaodashi();
} else error(0);
//if(!ss[ii].compare("\n")) {ii++; h++;}
}
void biaodashi() { //表达式
xiang();
if(!ss[ii].compare("+")||!ss[ii].compare("-")) {
ii++;
xiang();
while (!ss[ii].compare("+")||!ss[ii].compare("-")) {
ii++;
xiang();
}
}
//else if(!ss[ii].compare("\n")) {ii++; h++;}
}
void xiang() { //项
yinzi();
while(!ss[ii].compare("*")||!ss[ii].compare("/")) {
ii++;
yinzi();
}
}
void yinzi() { //因子
if(!ss[ii].compare("(")) {
ii++;
biaodashi();
if(!ss[ii].compare(")")) {
ii++;
} else error(0);
} else if(!ss[ii].compare("\n")) {
ii++;
h++;
} else ii++;
}
//用gets()来输入,自动舍弃\n,输入一个字符串,结尾使用\0.
int main() {
a[0]='\0';
scanf("%[^\.]",a);
a[length(a)]='.';
while(a[i]!='\0') { //每一行的每个字符 //词法分析
if(a[i]=='\0') break;
if(a[i]==9) {
i++;
continue;
}
if(a[i]==' ') {
i++;
continue;
}
if(a[i]=='\n') {
ss[ii++]="\n";//ss用于存储单词,ii当前单词下标
i++;
h++;
} else if(isstring(a[i])) {
bb(a[i]);
continue;//处理字符
} else if(isnum(a[i])) {
aa(a[i]) ;
continue;//处理数字
} else if(a[i]=='/') {
if(a[i+1]=='/') {
ss[ii++]="//";
i=i+2;
str[0]='\0';
while(a[i]!='\n') strcatt(str,a[i++]);
ss[ii++]=str;
ss[ii++]="\n";
i++;
continue;
} else if (a[i+1]=='*') {
ss[ii++]="/*";
i=i+2;
while(!(a[i]=='*'&&a[i+1]=='/')) {
if(a[i]=='\n') {
ss[ii++]="\n";
i++;
continue;
}
str[0]='\0';
while(a[i]!='\n') strcatt(str,a[i++]);
ss[ii++]=str;
ss[ii++]="\n";
i++;
}
ss[ii++]="*/";
i=i+2;
str[0]='\0';
continue;
} else {
while(a[i]!=' '&& isjie(a[i])!=1 && a[i]!='\0') {
strcatt(str,a[i]);
i++;
}
printf("(非法字符(串),%s,行号:%d)\n",str,h);
str[0]='\0';
break;
}
} else if(a[i]=='<'||a[i]=='>') {
i++;
if(a[i]=='=') {
if(a[i-1]=='<') ss[ii]="<=";
else ss[ii]=">=";
ii++;
i++;
continue;
} else {
if(a[i-1]=='<') ss[ii]="<";
else ss[ii]=">";
ii++;
continue;
}
} else if(a[i]==':') {
i++;
if (a[i]=='=') {
ss[ii++]=":=";
i++;
continue;
} else {
printf(":后面不是=号\n");
continue;
}
} else if(isyun(a[i])) {
ss[ii++]=a[i];
i++;
continue;
} else if(isjie(a[i])) {
ss[ii++]=a[i];
i++;
continue;
} else {
printf("(非法字符(串),%c,行号:%d)\n",a[i],h);
i++;
}
}
//语法分析
i=0;
ii=0;
h=1;
chengxv();
return 0;
}