?? 詞法分析器.cpp
字號:
#include "iostream.h"
#include "fstream.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#define AND 1
#define ARRAY 2
#define BEGIN 3
#define CASE 4
#define CONST 5
#define DIV 6
#define DO 7
#define DOWNTO 8
#define ELSE 9
#define END 10
#define FILE 11
#define FOR 12
#define FUNCTION 13
#define GOTO 14
#define IF 15
#define IN 16
#define LABEL 17
#define MOD 18
#define NIL 19
#define NOT 20
#define OF 21
#define OR 22
#define PACKED 23
#define PROCEDURE 24
#define PROGRAM 25
#define RECODE 26
#define REPEAT 27
#define SET 28
#define THEN 29
#define TO 30
#define TYPE 31
#define UNTIL 32
#define VAR 33
#define WHILE 34
#define WITH 35 //35個關鍵字
#define IDENTIFIER 36 //標識符
#define UNSIGNINT 63 //整型
#define UNSIGNREAL 64 //實型
#define CHAR 65 //字符型
#define STRING 66 //字符串型
#define TAB 9
void Analysis(fstream &file)
{
char ch; //搜索字符
char word[121]; //單詞數組
int i; //單詞下標
int length; //單詞長度
int type; //單詞類型
bool tag,flag; //單詞分析循環控制變量,過程控制變量
char KEYWORD[10],keyword[10]; //準關鍵字和關鍵字
int INT; //無符號整型數的值
float REAL,weight; //無符號實型數的值,權
int exp; //指數
fstream finalfile,keyword_file;
finalfile.open("final.txt",ios::out|ios::app);
if(finalfile.fail())
{
cout<<"輸出文件打開失敗!"<<endl;
exit(0);
}
tag=true; //沒有語法錯誤
length=0; //初始化單詞長度
while(!file.eof() && tag)
{
file.get(ch);
if(!file.eof())
{
if((ch>='A' && ch<='Z') ||(ch>='a' && ch<='z') ) //標識符或關鍵字識別開始
{
i=0;
while( (ch>='A' && ch<='Z') || (ch>='a'&& ch<='z') || (ch>='0' && ch<='9') )
{
if(i<120) //截斷
{
word[i]=ch;
file.get(ch);
i++;
}
}
file.seekg(-1L,ios::cur); //文件指針回退一步
word[i]='\0';
length=i;
flag=true; //flag為true表示word是準關鍵字,false表示word為標識符
for(i=0;i<length;i++) //把標識符轉換成大寫字符串,以便判斷是不是關鍵字
{
if(word[i]>='a' && word[i]<='z')
KEYWORD[i]=word[i]-32;
else if(word[i]>='A' && word[i]<='Z' )
KEYWORD[i]=word[i];
else
{
flag=false;
type=IDENTIFIER; //word為標識符
break;
}
} //大寫轉換完畢
if(flag)
{
KEYWORD[i]='\0'; //字符串結束符
keyword_file.open("keyword.txt",ios::in); //打開關鍵字表
if(keyword_file.fail())
{
cout<<"找不到keyword_file!"<<endl;
exit(0);
}
keyword_file>>keyword;
type=1;
while(!keyword_file.eof()) //匹配關鍵字表
{
if(strcmp(keyword,KEYWORD)==0)
break;
else
{
keyword_file>>keyword;
type++;
}
}
keyword_file.close();
} //1-35為關鍵字,36為標識符,所以若關鍵字表找不到,type為36,剛好是標識符
finalfile<<type<<" "<<word<<endl; //存放到文件finalfile中去
break; //退出詞法分析循環
} //標識符或關鍵字識別完畢
else if(ch>='0' && ch<='9') //無符號數識別開始
{
i=0;
while(ch>='0' && ch<='9')
{
word[i]=ch;
file.get(ch);
i++;
}
if(ch!='.' && ch!='E')
{
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur); //文件指針回退一步
INT=0;
for(i=0;i<length;i++)
INT=INT*10+word[i]-'0';
finalfile<<UNSIGNINT<<" "<<INT<<endl;
break;
} //無符號整型數識別
else //無符號實型數識別開始
{
if(ch=='.') //開始處理小數點
{
word[i]=ch; //保存小數點
file.get(ch); //讀取下一個字符
i++; //下標前移
if(ch>='0' && ch<='9') //讀取小數點后的數開始
{
while(ch>='0' && ch<='9')
{
word[i]=ch;
i++;
file.get(ch);
} //小數部分讀取
if(ch!='E') //無符號實數xxx.xxx轉換開始
{
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur);
REAL=0.0;
for(i=0;word[i]!='.';i++) //整數部分
{
REAL=REAL*10+word[i]-'0';
}
weight=10.0;
for(i++;i<length;i++) //小數部分
{
REAL=REAL+(word[i]-'0')/weight;
weight*=10;
}
finalfile<<UNSIGNREAL<<" "<<REAL<<endl;
} //無符號實數xxx.xxx識別
else //繼續識別無符號實數XXX.XXXEXXX
{
word[i]=ch; //保存E
i++; //下標前移
file.get(ch); //讀取下一個字符
if(ch=='+' || ch=='-') //讀進一個正號或負號,如果沒有則略過
{
word[i]=ch;
i++;
file.get(ch);
}
if(ch>='0' && ch<='9')
{
while(ch>='0' && ch<='9') //讀取階碼
{
word[i]=ch;
i++;
file.get(ch);
}
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur);
REAL=0.0;
for(i=0;word[i]!='.';i++) //整數部分
{
REAL=REAL*10+word[i]-'0';
}
weight=0.1f;
for(i++;word[i]!='E';i++) //小數部分
{
REAL=REAL+(word[i]-'0')*weight;
weight/=10.0;
} //E前的尾數
i++;
weight=10.0; //如果沒有正負號,默認階碼為正
if(word[i]=='+') //判斷階碼正負號
{
weight=10.0;
i++;
}
else if(word[i]=='-')
{
weight=0.1f;
i++;
}
exp=0; //階碼
for(;i<length;i++)
{
exp=exp*10+word[i]-'0';
}
while(exp>0)
{
REAL=REAL*weight;
exp--;
}
finalfile<<UNSIGNREAL<<" "<<REAL<<endl;
} //無符號實數XXX.XXXEXXX識別
else
{
tag=false;
break;
}
} //無符號實數XXX.XXXEXXX識別
} //讀取小數點后的數結束
else
{
tag=false;
break;
}
} //小數點處理結束
else if(ch=='E') //開始處理E
{
word[i]=ch; //讀進一個E
i++; //下標前移
file.get(ch); //讀取下一個字符
if(ch=='+' || ch=='-') //讀進一個正號或負號,如果沒有就跳過
{
word[i]=ch;
i++;
file.get(ch);
}
if(ch>='0' && ch<='9')
{
while(ch>='0' && ch<='9') //讀取階碼
{
word[i]=ch;
i++;
file.get(ch);
}
word[i]='\0';
length=i;
file.seekg(-1L,ios::cur);
REAL=0.0;
for(i=0;word[i]!='E';i++) //整數部分
{
REAL=REAL*10+word[i]-'0';
} //E前的尾數
i++; //略過E
weight=10.0; //如果沒有正負號,默認階碼為正
if(word[i]=='+') //判斷階碼正負號
{
weight=10.0;
i++;
}
else if(word[i]=='-')
{
weight=0.1f;
i++;
}
exp=0;
for(;i<length;i++) //階碼
{
exp=exp*10+word[i]-'0';
}
while(exp>0)
{
REAL=REAL*weight;
exp--;
}
finalfile<<UNSIGNREAL<<" "<<REAL<<endl; //保存到文件finalfile
}
else
{
tag=false;
break;
}
} //E處理完畢
} //無符號實型數處理完畢
break; //退出詞法分析循環
} //無符號數識別完畢
else if(ch=='\'') //字符或字符串常數識別開始
{
i=0;
file.get(ch);
flag=true; //flag為true表示字符或字符串處理還沒結束,為false表示處理結束
while(flag)
{
if(ch=='\'')
{
file.get(ch);
if(ch=='\'') //讀到字符串中的“''”,即“'”號
{
word[i]=ch;
i++;
file.get(ch);
}
else //字符或字符串識別完畢
{
file.seekg(-1L,ios::cur);
flag=false;
}
}
else
{
if(i<120) //截斷
{
word[i]=ch;
i++;
file.get(ch);
}
}
if(file.eof())
{
tag=false;
break;
}
}
word[i]='\0';
length=i;
if(tag==false)
break;
if(length==0)
tag=false;
else if(length==1)
finalfile<<CHAR<<" "<<word<<endl;
else if(length>1)
finalfile<<STRING<<" "<<word<<endl;
break;
} //字符或字符串常數識別完畢
else if((ch>=40 && ch<=45) || ch=='/' || ch==';' || ch=='=')
{ //ASCII字符從40-47, ‘/’ , ‘;’ , ‘=’ 都是可唯一確定的界符,且編號等于它們的ASCII碼
finalfile<<int(ch)<<" "<<ch<<endl;
break;
}
else
{
flag=false; //flag 為true 表示已尋找到界符,為false表示沒有尋找到界符
switch(ch)
{
case'[':
finalfile<<54<<" "<<ch<<endl;
flag=true;
break;
case']':
finalfile<<55<<" "<<ch<<endl;
flag=true;
break;
case'^':
finalfile<<53<<" "<<ch<<endl;
flag=true;
break;
case'<':
file.get(ch);
if(ch=='=')
finalfile<<48<<" "<<'<'<<ch<<endl;
else if(ch=='>')
finalfile<<49<<" "<<'<'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int('<')<<" "<<'<'<<endl;
}
flag=true;
break;
case'>':
file.get(ch);
if(ch=='=')
finalfile<<50<<" "<<'>'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int('>')<<" "<<'>'<<endl;
}
flag=true;
break;
case':':
file.get(ch);
if(ch=='=')
finalfile<<51<<" "<<':'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int(':')<<" "<<':'<<endl;
}
flag=true;
break;
case'.':
file.get(ch);
if(ch=='.')
finalfile<<52<<" "<<'.'<<ch<<endl;
else
{
file.seekg(-1L,ios::cur);
finalfile<<int('.')<<" "<<'.'<<endl;
}
flag=true;
break;
case '\n':
case TAB:
case ' ':
while(ch==' '|| ch==TAB || ch=='\n') //略過空格
file.get(ch);
if(file.eof())
{
tag=false;
break;
}
file.seekg(-1L,ios::cur); //文件指針后移一步
break;
case '{': //清除注釋
while(ch!='}')
{
file.get(ch);
if(file.eof())
{
tag=false;
break;
}
}
break;
}
if(flag)
break;
}
}
}
finalfile.close();
}
void main()
{
fstream file;
file.open("source.txt",ios::in|ios::nocreate);
if(file.fail())
{
cout<<"文件打開失敗,請確認文件時候存在!"<<endl;
exit(0);
}
while(!file.eof())
Analysis(file);
cout<<"結果已保存到了文件final.txt中"<<endl;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -