//基于LL(1)法的条件语句语法语义分析程序
#include<iostream.h>
#include<fstream.h>
#include<string.h>
#include<iomanip.h>
#include<malloc.h>
enum keyword{ $right_paren,$left_paren,$mul,$div,$add,$sub,$fenhao,
$equal,$IF,$THEN,$ELSE,$greater,$less,$id,$num,$end};
typedef struct Token
{
keyword type;
char ch;
}Token;
typedef enum{JUMP,JG,JL,equal,END,add,mul,sub,div}OpKind;
typedef struct
{
int label;//标号
OpKind op;//操作符
char par1,par2;//操作数
union
{
char result;//结果
int address;//地址
};
}Quad; //四元式入口
#define MAX_TOKEN 256//Token表大小
#define MAX_QUAD 256//四元式数组大小
Token tokentable[MAX_TOKEN];
Quad quad[MAX_QUAD];
int token_index;//token表索引
int total_len;//token表有效长度
int quad_len;//四元式表有效长度
int quad_index;//四元式索引
Token cur;
Token queue[10];
int label,k,one; //标记接口
char curchar;//存储当前待比较字符
char curtocmp;//存储当前栈顶字符
ifstream ins;
int trueadd,falseadd,end;
int table[5][8]={{1,0,0,0,0,1,0,0},
{0,1,1,0,0,0,1,1},
{1,0,0,0,0,1,0,0},
{0,1,1,1,1,0,1,1},
{1,0,0,0,0,1,0,0}}; //存储预测分析表,1为有产生式,0为没有
int i,j;
int flag;
struct Lchar
{
char char_ch;
struct Lchar *next;
}Lchar,*temp,*top,*base;
int right;//定义开关项
bool initialize(char filename[255]);//文件打开初始化
bool accidence();//词法分析
void print();//输出单词表
void backpath(int,int);//回填出口
void ERROR();
void sentence();//分析语句
void boolean();// 分析E->id < id | id > id语句
bool nexttoken();//读下一单词
char newchar();
void push();//进队列
char dosome(void);//算法函数
void pushs(char pchar);//入栈函数
void pop(void);//出栈函数
void doforpush(int t);//根据数组下标计算的值产生式入栈
void changchartoint();//根据curchar,curtocmp转为数字以判断是否有产生式
void semantic();//语法语义分析
char LL1();//LL(1)文法分析
void printQuad();//输出四元式
void ERROR(char str[20]);
void AD_ADDRESS(int nlabel,OpKind nop,char npar1,char npar2,int naddress);
void AD_RESULT(int nlabel,OpKind nop,char npar1,char npar2, char nresult);
void main()
{
cout<<" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "<<endl
<<" @ 基于LL(1)法的条件语句语法语义分析程序 @ "<<endl
<<" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "<<endl;
cout<<"输入您要编译文件的文件名(文件名.txt):";
char fname[100];
cin>>fname;
if(!initialize(fname))
return;
if(!accidence())
return;
char ch;
while(1)
{
if(ins.eof())
break;
ins>>ch;
}
cout<<endl<<"词法分析结果如下:";
print();
cout<<endl;
cout<<"词法分析结束。"<<endl<<endl;
semantic(); //语法语义分析
cout<<endl<<"输出四元式:"<<endl;
printQuad();
if(right==1)
cout<<"分析成功"<<endl;
else
cout<<"分析失败"<<endl;
cout<<"语法语义分析结束"<<endl;
}
char newchar()
{ char p;
p=char(k);
k++;
return p;
}
//文件打开初始化
bool initialize(char filename[100])
{
one=0;
token_index=0;
total_len=0;
quad_len=0;
quad_index=0;
label=0;
end=0;
k=48;
ins.open(filename,ios::nocreate | ios::in);
if(ins.fail())
{
cout<<"文件打开出错!"<<endl;
return false;
}
return true;
}
//词法分析
bool accidence()
{
int k=0;
char buf[16];
char ch;
while(1)
{
ins>>ch;
if(ins.fail())
break;
while(ch==' ')
{ ins>>ch;}
if(ch=='I')
{
ins>>buf;
if(strcmp(buf,"F")==0)
tokentable[total_len++].type=$IF;
}
else if(ch=='T')
{
ins>>buf;
if(strcmp(buf,"HEN")==0)
tokentable[total_len++].type=$THEN;
}
else if(ch=='E')
{
ins>>buf;
if(strcmp(buf,"LSE")==0)
tokentable[total_len++].type=$ELSE;
}
else if(ch=='>')
{
tokentable[total_len++].type=$greater;
}
else if(ch=='<')
{
tokentable[total_len++].type=$less;
}
else if(ch=='=')
{
tokentable[total_len++].type=$equal;
}
else if((ch>='A'&& ch<='Z' )|| (ch>='a' && ch<='z'))
{
tokentable[total_len].type=$id;
tokentable[total_len++].ch=ch;
}
else if(ch>='0' && ch<='9')
{ tokentable[total_len].type=$num;
tokentable[total_len++].ch =ch;
}
else
switch (ch)
{case '+' :
tokentable[total_len].type=$add;
tokentable[total_len++].ch =ch;
break;
case '-' :
tokentable[total_len].type=$sub;
tokentable[total_len++].ch =ch;
break;
case '/' :
tokentable[total_len].type=$div;
tokentable[total_len++].ch =ch;
break;
case '*' :
tokentable[total_len].type=$mul;
tokentable[total_len++].ch =ch;
break;
case ';' :
tokentable[total_len].type=$fenhao;
tokentable[total_len++].ch =ch;
break;
case '(' :
tokentable[total_len].type=$left_paren;
tokentable[total_len++].ch =ch;
break;
case ')' :
tokentable[total_len].type=$right_paren;
tokentable[total_len++].ch =ch;
break;
default:cout<<"!"<<endl;
}
}
return true;
}
//语法语义分析
void semantic()
{
if(!nexttoken())
ERROR("s(0)");
cout<<"开始进行语法语义分析:"<<endl
<<"所使用的产生式:"<<endl
<<"<if语句> -> if E then S else S"<<endl
<<"S->if E then else P2"<<endl
<<"E->a>b"<<endl
<<"P->x:=a*c"<<endl
<<"P->x:=b*c"<<endl
<<"语法语义分析过程如下:"<<endl;
if(cur.type==$IF)
{
boolean();//分析布尔语句
if(!nexttoken())
ERROR("S(0)");
if(cur.type==$THEN)
{
backpath(trueadd,quad_len);//回填出口
sentence();//分析语句
end=quad_len;
AD_ADDRESS(quad_len,JUMP,'-','-',end); //产生跳转地址的四元式
if(cur.type==$ELSE)
{
backpath(falseadd,quad_len);
sentence();
backpath(end,quad_len);
}
else
ERROR("S(else)");
}
else
{
ERROR("S(then)");
}
}
else
ERROR("S(if)");
AD_RESULT(quad_len,END,0,0,'-'); //产生数值语句的四元式
}
//读下一单词
bool nexttoken()
{
if(token_index>=total_len)
return false;
if(tokentable[token_index].type==$fenhao)
token_index++;
cur.type=tokentable[token_index].type;
cur.ch=tokentable[token_index].ch;
token_index++;
return true;
}
//进队列
void push()
{ one=0;
while(tokentable[token_index].type!=$fenhao)
{
queue[one].type=tokentable[token_index].type;
queue[one].ch=tokentable[token_index].ch;
cout<<queue[one].ch;
token_index++;
one++;
}
queue[one].type=$end;
queue[one].ch='#';
cout<<queue[one].ch;
}
//队列下一个字符
void next()
{
cur.type=queue[one].type;
cur.ch =queue[one].ch ;
one++;
}
// 分析E->id < id | id > id语句
void boolean()
{
char a,b;
int c;
if(!nexttoken())
ERROR("E(0)");
if(cur.type==$id||cur.type==$num)
{
a=cur.ch;
if(!nexttoken())
ERROR("E(0)");
if(cur.type==$greater||cur.type==$less)
{
c=cur.type ;
if(!nexttoken())
ERROR("E(0)");
if(cur.type==$id||cur.type==$num)
b=cur.ch;
else
ERROR("E(id/num)");
if(c==$greater)
{
trueadd=quad_len-1;
falseadd=quad_len;
AD_ADDRESS(quad_len,JG,a,b,trueadd);
AD_ADDRESS(quad_len,JUMP,0,0,falseadd);
}
else
{
trueadd=quad_len;
falseadd=quad_len+1;
AD_ADDRESS(quad_len,JL,a,b,trueadd);
AD_ADDRESS(quad_len,JUMP,0,0,falseadd);
}
}
else
ERROR("E(id/num)");
}
else
ERROR("E(greater/less)");
}
//分析语句
void sentence()
{ char rtn;
char c;
if(!nexttoken())
ERROR("S(0)");
if(cur.type==$id)
{
c=cur.ch;
if(!nexttoken())
ERROR("S(0)");
if(cur.type!=$equal)
ERROR("S(equal)");
push();
one=0;
rtn=LL1();
AD_RESULT(quad_len,equal,rtn,'-',c);
nexttoken();
while(cur.type==$id)