//////////////////////////////////////////////////////////////////////////
// Fundamentals of Compiler
//project: World analysis
//written by: kejie 03 computer science and techology 086
//create time: 2006.4.5
//modified: 2006.4.10
//file name: Analysis.h
//note: This file is the head file of the analysis.cpp,the declear of the class
//Copyright University of electronic science and technology of China, ZhongShan Institute.
//////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <ctype.h>
#include "BSTree.h"
#define MAXSTRTAKEN 20
#define MAXBUF 50
class LEX
{
public:
LEX();
LEX(char * path);
void LoadSource(); //開啟來源程式
void PrintSource(); //列印讀入的來源程式
int Analysis(); //開始分析
int ProError(int ErrorCode ); //錯誤處理,返回錯誤碼
private:
char GetChar(); //讀入字元
bool GetBc( char ReadChar ); //檢測讀入字元是否為空白格,斷行符號,換行
void Concat(); //將讀入的ch加入到已構成的單詞串中
int ResertKeyWord(); //strToken中的字串尋找關鍵表和內部符號表,返回內部編碼
int ResertOperator();
int * InsertId(); //將strToken中的字串插入符號表,返回符號表指標
int * InsertConst(); //將strToken中的字串插入常數表,返回符號表指標
void Retract(); //檔案指標回退一個字元位置,將ch置為空白
void ReSetBuf(); //將所有變數,緩衝初始化
void ReSetStrToken();
void DigitWordAnalysis(); //數字串識別
void StringAnalysis(); //字串關鍵字識別
void OperatorAnalysis(); //操作符識別
void SaveAnalysisResult(); //儲存分析結果
char strToken[MAXSTRTAKEN]; //存放構成單詞符號的字串
int strPos; //構成單詞符號位置
char buf[MAXBUF]; //讀入緩衝
int bufPos; //緩衝位置
char ch; //最新讀入來源程式字元
char * FilePath; //來源程式路徑
ifstream Infile; //檔案
};
//////////////////////////////////////////////////////////////////////////
// Fundamentals of Compiler
//project: World analysis
//written by: kejie 03 computer science and techology 086
//create time: 2006.4.8
//modified: 2006.4.15
//file name: Analysis.cpp
//note: Word analysis class implement
//Copyright University of electronic science and technology of China, ZhongShan Institute.
//////////////////////////////////////////////////////////////////////////
#include "Analysis.h"
char * SourcePath = "source.txt";
extern BSTree OperatorTable;
extern BSTree KeyTable;
LEX::LEX()
{
memset(strToken,0,MAXSTRTAKEN);
strPos = 0;
FilePath = NULL;
ch = '0';
memset(buf,0,MAXBUF);
bufPos = 0;
}
LEX::LEX(char * path)
{
memset(strToken,0,MAXSTRTAKEN);
strPos = 0;
FilePath = NULL;
ch = '0';
memset(buf,0,MAXBUF);
bufPos = 0;
FilePath = path;
}
//開啟來源程式
void LEX::LoadSource()
{
Infile.open(FilePath);
Infile.close();
}
//列印讀入的來源程式
void LEX::PrintSource()
{
Infile.open(FilePath);
//讀入來源程式,以行讀入,忽略空格
while(Infile.getline(buf,' '))
cout<<buf<<endl;
Infile.close();
}
//重設讀入緩衝
void LEX::ReSetBuf()
{
memset(buf,0,MAXBUF);
bufPos = 0;
ch = 0;
}
//重設讀入字串緩衝
void LEX::ReSetStrToken()
{
memset(strToken,0,MAXSTRTAKEN);
strPos = 0;
}
//讀入字元
char LEX::GetChar()
{
return buf[bufPos++];
}
//檢測讀入字元是否為空白格,斷行符號,換行
bool LEX::GetBc( char ReadChar )
{
//return (buf[bufPos] == 0x20 || buf[bufPos] == 0x00 );
return (ReadChar == 0x00 || ReadChar == 0x20 || ReadChar == 0x0d || ReadChar == 0x0a || ReadChar == 0x09 );
}
//將讀入的ch加入到已構成的單詞串中
void LEX::Concat()
{
strToken[strPos++] = ch;
}
//strToken中的字串尋找關鍵表和內部符號表,返回內部編碼
int LEX::ResertKeyWord()
{
return KeyTable.GetWordCode(strToken);
}
int LEX::ResertOperator()
{
return OperatorTable.GetWordCode(strToken);
}
//檔案指標回退一個字元位置,將ch置為空白
void LEX::Retract()
{
--bufPos;
ch = 0;
}
//將strToken中的字串插入符號表,返回符號表指標
int * LEX::InsertId()
{
return 0;
}
//將strToken中的字串插入常數表,返回符號表指標
int * LEX::InsertConst()
{
return 0;
}
//數字串識別
void LEX::DigitWordAnalysis()
{
while( isdigit((ch = GetChar())) )
Concat();
cout<<"< "<<strToken<<" , - >"<<endl;
Retract();
ReSetStrToken();
}
//字串/關鍵字識別
void LEX::StringAnalysis()
{
//如果讀入有數字則表示不是關鍵字
bool isKeyWorld = true;
int Code = -1;;
while( isalpha((ch = GetChar())) || isdigit(ch) )
{
if ( isdigit(ch) )
isKeyWorld = false;
Concat();
}
if ( isKeyWorld )
{
//如果尋找到關鍵字,則輸出編碼,否則為一般字元串
Code = ResertKeyWord();
if ( Code >= 0x00 )
cout<<"< "<<strToken<<" , "<<hex<<Code<<" >"<<endl;
else
cout<<"< "<<strToken<<" , - >"<<endl;
}
else
{
cout<<"< "<<strToken<<" , - >"<<endl;
}
Retract();
ReSetStrToken();
}
//操作符識別
void LEX::OperatorAnalysis()
{
//如果讀進時 " 時,則直接輸出到下一個 " 為止
if ( ch == '"')
{
strPos = 0;
while( (ch = GetChar()) != '"')
strToken[strPos++] = ch;
cout<<"< "<<strToken<<" , - >"<<endl;
ReSetStrToken();
return;
}
//再讀入一個,看看是否是二元操作符,不是的話回退一格
ch = GetChar();
if ( !isdigit(ch) && !isalpha(ch) && ResertOperator() )
{
Concat();
if ( ResertOperator() < 0 )
{
Retract();
strToken[--strPos] = 0;
}
}
else
Retract();
cout<<"< "<<strToken<<" , "<<hex<<ResertOperator()<<" >"<<endl;
//識別完一個後清空緩衝
ReSetStrToken();
}
//開始分析
int LEX::Analysis()
{
int buflen = 0;
//int bufindex;
Infile.open(FilePath);
//讀入來源程式,開始分析
//1.逐行讀入程式,放在緩衝buf中,分析完一行後清空buf,再讀入
while(Infile.getline(buf,' '))
{
//先判斷讀入的一行是不是注釋,是的話讀入下一行
if ( buf[0] == '/' && buf[1] == '/')
continue;
//2.分析緩衝buf,將字串加入strToken中,//ch儲存為讀入的單個字元
buflen = strlen(buf);
for( bufPos=0; bufPos<buflen; )
{
ch = GetChar();
Concat();
if ( isdigit(ch) ) //識別數字串
{
DigitWordAnalysis();
}
else if ( isalpha(ch) ) //識別字串/關鍵字
{
StringAnalysis();
}
else if ( GetBc( ch ) ) //判斷讀入符是否為空白格/換行/斷行符號
{
ReSetStrToken();
}
else //識別操作符
{
OperatorAnalysis();
}
}
ReSetBuf();
ReSetStrToken();
}
Infile.close();
return 0;
}
//儲存分析結果
void SaveAnalysisResult()
{
}
//錯誤處理,返回錯誤碼
int LEX::ProError( int ErrorCode )
{
return 0;
}