📄 预测分析.cpp
字号:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
#define max_id 256 //标识符最大长度;
#define stack_size 90 //栈的大小;
#define max_in 90 //输入存放数组的大小;
struct token_x{
char id;
char val[max_id];
}; //符号表表项的结构体定义;
#define max_buf 1024 //缓冲区大小;
#define symmax 100 //符号表长度;
#define tokmax 200 //记号表长度;
struct entry
{
char var[max_id];
char id;
void *addr; //存放内存地址(2字节),地址标识范围为0-65535
int type; //用于记录标识符的类型,1表示整型,0表示字符型;
}symtable[symmax]; //符号表表项及声明;
struct token
{ char id;
entry *ptr;
}toktable[tokmax]; //token字表表项结构体声明;
char buff[1024]={'\0'}; //全局变量,存储经过预处理后的源代码;
void ex_process(char *filename) //预处理函数,参数值为源代码文件的句柄;
{ ifstream infile(filename,ios::in);
char old_ch='\0',ch;
int i=0;
int flag=0;
bool in_comment=false;
while(infile.read(&ch,sizeof(char)))
{ switch(in_comment)
{ case false:
if(old_ch=='/'&&ch=='*') //遇到注释前标符则将注释标志变量值为真;
{ in_comment=true;
i--;
i--;
}
else if(ch=='\t'||ch=='\n'||ch==' ') //将制表符,换行符换为空格;
{ buff[i]=' ';
}
else if(ch>='A'&&ch<='Z')
{ buff[i]=ch+32;
}
else
{ buff[i]=ch;
}
break;
case true: //注释标志变量值为真则忽略注释中的字符
if(old_ch=='*'&&ch=='/') //遇到注释结束符将注释标志变量复位,跳出注释
in_comment=false;
i--;
break;
}
// cout<<ch;
i++;
old_ch=ch;
}
buff[i]='#';
cout<<buff<<endl;
}
void concat(char temp[],char c) //连接函数,将字符c连接到字符数组temp的末尾
{ for(int i=0;temp[i]!='\0';i++)
{ }
temp[i]=c;
temp[++i]='\0';
}
char ifkey(char *t)
/*查找函数,查找字符串t是否为源语言中的关键字
是则返回对应关键字的记号,否则则返回标识符记号'i'*/
{ char *table[]={"if","else","return","break","do","while","case","bool","true","false",
"int","char","then","void","for"};
char code[]={"0123456789abcde"};
int i;
int a=strlen(code);
for(i=0;i<a;i++)
if(strcmp(table[i],t)==0) return code[i];
return 'i';
}
struct entry idscan(void) //扫描函数,返回一个符号表表项的结构体
{ char temp[max_id]={'\0'};
entry temp_entry={'\0',"NUL"};
static int i=0;
temp[0]=0;
while(buff[i]==' ')
i++;
if(buff[i]>='a'&&buff[i]<='z') //扫描标识符;
{ while(buff[i]>='a'&&buff[i]<='z'||buff[i]>='0'&&buff[i]<='9')
{ concat(temp,buff[i]);
i++;
}
temp_entry.id=ifkey(temp);
strcpy(temp_entry.var,temp);
return temp_entry;
}
else if(buff[i]>='0'&&buff[i]<='9')//扫描数字;
{ if(buff[i]=='0')
{ concat(temp,buff[i]);
i++;
if(buff[i]=='.')
{ i++;
while(buff[i]>='0'&&buff[i]<='9')
{ concat(temp,buff[i]);
i++;
}
}
}
else
while(buff[i]>='0'&&buff[i]<='9')
{ concat(temp,buff[i]);
i++;
if(buff[i]=='.')
{ i++;
while(buff[i]>='0'&&buff[i]<='9')
{ concat(temp,buff[i]);
i++;
}
}
}
if(buff[i]=='e')
{ i++;
if(buff[i]=='+'||buff[i]=='-')
{ i++;
while(buff[i]>='0'&&buff[i]<='9')
{ concat(temp,buff[i]);
i++;
}
}
else
i--;
}
temp[i]='\0';
temp_entry.id='n';
strcpy(temp_entry.var,temp);
return temp_entry;
}
else //扫描界符;
{ switch(buff[i])
{ case ',':
temp_entry.id=',';
break;
case ';':
temp_entry.id=';';
break;
case '(':
temp_entry.id='(';
break;
case ')':
temp_entry.id=')';
break;
case '!':
if(buff[++i]=='=')
{ temp_entry.id='w'; // !=的id为w;
}
else
{ temp_entry.id='!';
i--;
}
break;
case '=':
if(buff[++i]=='=')
{ temp_entry.id='z'; // ==的id为z;
}
else
{ temp_entry.id='=';
i--;
}
break;
case '&':
if(buff[++i]=='&')
{ temp_entry.id='&';
}
else
{ temp_entry.id='&';
i--;
}
break;
case '+':
if(buff[++i]=='+')
{ temp_entry.id='u'; //++的id为u;
}
else
{ temp_entry.id='+';
i--;
}
break;
case '<':
if(buff[++i]=='=')
{ temp_entry.id='x'; // <=的id为x;
}
else
{ temp_entry.id='<';
i--;
}
break;
case '>':
if(buff[++i]=='=')
{ temp_entry.id='y'; // >=的id为y;
}
else
{ temp_entry.id='>';
i--;
}
break;
case '-':
if(buff[++i]=='-')
{ temp_entry.id='v'; // --的id为v;
}
else
{ temp_entry.id='-';
i--;
}
break;
case '*':
temp_entry.id='*';
break;
case '/':
temp_entry.id='/';
break;
case '#':
temp_entry.id='#';
break;
case '{':
temp_entry.id='{';
break;
case '}':
temp_entry.id='}';
break;
default:
cout<<"出错!语言中无此字符"<<buff[i]<<endl; //界符不识别则报错;
exit(0);
break;
}
i++;
strcpy(temp_entry.var,"NUL");
return temp_entry;
}
}
int symnum=0,toknum=0; //全局变量定义符号表指针及记号表指针;
int search(string a) //查找函数,若标识符已在符号表中则返回其在符号表中的位置,否则返回-1;
{ for(int i=0;i<symnum;i++)
if(a==symtable[i].var) return i;
return -1;
}
int insert(void) //将idscan返回的结构体插入符号表和记号表;
{
entry temp_entry={'\0',"NUL"};
while(1)
{ temp_entry=idscan();
if(temp_entry.id=='n'||temp_entry.id=='i')
{ if(symnum+1>=symmax||toknum+1>=tokmax)
{ cout<<"符号表或记号表空间不足!出错!"<<endl;
return 0;
}
if(search(temp_entry.var)==-1) //若当前标识符不在符号表中则将其插入;
{ symtable[symnum]=temp_entry;
toktable[toknum].id=temp_entry.id;
toktable[toknum].ptr=&symtable[symnum];
symtable[symnum].addr=toktable[toknum].ptr;
symnum++;
toknum++;
}
else //否则只将当前字符插入token表,表项指针指向已存在的符号表表项
{ int a=search(temp_entry.var);
toktable[toknum].id=temp_entry.id;
toktable[toknum].ptr=&symtable[a];
toknum++;
}
}
else
{ if(toknum+1>=tokmax)
{ cout<<"记号表空间不足!出错!"<<endl;
return 0;
}
toktable[toknum].id=temp_entry.id;
toktable[toknum].ptr=NULL;
toknum++;
}
if(temp_entry.id=='#') break;
}
return 1;
}
void display(void) //显示函数,输出符号表和记号表到文件;
{
ofstream outfile1("id.txt",ios::out);
for(int i=0;i<symnum;i++)
{ outfile1<<symtable[i].var<<'\t'<<symtable[i].id<<endl;
}
ofstream outfile2("token.txt",ios::out);
for(i=0;i<toknum;i++)
{// cout<<toktable[i].id;
outfile2<<toktable[i].id<<'\t'<<toktable[i].ptr<<endl;
}
}
int cifamain()
{ char filename[40];
cout<<"请输入源代码文件名:";
cin>>filename;
// cout<<filename;
ex_process(filename);
insert();
display();
return 0;
}
char row[]={"QPLDVEWTFBMSNRX"}; //预测分析表的行标号;
char collumn[]={"i()a;+*>&=0c54{}n$"}; //预测分析表的列标号;
int M[15][20]={ {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,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,-1,-1,-1},
{-1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,6,-1,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,-1},
{-1,-1,9,-1,9,9,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{10,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,-1},
{12,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,23,-1},
{13,13,-1,-1,-1,-1,-1,-1,14,-1,-1,15,-1,15,-1,-1,13,-1},
{16,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{19,-1,-1,-1,-1,-1,-1,-1,-1,-1,17,-1,18,-1,-1,-1,-1,-1},
{21,-1,-1,-1,-1,-1,-1,-1,-1,-1,21,-1,21,-1,-1,20,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,-1,-1,-1},
{24,24,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,-1,24,-1}
};
const char *q[]={"Q→P","P→i()L;R","L→DL","L→$","D→ai;","V→+TV","V→$","E→TV"
,"W→*FW","W→$","T→FW","F→(E)","F→i","B→XB","B→&B","B→$","M→i=E"
,"S→if B then M","S→while B do M","S→M","N→$","N→S;N","R→{N}","F→n","X→F>F"};
const char *p[]={"P","RL)(i","LD","\0",";ia","VT+","\0","VT"
,"WF*","\0","WF",")E(","i","BX","B&","\0","E=i"
,"McB0","M4B5","M","\0","N;S","}N{","n","F>F"};
// for-e,while-5,do-4,if-0,else-1,++-u,---v,>=-y,<=-x,==-z,!=-w,then-c,int-a
/*文法产生式;
0.Q→P
1.P→i()LR
2.L→DL
3.L→$
4.D→ai;
5.V→+TV
6.V→$
7.E→TV
8.W→*FW
9.W→$
10.T→FW
11.F→(E)
12.F→i
13.B→XB
14.B→&B
15.B→$
16.M→i=E
17.S→if B then M
18.S→while B do M
19.S→M
20.N→$
21.N→S;N
22.R→{N}
23.F→n
24.X→F>F
*/
struct siyuanshi//语义四元式的数据结构
{
string op;//操作符
string arg1;//操作数
string arg2;//操作数
string result;//结果
}stable[200];
int s_ptr; //四元式指针;
struct L //真链与假链项的数据结构;
{ int a; //标记真链或假链中的四元式标号;
L *next; //指向下个节点的指针;
};
L *Ltrue,*Lfalse;//真链与假链的链首指针;
string tval_table[1024]; //临时变量表;
int tval_ptr=0; //临时变量序号指针;
string id_name,id0_name,id1_name,id2_name,E_name,T_name,F_name,plus_name,mul_name,V_name,W_name;
int err=0,id_then,id_do,id_while;
struct S
{ int position;
int num;
};
S yuyi_stack[200]; //定义产生式调用寄存栈;
int stack_ptr=0;
int lookup(string m)//检查变量是否已经声明
{
for(int i=0;i<symnum;i++)
{ if(symtable[i].var==m) break;
}
if(symtable[i].type==1)
return 1;
else
return 0;
}
string newop(int m)//数字变成字符串生成临时变量;
{
int shang,yushu;
string chuan,chuan1;
shang=m;
chuan="";
while(1)
{
yushu=shang%10;
chuan=chuan+char(48+yushu);
shang=shang/10;
if(shang==0)
break;
}
int i;
char *ch;
ch=&chuan[0];
chuan1="";
for(i=strlen(ch)-1;i>=0;i--)
chuan1=chuan1+chuan[i];
return(chuan1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -