内容:设计并实现含多条简单赋值语句的语法语义分析程序,要求采用递归下降翻译法。
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _KEY_WORD_END "waiting for your expanding"//定义关键字结束标志
typedef struct//单词二元组的结构
{
int typenum;
char *word;
}WORD;
char input[255];//输入换缓冲区
char token[255]="";//单词缓冲区
int p_input;//输入换缓冲区指针
int p_token;//单词缓冲区指针
int kk=0;
int k=0;
int i=0;
int j=0;
int sum=0;
WORD* oneword=new WORD;
char ch;//当前读入字符
char* rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END};//可扩充的关键字数组
int syn;
WORD* scaner();//词法扫描函数,获得一个单词
char m_getch(){//从输入缓冲区读取一个字符到ch中
ch=input[p_input];
p_input=p_input+1;
return (ch);
}
void retract(){//回退一个字符
p_input=p_input-1;
}
struct
{
char result[8];
char ag1[8];
char op[8];
char ag2[8];
}pquad[20];//四元式数组
void emit(char *result,char *ag1,char *op,char *ag2)
{
sprintf(pquad[j].result,result);//把字符串写入某个缓冲区
sprintf(pquad[j].ag1,ag1);
sprintf(pquad[j].op,op);
sprintf(pquad[j].ag2,ag2);
j++;
return;
}
char *newtemp(void)
{
char *p;
char m[8];
p=(char *)malloc(8);
k++;
itoa(k,m,10);//k转换的数据,m目标字符串的地址,10为转换后的进制数,把一个整数转换为字符串
strcpy(p+1,m);
p[0]='t';
return(p);
}
void PrintQuaternion(void)//打印四元数组
{
int nLoop;
for(nLoop=0;nLoop<j;nLoop++)
{
printf("(%d)%s=%s%s%s\n",nLoop+1,pquad[nLoop].result,pquad[nLoop].ag1,pquad[nLoop].op,pquad[nLoop].ag2);
}
}
char *factor();
char *term(void)
{
char *tp,*ep2,*eplace,*tt;//临时变量的编号,tp装计算结果,eplace左操作数,tt运算符,ep2右操作数
tp=(char *)malloc(12);
ep2=(char *)malloc(12);
eplace=(char *)malloc(12);
tt=(char *)malloc(12);
strcpy(eplace,factor());//调用term分析产生表达式计算的第一项eplace
while(syn==15||syn==16)
{
if(syn==15)
tt="*";
else
tt="/";
scaner();
strcpy(ep2,factor());//调用term分析产生表达式计算的第二项
strcpy(tp,newtemp());//调用newtemp产生临时变量tp存储计算结果
emit(tp,eplace,tt,ep2);//生成四元式送入四元式表
strcpy(eplace,tp);//将计算结果作为下一次表达式计算的第一项eplace
}
return(eplace);
}
char *expression(void)
{
char *tp,*ep2,*eplace,*tt;
tp=(char *)malloc(12);
ep2=(char *)malloc(12);
eplace=(char *)malloc(12);
tt=(char *)malloc(12);
strcpy(eplace,term());//调用term分析产生表达式计算的第一项eplace
while(syn==13||syn==14)
{
if(syn==13)
tt="+";
else
tt="-";
scaner();
strcpy(ep2,term());//调用term分析产生表达式计算的第二项
strcpy(tp,newtemp());//调用newtemp产生临时变量tp存储计算结果
emit(tp,eplace,tt,ep2);//生成四元式送入四元式表
strcpy(eplace,tp);//将计算结果作为下一次表达式计算的第一项eplace
}
return(eplace);
}
int statement()
{
char tt[8],eplace[8];
int schain=0;
{
switch(syn)//根据当前的单词符号判断是何种语句
{
case 10://赋值语句
strcpy(tt,token);
scaner();
if(syn==18)
{
scaner();
strcpy(eplace,expression());//调用expression进行分析
emit(tt,eplace,"","");
schain=0;
}
else
{
printf("赋值号错误");
kk=1;
}
return(schain);
break;
}
}
}
int yucu()
{
int schain=0;
schain=statement();//调用statement()
while(syn==26)//判断是否为;
{
scaner();//读下一个单词符号
schain=statement();//调用statement函数
}
return(schain);
}
int irparser()
{
int schain=0;
int kk=0;
if(syn!=1)
{
printf("begin错误\n");
kk=1;
}
scaner();//读下一个单词符号
schain=yucu();//调用yucu函数
if(syn==6)//判断是否为end
{
scaner();//读下一个单词符号
if(syn==0&&(kk==0))//前面语句未出错则kk为0,下一个单词为#则结束
{
printf("success\n");
}
}
else {
printf("缺end错误\n");
kk=1;
}
return(schain);
}
char *factor(void)
{
char *fplace;
fplace=(char *)malloc(12);
strcpy(fplace,"");
if(syn==11||syn==10)
{
strcpy(fplace,token);//将标识符token的值赋给fplace
scaner();
}
else if(syn==27)
{
scaner();
fplace=expression();//调用expression分析返回表达式的值
if(syn==28)
scaner();
else
{
printf("')'错误");
kk=1;
}
}
else
{
printf("'('错误");
kk=1;
}
return(fplace);
}
int main()
{
int over=1;
int ch1;
WORD* oneword=new WORD;
FILE *fp1;
fp1=fopen("f2.txt","r");
if(fp1==NULL)
{
printf("error");
}
while((ch1=fgetc(fp1))!='#'){
input[i]=ch1;
i++;
}
p_input=0;
scaner();
irparser();
PrintQuaternion();
fclose(fp1);//关闭文件
return 0;
}
void getbc(){//去掉空白符号
while(ch==' '||ch=='\n'){
ch=input[p_input];
p_input=p_input+1;
}
}
void concat(){//拼接单词
token[p_token]=ch;
p_token=p_token+1;
token[p_token]='\0';
}
int letter(){//判断是否字母
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
return 1;
else
return 0;
}
int digit(){//判断是否为数字
if(ch>='0'&&ch<='9'||ch=='.')
return 1;
else
return 0;
}
int reserve(){//检索关键字表格
int i=0;
while(strcmp(rwtab[i],_KEY_WORD_END)){
if(!strcmp(rwtab[i],token)){
return i+1;
}
i=i+1;
}
return 10;
}
char* dtb(){//数字转换为二进制
return NULL;
}
WORD* scaner(){
WORD* myword=new WORD;
myword->typenum=10;
myword->word="";
p_token=0;
m_getch();
getbc();
if(letter()){
while(letter()||digit()){
concat();
m_getch();
}
retract();
myword->typenum=reserve();
myword->word=token;
syn=myword->typenum;
return myword;
}
else if(digit()){
while(digit()){
concat();
m_getch();
}
retract();
myword->typenum=11;
myword->word=token;
syn=myword->typenum;
return myword;
}
else switch(ch){
case '=': m_getch();
if(ch=='='){
myword->typenum=39;
myword->word="==";
return myword;
}
retract();
myword->typenum=25;
myword->word="=";
syn=myword->typenum;
return myword;
break;
case '+': myword->typenum=13;
myword->word="+";
syn=myword->typenum;
return myword;
break;
case '-': myword->typenum=14;
myword->word="-";
syn=myword->typenum;
return myword;
break;
case '*': m_getch();
if(ch=='/'){
myword->typenum=700;
myword->word="*/";
syn=myword->typenum;
return myword;
}
retract();
myword->typenum=15;
myword->word="*";
syn=myword->typenum;
return myword;
break;
case '/': m_getch();
if(ch=='/'){
myword->typenum=500;
myword->word="//";
syn=myword->typenum;
return myword;
}
if(ch=='*'){
myword->typenum=600;
myword->word="/*";
syn=myword->typenum;
return myword;
}
retract();
myword->typenum=16;
myword->word="/";
syn=myword->typenum;
return myword;
break;
case '(': myword->typenum=27;
myword->word="(";
syn=myword->typenum;
return myword;
break;
case ')': myword->typenum=28;
myword->word=")";
syn=myword->typenum;
return myword;
break;
case '[': myword->typenum=29;
myword->word="[";
syn=myword->typenum;
return myword;
break;
case ']': myword->typenum=30;
myword->word="]";
syn=myword->typenum;
return myword;
break;
case '{': myword->typenum=31;
myword->word="{";
syn=myword->typenum;
return myword;
break;
case '}': myword->typenum=32;
myword->word="}";
syn=myword->typenum;
return myword;
break;
case ',': myword->typenum=33;
myword->word=",";
syn=myword->typenum;
return myword;
break;
case ':': m_getch();
if(ch=='='){
myword->typenum=18;
myword->word=":=";
syn=myword->typenum;
return myword ;
}
retract();
myword->typenum=17;
myword->word=":";
syn=myword->typenum;
return myword;
break;
case ';': myword->typenum=26;
myword->word=";";
syn=myword->typenum;
return myword;
break;
case '>': m_getch();
if(ch=='='){
myword->typenum=24;
myword->word=">=";
syn=myword->typenum;
return myword;
}
retract();
myword->typenum=23;
myword->word=">";
syn=myword->typenum;
return myword;
break;
case '<': m_getch();
if(ch=='='){
myword->typenum=22;
myword->word="<=";
syn=myword->typenum;
return myword;
}
else if(ch=='>'){
myword->typenum=21;
myword->word="<>";
return myword;
}
retract();
myword->typenum=20;
myword->word="<";
syn=myword->typenum;
return myword;
break;
case '!': m_getch();
if(ch=='='){
myword->typenum=40;
myword->word="!=";
syn=myword->typenum;
return myword;
}
retract();
myword->typenum=-1;
myword->word="ERROR";
syn=myword->typenum;
return myword;
break;
default:myword->typenum=0;
myword->word="ERROR";
syn=myword->typenum;
return myword;
}
}
测试文件:
begin
aa:=2+3564;
x:=(a+b)/c9.9
end#
测试结果:
注:此程序暂不支持错误恢复功能。