?? gj.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 + -