武汉理工大学《编译原理》课程设计说明书
词法分析程序如下: void lexical()
{ //\是其一条特殊的例子 int i,j,d; char ch; j=d=0; for(i=0;var[i]!='#';i++) { ch=var[i]; if(ch=='i'&&var[i+1]=='f') { cout<<\关键字]\ queue[j++]='f';i+=1; }//{判断\关键字} else if(ch=='t') { ch=var[i+1]; if(ch=='h') { ch=var[i+2]; if(ch=='e') { ch=var[i+3]; if(ch=='n') { ch=var[i+4]; } } } cout<<\关键字]\ queue[j++]='t';i+=3; }//{判断\关键字} else if(ch=='e') { ch=var[i+5]; if(ch=='l') { ch=var[i+6]; if(ch=='s') { ch=var[i+7]; if(ch=='e')
6
武汉理工大学《编译原理》课程设计说明书
{ ch=var[i+8]; } } } cout<<\关键字]\ queue[j++]='e';i+=3; }//{判断\关键字} else if(index(ch,VT)<=0) { if(ch!='{'&&ch!='}'&&ch!='('&&ch!=')') { cout< 5 语法分析 主要的思想是设置一个分析栈和一个输入串队列,栈中最开始时存放的是文法开始 符和“#”。因为我这个程序本身已经确定是以if语句开头,所以,就不再把if放在 输入串中,而只是分析if以后的句子。在语法分析之前应该判定该文法是不是一个 LL(1)文法。判别的主要方法是做出文法中所有产生式的select集,对于同一个非终 结符的不同产生式,如果他们的select集合没有交集,则说明这个文法是LL(1)文法。 这个文法的预测分析表也设计的比较简单,如下表所示: {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1}, {1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 2, -1}, 7 武汉理工大学《编译原理》课程设计说明书 {4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {5, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, 6, 7, -1, -1, -1, -1, -1, 8, 8, 8}, {9, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1}, {-1, -1, -1, -1 , 12, 12, 10, 11, -1, -1, -1, 12, 12, 12}, {14, -1, -1, -1, -1, -1,- 1, -1, 13, -1, -1, -1, -1, -1}, {-1, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1,- 1,- 1, -1}, //预测分析表 注:除了-1代表此处有产生式与之对应,具体的产生式在程序中给出。-1代表此处无 产生式与之对应。 void syntax() { int n; count++; print(); X=stack[sp]; a=queue[front]; if(X=='#'&&a=='#')f=4; if(X<'A'||X>'Z') //{判断字符集不是大写字母集合} { if(X==a) { sp--; front++; if(a!='i') //{\是特征字母} { if(a!='f'&&a!='t'&&a!='e'&&a!=';'&&a!='#') { opr=index(a,VT); 8 武汉理工大学《编译原理》课程设计说明书 } semantic(); else if(a==';'||a=='e'||a=='t'||a=='#') { opr=-2; } else f=1; //字符不匹配,转去出错处理 } else { int tx=index(X,VN);//{索引选择} int ta=index(a,VT);//{索引选择} n=M[tx][ta]; //{产生式选择} td[t++]=M[tx][ta]; //{产生式选择} if(ta==-1) { f=2;cout< opd=c; //cout< cout<<'\\t'<<'\\''< cout<<'\\t'<<'\\''< semantic(); } //字符没有出现在产生式终结符集VT中,转去出错处理 else if(n==-1)f=3; //没有找到合适的候选产生式来做进一步推导,转去出错处理 9 武汉理工大学《编译原理》课程设计说明书 } else { //用产生式M[tx][ta]来做进一步推导 } } if(f==0)syntax(); else { td[t]='-1'; err(f); } sp--; cout<<'\\t'< else cout<<\空串\ for(int i=len(p[n])-1;i>=0;i--) { } cout< stack[++sp]=p[n][i]; cout< 因为在推导过程中,会一并完成产生式后面附加的语义动作,所以这两部分是一起做的。 另外,在LL(1)分析过程中,会出现错误信息,如字符不匹配,或字符没有出现在产生式终结符集VT中,或没有找到合适的候选产生式来做进一步推导,会调用相应的出错处理函数err(f)。另外,此函数是递归实现,结束标志是f!=0,即成功或失败。 10