📄 micro( ok 07.6.27基本完成).cpp
字号:
////////////////////////////////////////
//Micro 编译器前端
//辽宁科技大学
//计算机科学与工程学院
//计算机科学与技术 05 级2班
//刘世安
/////////////////////////////////////////
#include <iostream.h>
#include <stdlib.h>//atoi() atol()
#include <fstream.h>
#include <string.h>
struct FormStruct//变量属性结构体
{
char varName[10];
char varType[10];
};
struct PostfixStruct//后缀式存储表
{
char N_Str[10];//变量名
char C_Str[10];//变量类型
float R_Num;
int Z_Num;
};
struct PivotalStruct//关键字结构
{
char name[10];
char Outname[10];
int flag;
};
PivotalStruct guanjian[]={//初始化关键字
{"begin","$begin",1},
{"var","$var",2},
{"integer","$integer",5},
{"real","$real",5},
{"read","$read",9},
{"end","$end",11},
{"write","$write",10}};
class MicroComPile
{
private:
ifstream infile;
ofstream outfile;
char letter;
char thisWord[10];
float number;
int arraySign;
int numOfLine;
int flag;
bool numflag;
int err;
int warn;
int numOfEnter;
FormStruct varForm[20];//符号表
char *SourceFile;//保存文件
int Ecount;
PostfixStruct express[10];//后缀式存储空间
public:
MicroComPile(char *filename);
~MicroComPile();
void Read();
void NoBlank();//删除空格
void Append();
void Parser();//语法分析
void Identifier();
void Error(int n);//
void Match(int n,int m);//
void Expr();//
bool isLetter();//letter是字母
bool isDigit();//letter是数字
void Scanner();//词法分析
void DisplayResult();
void ReadConstant();//处理常数
void Semantic();//语义分析实现
void ExprSemantic();//语义分析实现使用
int varTest();//功能:检测变量是否有声明
void ErrOfSemantic(int n);
char* newadress(int n);//产生临时变量名
void disvarForm();//显示表格内容
void disbiao();
char* ProduceMiddleP();//中间代码生成
};
MicroComPile::MicroComPile(char *filename)
{
err=0;//为Error()初始化err;
warn=0;//为Scanner()初始化warn;
numOfEnter=1;
numOfLine=1;
infile.open(filename);
if(infile.fail())
{
cout<<"input.txt open fail \n";
exit(1);
}
infile.seekg(0,ios::end);
// 读指针移到文件尾
int FileSize= infile.tellg();
// 取文件大小,
SourceFile=new char[FileSize+1];
//动态声请内存
infile.seekg(0, ios::beg);
// 读指针移到文件头
arraySign=0;//初始化i;
while(!infile.eof())
{
SourceFile[arraySign]=infile.get();
arraySign++;
}
arraySign=0;//再次为Read()初始化i;
infile.close();
/////////////////////////////
outfile.open("output.txt");
if(outfile.fail())
{
cout<<"output.txt open fail n";
exit(1);
}
}
MicroComPile::~MicroComPile()
{
outfile.close();
}
void MicroComPile::Read()
{
letter=SourceFile[arraySign];
arraySign++;
numOfLine++;
}
void MicroComPile::DisplayResult()
{
cout<<"\n共"<<warn<<"个警告(词法分析)\n";
cout<<"共"<<err<<"个错误(语法语义分析)\n";
}
void MicroComPile::NoBlank()
{
while(letter==' ' || letter=='\n' ||
letter=='\t')
{
if(letter=='\n')
{
numOfEnter++;
numOfLine=0;
}
if(letter==' ')
numOfLine--;
Read();
}
}
///////////////////////////////////////////////
bool MicroComPile::isLetter()
{
if((letter>='a' && letter<='z') ||
(letter>='A' && letter<='Z'))
return true;
else
return false;
}
bool MicroComPile::isDigit()
{
if(letter>='0' && letter<='9')
return true;
else
return false;
}
void MicroComPile::Append()
{
int len=strlen(thisWord);
//求的已读到的字母个数,将本次读到的 单词加到未部
thisWord[len]=letter;
len++;
thisWord[len]='\0';
}
void MicroComPile::Identifier()
{
for(int i=0;i<10;i++)//将上次的单词清掉
thisWord[i]='\0';
while(isLetter() || isDigit())
{
Append();
Read();
}//while的条件不符时退到 Scanner
arraySign--;
//当最后读到的不是字符时要重新读入并处理
}
//若出现类似于 21str 这样的变量时当数字处理,
//字母舍掉
void MicroComPile::ReadConstant()
{
numflag=false;
for(int i=0;i<10;i++)//将上次的单词清掉
thisWord[i]='\0';
while( isDigit())
{
Append();
Read();
}//while的条件不符时退到 Scanner
if(letter=='.')
{
numflag=true;
do
{
Append();
Read();
}while(isDigit());
arraySign--;
//当最后读到的不是字符时要重新读入并处理
}
else
arraySign--;
//当最后读到的不是字符时要重新读入并处理
}
void MicroComPile::Scanner()
{
Read();
NoBlank();
//去掉while((SourceFile[i]!='\0'))后程序结束的条件
if(SourceFile[arraySign]==EOF)//6.14修改
{
flag=0;
return;
}
int b=0;
if(isLetter())//是字母
{
Identifier();//则到这里将其拼成单词
for(int i=0;guanjian[i].name[0];i++)
{
if(strcmp(thisWord,guanjian[i].name)!=0)
continue;
else
{
outfile<<guanjian[i].Outname<<endl;
flag=guanjian[i].flag;
b=1;//标记
break;
}
}
if(b==0)
{
outfile<<"($id,"<<thisWord<<")"<<endl;
flag=3;
}
}
else if(isDigit())//是数字
{
ReadConstant();
if(numflag)
{
outfile<<"($realC,"<<thisWord<<")"<<endl;
flag=17;
}
else
{
outfile<<"($intC,"<<thisWord<<")"<<endl;
flag=16;
}
}
//以下都是符号的处理
else if(letter=='(') //是符号输出相应的标志
{
outfile<<"$Lparen"<<endl;
flag=7;
}
else if(letter==')')
{
outfile<<"$Rparen"<<endl;
flag=8;
}
else if(letter=='+')
{
outfile<<"$plus"<<endl;
flag=15;
}
else if(letter=='*')
{
outfile<<"$mult"<<endl;
flag=14;
}
else if(letter==';')
{
outfile<<"$semi"<<endl;
flag=6;
}
else if(letter==':')
{
Read();//再向前看一个
if(letter=='=')
{
outfile<<"$assig"<<endl;
flag=12;
}//输出赋值标志。
else
{
outfile<<"$colon"<<endl;
flag=4;//退到 while()
arraySign--;
//当最后读到的不是字符时要重新读入并处理
}
}
else if(letter=='.')
//文件正常结束时 返回到主函数
{
outfile<<"$stop"<<endl;
flag=13;
}
else if(letter=='#')
{
do//删除注释
{
Read();
if(SourceFile[arraySign]=='\0')
{
cout<<"最后的#无对应的结束符\n";
break;
}
}while(letter!='#');
Scanner();//自调用
}
else//非法标点符号的处理
{ warn++;
cout<<"第"<<numOfEnter<<"行 第"<<numOfLine
<<"个标点符号: \""<<letter<<"\" 非法!\n";
}
}
void MicroComPile::Error(int n)
{ err++;
cout<<"第"<<numOfEnter<<"行 第"<<numOfLine<<"个字符处: ";
switch(n)
{
case 1:cout<<"程序头不是begin"<<endl;break;
case 2:cout<<"变量声明头不是var"<<endl;break;
case 3:cout<<"var后面不是标识符"<<endl;break;
case 4:cout<<"var id后不是\":\""<<endl;break;
case 5:cout<<"var id后不是类型符"<<endl;break;
case 6:cout<<"变量声明后不是\";\""<<endl;break;
case 7:cout<<"write后不是\"(\""<<endl;break;
case 8:cout<<"write(E 后不是\")\""<<endl;break;
case 9:cout<<"read后不是\"(\""<<endl;break;
case 10:cout<<"read(后不是id"<<endl;break;
case 11:cout<<"read(id后不是\")\""<<endl;break;
case 12:cout<<"赋值语句左部不是\":=\""<<endl;break;
case 13:cout<<"语句头单词错"<<endl;break;
case 14:cout<<"程序结束符错"<<endl;break;
case 15:cout<<"语句后继符错"<<endl;break;
case 16:cout<<"缺\"(E)\"中的 闭括号"<<endl;break;
case 17:cout<<"17运算分量的后继符错"<<endl;break;
default:cout<<"决不出现的错误!!!"<<endl;
}
}
void MicroComPile::Expr()
{
do{
Scanner();
//若条件成立,则再读一个单词,所以这里需要 Scanner()
if(flag==3);//ID
else if(flag==16||flag==17);//number
else if(flag==7)//(
{
Expr();
Scanner();
if(flag!=8)
Error(16);
}
else
Error(17);
Scanner();
}while(flag==14||flag==15); //+or*时while
}
void MicroComPile::Match(int n,int m)
{
Scanner();
if(flag!=n)
Error(m);
}
void MicroComPile::Parser()
{
Match(1,1);
Match(2,2);
do
{
Match(3,3);
Match(4,4);
Match(5,5);
Match(6,6);
Scanner();
}while(flag==2);
do
{
if(flag==10)//write
{
Match(7,7);//(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -