⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gj.cpp

📁 该编译器对表达式可实现词法分析,语法分析,语义分析
💻 CPP
字号:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <stack>
using namespace std;

const short WORDLEN=20;
void cifa_main();
void yufa_main();
void yuyi_main();

int is(const char c);
int os(const char c);
int Translate_Four(string s);

int key = 0 ;                   //存储标识
int key1 = 0 ;                  //存储标识
int step = 0;                   //语义分析的过程编号
int temp_step = 1;    

void S(void);void X(void);void X1(void);void Y(void);void Y1(void);void Z(void);void S1(void);//函数原型
struct code_val{char code;char val[WORDLEN];} t; //定义临时结构变量,存放单词二元式。
ifstream cinf("lex_r.txt",ios::in); //从文件lex_r.txt输入数据
ofstream coutf("par_r.txt",ios::out);//结果输出至文件screen.txt

//预处理函数原型
void pro_process(char *);
//扫描函数原型
code_val scanner(char *);
//拼接函数原型
void concat(char [],char);
//查保留字表函数
char reserve(char []);
//主函数
int main()
{
    cout<<"        欢迎使用,此编译器包括词法分析,语法分析,最后进行的是语义分析!"<<endl;
	cout<<"         源测试码在 source.txt 中 ,它能完成简单赋值语句的分析过程  !"<<endl;
    system("pause");		
	cout<<"词法分析部分:"<<endl;
	cout<<"**************************************"<<endl;
	cifa_main();
	cout<<"**************************************"<<endl;
	system("pause");


	cout<<"语法分析部分:"<<endl;
	cout<<"**************************************"<<endl;
	yufa_main();
	cout<<"**************************************"<<endl;
	system("pause");


	cout<<"语义分析部分:"<<endl;
	cout<<"**************************************"<<endl;
	yuyi_main();
	cout<<"**************************************"<<endl;
	return 0;
}
//词法主函数
void cifa_main()
{
	char buf[4048]={'\0'};//扫描缓冲区


//预处理
	pro_process(buf);
//显示buf
	cout<<buf<<endl;
//单词识别
	ofstream coutf("Lex_r.txt",ios::out);
	code_val t;//临时变量
	do{
		t=scanner(buf);//调用一次扫描器获得一个单词二元式
		cout<<t.code<<'\t'<<t.val<<endl;//屏幕显示单词二元式
 		coutf<<t.code<<'\t'<<t.val<<endl;//单词二元式输出至文件
	} while(t.code!='#');
	cout<<"End of lexical analysis!"<<endl;
	/*getch();*/
}
//扫描函数,每调用一次,返回一个单词的二元式。
struct code_val scanner(char *buf)
{
	static int i=0;//buf指针
	struct code_val t={'\0',"NUL"};//临时变量
	char token[WORDLEN]="";//用于拼接单词
//去除前导空格
	while(buf[i]==' ')i++;
//开始识别单词
	//标识符或基本字
	if(buf[i]>='a' && buf[i]<='z'){
		while(buf[i]>='a' && buf[i]<='z'||buf[i]>='0' && buf[i]<='9')
			concat(token,buf[i++]);
		t.code=reserve(token);//查保留字表
		if(t.code=='i')strcpy(t.val,token);//是标识符
		return t;//返回标识符或基本字的二元式
	}
	//整常数或实常数
	if(buf[i]>='0' && buf[i]<='9'){
		while(buf[i]>='0' && buf[i]<='9')
			concat(token,buf[i++]);
		if(buf[i]=='.'){//实常数123.
			concat(token,buf[i++]);
			while(buf[i]>='0' && buf[i]<='9')//123.4
				concat(token,buf[i++]);
			t.code='y';
		}
		else//整常数
			t.code='x';
		strcpy(t.val,token);
		return t;//返回当前单词整常数(123)或实常数(123.或123.4)的二元式
	}
	//实常数
	if(buf[i]=='.'){
		concat(token,buf[i++]);
		if(buf[i]>='0' && buf[i]<='9'){
			while(buf[i]>='0' && buf[i]<='9')
				concat(token,buf[i++]);
			t.code='y';
			strcpy(t.val,token);
			return t;//返回当前单词实常数(.123)的二元式
		}
		else{//单个.错误词形
			cout<<"Error word>"<<token<<endl;
			exit(0);
		}
	}
	//其余单词
	switch(buf[i]){
		case ',':
			t.code=',';
			break;
		case ';':
			t.code=';';
			break;
		case '(':
			t.code='(';
			break;
		case ')':
			t.code=')';
			break;
		case '=':
			t.code='=';
			break;
		case '+':
			if(buf[++i]=='+')	
				t.code='$';
			else{
				t.code='+';
				i--;
			}
			break;
		case '*':
			t.code='*';
			break;
		case '#':
			t.code='#';
			break;
		default://错误字符
			cout<<"Error char>"<<buf[i]<<endl;
			exit(0);
	}//end of switch
	i++;//指向下个单词
	return t;//返回当前单词的二元式
}
//拼接函数,原token="BEG", buf[i++]='I', 调用后token="BEGI"。
void concat(char token[],char c)
{
	for(int i=0;token[i];i++);
	token[i]=c;
	token[++i]='\0';
}
char reserve(char token[])
{
	const char *table[]={"begin","end","integer","real"};
	const char code[]={"{}ac"};
	for(int i=0;i<(int)strlen(code);i++)
		if(strcmp(token,table[i])==0) return code[i];
	return 'i';	//标识符的单词种别为'i'
}
//预处理函数
void pro_process(char *buf)
{
	ifstream cinf("source.txt",ios::in);
	int i=0;char old_c='\0',cur_c;//计数器,前一个字符,当前字符。
	bool in_comment=false;//状态标志,false表示当前字符未处于注释中。
	while(cinf.read(&cur_c,sizeof(char))){//从文件读一个字符
		switch(in_comment){
		case false:
			if(old_c=='/' && cur_c=='*'){//进入注释
				i--;//去除已存入扫描缓冲区的字符'/'
				in_comment=true;
			}
			else {
				if(old_c=='\\' && cur_c=='\n') //去除续行符'\',包括后续换行符。
					i--;//去除已存入扫描缓冲区的字符'\'
				else {
					if(cur_c>='A' && cur_c<='Z') cur_c+=32;//大写变小写
					if(cur_c=='\t' || cur_c=='\n') cur_c=' ';//空格
					buf[i++]=cur_c ;
				}
			}
			break;
		case true:
			if(old_c=='*' && cur_c=='/')//离开注释
				in_comment=false;
		}//end of switch
		old_c= cur_c;//保留前一个字符
	}//end of while
	buf[i]='#';
}
//语法主函数
string m;
void yufa_main(void)
{
	cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code; m=t.code;//读一个单词的二元式并输出单词种别
	S( );
	if(t.code=='#')
	{
		cout<<m<<endl;
		cout<<endl<<"语法分析结束,语法正确。"<<endl;
		coutf<<endl<<"ok"<<endl;
	}
	else
	{
		cout<<"语法分析结束,语法错误。"<<endl;
		coutf<<endl<<"语法分析结束,语法错误。"<<endl;
		exit(0);
		
	}
}
void S(void){//S -> i = X ; | S1 
	if(t.code=='i'){
			cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code;//读一个单词的二元式并输出单词种别
			if(t.code=='=')
			{
				cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code;//读一个单词的二元式并输出单词种别

				 X( ); 	
				 	if(t.code==';')
					{
						cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code;//读一个单词的二元式并输出单词种别
						S1();

					}
			}
	}

	else{
		cout<<"Err in S()>"<<endl;
		coutf<<endl<<"Err in S()>"<<t.code<<endl;exit(0);
	}
}
void S1(void)//S1 -> ; S1 | 空
{
	if(t.code=='i')
	{

	 S();
	}

	else if(!(t.code=='i'||t.code=='#'))
	{
		cout<<"Err in S1()>"<<endl;
		coutf<<endl<<"Err in S1()>"<<t.code<<endl;exit(0);

	}

}

void X(void)//X -> Y X1
{
	if(t.code=='-'||t.code=='i'||t.code=='x'||t.code=='y'||t.code=='('){//Y 的 first 集
	
		Y( ); X1( );
	}
	else 
	{
		cout<<"Err in X()>"<<endl;
		coutf<<endl<<"Err in X()>"<<endl<<t.code;
	}
}
void X1(void)//X1 -> + Y X1 | 空
{
	if(t.code=='+'){
		cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code;//读一个单词的二元式并输出单词种别 

		Y( );X1( );
	}
	else if(!(t.code==')'||t.code=='#'||t.code==';')){//if(!t.code∈follow(X1))
		cout<<"Err in X1()>"<<endl;
		coutf<<endl<<"Err in X1()>"<<t.code<<endl;exit(0);
	}
}
void Y(void)//Y -> Z Y1
{
	if(t.code=='-'||t.code=='i'||t.code=='x'||t.code=='y'||t.code=='('){//Z的frist集
		Z( );Y1( );
	}
	else {
		cout<<"Err in Y()>"<<endl;
		coutf<<endl<<"Err in Y()>"<<t.code<<endl;exit(0);
	}
}
void Y1(void)//Y1 -> * Z Y1 | 空
{
	if(t.code=='*'){ 
		cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code; //读一个单词的二元式并输出单词种别
		Z(); Y1();
	}
	else if(!(t.code=='+'||t.code==')'||t.code=='#'||t.code==';')){//if(!t.code∈follow(Y1))
		cout<<"Err in Y1>"<<endl;
		coutf<<endl<<"Err in Y1>"<<t.code<<endl;exit(0);
	}
}
void Z(void)//Z -> (X) | -Z | i | x | y 
{
	if(t.code=='i'||t.code=='x'||t.code=='y'){ 
		cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code; //读一个单词的二元式并输出单词种别
	
	}
	else if(t.code=='(')
	{
		cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code; //读一个单词的二元式并输出单词种别
		X();
		if(t.code==')')
		{
			cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code; //读一个单词的二元式并输出单词种别
		}
	}
	else if(t.code=='-')
	{
		cinf>>t.code>>t.val;cout<<t.code<<"  "<<t.val <<endl;coutf<<t.code;m=m+t.code; //读一个单词的二元式并输出单词种别
		Z();

	}
	else{
		cout<<"Err in Z>"<<endl;
		coutf<<endl<<"Err in Z>"<<t.code<<endl;exit(0);
	}


}
//语义主函数
int is(const char c)        //栈内符号优先级
{
	switch(c)
	{
		case '(': return 0;
		case '+': return 2;
		case '-': return 2;
		case '*': return 4;
		case '/': return 4;
		case ')': return 5;
		default: return -1;
	}
}

int os(const char c)         //栈外符号优先级
{
      switch(c)
	  {
		case '(': return 6;
		case '+': return 1;
		case '-': return 1;
		case '*': return 3;
		case '/': return 3;
		case ')': return 0;
		default: return -1;
	  }
}
void yuyi_main()
{
	string s;//构建s串,把2元式拼接
	ifstream cin("Lex_r.txt");//重新定义cin
	char cur_c[WORDLEN];
	int flag = 0;
	//cin >> t.code >> t.val;
	
	while( cin >> t.code >> t.val && t.code!='#')
	{
		//cout<<t.code<<endl;
		s = "";
		strcpy(cur_c , t.val);
	    cin >> t.code >> t.val ;
			
		s = s + cur_c; //构建 “i =”
		s = s + t.code;
			while( cin >> t.code >> t.val &&t.code !=';'&& t.code != '#' )
				{
					if(t.code=='i'||t.code == 'x'||t.code == 'y')   //变量
						s= s+t.val;
					else s=s+t.code;                              //符号
					flag = 1;
				}
				if(flag)
				{
					cout<<"分析表达式  : "<<s<<endl;
					Translate_Four(s);                              //分析表达式串
				}
	}

}			
int Translate_Four(string s)           //四元式翻译
{
stack<string> OPND;
stack<char> OPER;
char op;
string left, right;
int i = 0;
char sChange[10];
string sTemp;
for ( i=0; i<(int)s.length(); i++)
{
   if ( (s[i]>='0' && s[i]<='9') || (s[i]>='a' && s[i]<='z') )
   {
    sTemp = "";
    sTemp += s[i];
	int y = i+1 ;
	while( (s[y]>='0' && s[y]<='9') || (s[y]>='a' && s[y]<='z') || ( s[y] == '.' ) || ( s[y] == '_') )
	{
		sTemp += s[y];                          
		y++;				                  
	}
	i = y-1 ;
    OPND.push(sTemp);                      
	OPND.push("@");                             //用'@'来分隔
   }
   else                            //判断运算符
   {
    while (!OPER.empty() && os(s[i])<is(OPER.top()))   //站内优先级高,可以弹栈
    {
		left = right = "";
       if(OPND.top()=="@")
	   {	   
		   OPND.pop();
         right = right + OPND.top() ;      
         OPND.pop();
		}
	 if(OPND.top()=="@")
	{
		 OPND.pop(); 
		left = left + OPND.top();            
		 OPND.pop();
	 }
     op = OPER.top();
     OPER.pop();
     cout << "(" << step << ")   ";
     step++;
     sTemp = _itoa(temp_step, sChange, 10);        
     sTemp = "T" + sTemp;
  //   temp_num++;  
	 temp_step++;
     OPND.push(sTemp);
	 OPND.push("@");
   if(left[0]>='a'&&left[0]<='z') left = '&'+left;
   if(right[0]>='a'&&right[0]<='z' ) right = '&' + right;
     cout << op << "   " << left << "   " << right << "   " << sTemp << endl;
    }//end of while
    if(!OPER.empty() && os(s[i])==is(OPER.top()))   //遇到右“)”时,将 “(” 弹出
     OPER.pop();
    else
	{
		OPER.push(s[i]);         // 不满足优先级关系 或 符号栈为空 将当前运算符加入符号栈
	}	
   }
}
while (!OPER.empty())                 //将符号栈剩余符号依次弹出
{
	left = right = "";
	if( OPER.top() != '=')
	{
		if(OPND.top()=="@")
		{
			OPND.pop();
		   right = right + OPND.top();      //右操作数    
		}
		else 
		{
		   right = right + OPND.top();      //右操作数    
		}
		OPND.pop();
		if(OPND.top()=="@")
		{
			OPND.pop();
		left = OPND.top();                 //左操作数
		} 
		else 
		{	
		left = OPND.top();                //左操作数
		}
		OPND.pop();
      op = OPER.top();
      OPER.pop();
   cout << "(" << step << ")   ";
   step ++;
   sTemp = _itoa(temp_step, sChange, 10);
   sTemp = "T" + sTemp;
//    temp_num++;                    //临时变量加1
	temp_step++;                  //临时变量标识加1                 
   OPND.push(sTemp);              //临时变量压栈
   if(left[0]>='a'&&left[0]<='z') left = '&'+left;
   if(right[0]>='a'&&right[0]<='z' ) right = '&' + right;
   cout << op << "   " << left << "   " << right << "   " << sTemp << endl;
	}
	else /////////////////////            "="            //最后的“=” 号 处理
	{
	right = "0";                                // 右操作数置0
	if(OPND.top()=="@")
	{
		OPND.pop();
		left =left + OPND.top();
	}
	else 
		left =left + OPND.top();
	OPND.pop();
    op = OPER.top();
   OPER.pop();
   cout << "(" << step << ")   ";
   step++;
   //if(OPND.top()=='@') OPND.pop();
    sTemp = "";
	OPND.pop();
   sTemp += OPND.top();
   if(left[0]>='a'&&left[0]<='z') left = '&'+left; 
   if(sTemp[0]>='a'&&sTemp[0]<='z') sTemp = '&'+sTemp;
   cout << "j" <<op << "   " << left << "   " << right << "   " << sTemp << endl;
	}
}
return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -