#include"iostream.h"
#include"iomanip.h"
#include"stdlib.h"
#include"stdio.h"
#include"fstream.h"
#include"math.h"
#include"conio.h"
#include"string.h"
#define MAIN 1
#define ELSE 2
#define IF 3
#define INT 4
#define RETURN 5
#define VOID 6
#define WHILE 7
#define ADD 8
#define MINUS 9
#define MUL 10
#define DEVIDE 11
#define LESS 12
#define LESSEQURE 13
#define MORE 14
#define MOREEQURE 15
#define DEQURE 16
#define NODEQURE 17
#define EQURE 18
#define SEMICOLON 19
#define DOT 20
#define LPAREN 21
#define RPAREN 22
#define LMIDDLE 23
#define RMIDDLE 24
#define LBIG 25
#define RBIG 26
#define ID 27
#define NUM 28
//#define MAX 1999;
int Lexabc=0;
int Lextokennum=0;
int Lexerror1=0,Qiantao=0;
int LexLines=1,LexColumns=0;
int StrToken1=0;
char ch=' ',LexStrToken[10];
char ch1=' ';
int wrong=0;
int Token,j=1;
int Main=0; //判断原程序是否有主函数
int error1=0;
fstream LexFile;
char infilename[100];
fstream file,outfile;
struct key//用来存储关键字与专用符号
{
char keystring[7]; //存储关键字和专用符号
int value; //用一个简单数字对应一个关键字或专用符号
}Key[28]={{"main",1},{"else",2},{"if",3},{"int",4},
{"return",5},{"void",6},{"while",7},{"+",8},
{"-",9},{"*",10},{"/",11},{"<",12},{"<=",13},
{">",14},{">=",15},{"==",16},{"!=",17},{"=",18},
{";",19},{",",20},{"(",21},{")",22},{"[",23},
{"]",24},{"{",25},{"}",26},{"ID",27},{"NUM",28}}; //关键字表
//注意:以上结构体实现了一个数字对关键字字符串和专用符号的替代,这些
//数字在整个编译器的设计与实现当中起到了很好的作用
struct token //用来记录词法分析得到的单词符号的相关信息
{
char lexeme[10];//单词符号
int list;//类型
long int value;//单词符号的属性值
int lines;//所在行
int columns;//所在列
}LexToken[1000],token1;//token1
struct Lexerror//存储词法分析的错误信息
{
char errorwords[10];//非法单词符号
int lines;//所在行
int columns;//所在列
int type;//错误类型
}LexError1[100];
void LexError(int errortype)//错误处理
{
strcpy(LexError1[Lexerror1].errorwords,LexStrToken);
LexError1[Lexerror1].lines=LexLines;
LexError1[Lexerror1].columns=LexColumns;
LexError1[Lexerror1].type=errortype;
Lexerror1+=1;
}
void openfile(char* filename)//打开源文件
{
file.open("filename",ios::in|ios::binary);
if(file.fail()==1)
{
cout<<"Open"<<filename<<"Failed!"<<endl;
getch();
exit(0);
}
}
void openLexFile()//打开词法分析结果文件
{
outfile.open("Lex.txt",ios::out|ios::binary);
if(outfile.fail())
{
cout<<"Open File Lex.txt Failed!"<<endl;
getch();
exit(0);
}
}
void WriteFile(token temp)//写入文件
{
outfile.write((char*)&temp,sizeof(temp));
}
char GetChar()//读字符
{
file.get(ch);
LexColumns+=1;
if(ch=='\n')
{
LexLines+=1;
LexColumns=0;
}
return ch;
}
void GetBC()//略过空白符
{
while(((ch==' ')&&(file.eof()==0))|
((ch=='\n')&&(file.eof()==0))|
((ch=='\t')&&(file.eof()==0)))
GetChar();
}
void Concat()//字符归入字符串
{
LexStrToken[StrToken1]=ch;
StrToken1+=1;
}
bool IsLetter(char ch)
{
if((ch<='z'&&ch>='a')|(ch<='Z'&&ch>='A'))
return 1;
return 0;
}
bool IsDigit(char ch)
{
if(ch<='9'&&ch>='0')
return 1;
return 0;
}
int Reserve()//获取单词符号的属性值
{
ch=' ';
for(int i=0;i<28;i++)
if(strcmp(LexStrToken,Key[i].keystring)==0)
return i+1;
if(IsDigit(LexStrToken[0]))
return 28;
return 27;
}
void Retract()//读文件指针回退一个字符
{
file.seekg(-1l,ios::cur);
LexColumns-=1; //?????????
ch=' ';
}
void InsertID()//存单词符号
{
int list;
list=Reserve();
strcpy(LexToken[Lextokennum].lexeme,LexStrToken);
LexToken[Lextokennum].list=list;
LexToken[Lextokennum].columns=LexColumns;
LexToken[Lextokennum].lines=LexLines;
LexToken[Lextokennum].value=-1999;
if(list==28)
LexToken[Lextokennum].value=atoi(LexStrToken);
Lextokennum+=1;
}
void Break()//跳过非法字符
{
while((GetChar()!=' ')&&(file.eof()==0)) ;
}
void LexOut()//词法输出
{
for(int j=0;(j<100)&&(LexToken[j].lexeme[0]!='\0');j++)
{
cout<<"< "<<setw(6)<<LexToken[j].lexeme<<", ";
if(LexToken[j].list!=28) cout<<setw(3)<<"-"<<" >"<<endl;
else cout<<setw(3)<<LexToken[j].value<<" >"<<endl;
}
if(Lexerror1>0)
{
cout<<"***********************************词法错误***********************************"<<endl;
for(j=0;(j<100)&&(LexError1[j].lines!=0);j++)
{
cout<<"*"<<j+1<<". "<<LexError1[j].lines<<"行 "<<LexError1[j].columns<<"列 ";
if(LexError1[j].type==2)
cout<<"'"<<LexError1[j].errorwords<<"' 为非法标志符!"<<endl;
}
cout<<"******************************************************************************"<<endl;
}
else cout<<"程序无词法错误!"<<endl;
cout<<"词法分析完成!任意键返回主菜单"<<endl;
getch();
}
void Lex_main()
{
int code;
while(!file.eof())
{
GetBC();
if(file.eof()) break;
if(IsLetter(ch))
{
while(IsLetter(ch)|IsDigit(ch))
{
Concat();
GetChar();
}
Retract();
code=Reserve();
InsertID();
}
else if(IsDigit(ch))
{
while(IsDigit(ch))
{Concat(); GetChar();}
if(IsLetter(ch))
{
Concat();
LexError(2);
Break();
}
else InsertID();
Retract();
}
else if((ch=='<')|(ch=='>')|(ch=='=')|(ch=='!'))
{
Concat();
GetChar();
if(ch=='=')
{
Concat();
InsertID();
}
else{
InsertID();
Retract();
}
}
else if(ch=='/')
{
GetChar();
if(ch=='*')
{
if(Qiantao==1)
{
LexError(3);
Break();
}
else
{
Qiantao=1;
for(;;)
{
ch1=ch;
GetChar();
if(ch1=='/'&&ch=='*')
{
Qiantao+=1;
LexError(3);
Break();
}
if(ch1=='*'&&ch=='/')
{
Qiantao-=1;
if(Qiantao==0)
break;
}
}
}
}
else {
Retract();
ch='/';
Concat();
InsertID();
}
}
else
{
Concat();
InsertID();
}
ch=' ';
for(int i=0;(i<10)&&(LexStrToken[i]!='\0');i++)
LexStrToken[i]='\0';
StrToken1=0;
}//while
openLexFile();
for(int j=0;(j<1000)&&(LexToken[j].lexeme[0]!='\0');j++)
WriteFile(LexToken[j]);
outfile.flush();
if(Lexerror1==0)
wrong=1;
else wrong=2;
file.close();
outfile.close();
}
/************************************语法分析**************************************/
void declaration();
void var_declaration();
void type_special();
void type_specifier();
void fun_declaration();
void params();
void compound_stmt();
void params_list();
void param();
void local_declarations();
void statement_list();
void statement();
void selection_stmt();
void iteration_stmt();
void expression_stmt();
void expression();
void var();
void Rexpression();
void simple_expression();
void additive_expression();
void relop();
void term();
void addop();
void factor();
void mulop();
void args();
void arg_list();
void declaration_list();
void call();
void return_stmt();
void Reduce(int guiyue);
struct error//存储语法分析错误信息
{
char words[10];//不符合文法要求的单词符号
int lines;
int columns;
int errortype;
}Error[100];
void PassError()
{
while(LexFile.eof()==0)
{
LexFile.read((char*)&token1,sizeof(token));
Token=token1.list;
if(token1.list==19||token1.list==25||token1.list==26)
break;
}
}
void SyntaxError(int lines,int columns,int errortype,char* words)
{
Error[error1].lines=lines;
Error[error1].columns=columns;
if(LexFile.eof())
{
Error[error1].lines=lines;
Error[error1].lines+=1;
Error[error1].columns=1;
}
Error[error1].errortype=errortype;
strcpy(Error[error1].words,words);
error1+=1;
PassError();
}
void LexOpen()
{
LexFile.open("Lex.txt",ios::in|ios::binary);
if(LexFile.fail())
{
cout<<"Open File Le