簡序:
大學中,有很多夢想,寫一個教學用的小編譯器就是一個。也曾就此與我最喜歡的年輕老師之一薛老師進行討論,后來更是聯系了另外兩個非常厲害的同學,準備大四一起做這個,運用有關模式,重新設計語言,把它做出來。
可是現在,學校中只我一人,他們都去北京實習去了。而自己要忙的事情也太多,想實踐演化證明的思路,想通過內核代碼把“進程”理解好,想整理自己數據結構的筆記,想把數學分析看完……這個夢想,或許也就永遠留在心中了。
忽然看到原來的一封email,寫給薛老師的,就原封不動的,轉貼在這里,紀念這段歲月時光!
不去評論過去的東西了;只是要記得,新的夢想,新的征程!
也愿所有的大學生朋友珍惜光陰,夢想成真。
percylee
2003-10-15于武漢
--------------------------------------------------------------------------------------
薛老師:
首先祝您節日快樂!
我是111001班的學生,前些日子和您說要寫個小編譯器,那時語言與詞法分析器已寫好了,可惜現在要忙于考試,但爭取寒假前多寫點。
語言很小,是基于代數結構<Z/rou;+,*>的,rou=mod(8),呵呵,目標語言是c++吧。希望能和您常聯系。
下面是語言的小例子:
item a, b={3}, c;
a ={5};
c=b*(a +b)+a ;
out<<"c="<<c;
c=a+a*b;
out<<"now c="<<c;
if(c==a*b)
then
out<<"c is the mutlip of a and b";
else
out<<"c isnot mutlip of a and b";
end;
您看看部分程序吧,我用c++寫的,感覺不少困難;但總是想,如果有一天寫完了,一定會很有收獲---這都是您課堂上講的呀;到時候我會到bbs上寫系列的帖子,把所有的設計過程和原代碼都展示給同學看。對了,我是那個kindman:),離散版塊上問問題,真希望能得到您的回答---或者,我找您吧,去找蔡老師,怕他太忙了。
//一個文件
#pragma once
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#define SIZE 50000 //默認最大文件字符數
#define WORDNUM 20000 //最大單詞數
#define CONSTNUM 100 //最大常量數
#define IDNUM 200 //最大標志符數
#define ELENUM 500 //常量運算單元數
#define ERRORSIZE 1000 //
class Sources
{
public:
Sources(void);
~Sources(void);
private:
const char * keyWords[7]; //關鍵字
char * constTable[CONSTNUM]; //常量(字符串)
char * idTable[IDNUM]; //自定義標志符
char * elementTable[ELENUM]; //運算單元
char idFollow[10]; //標志符follow集
int idNum;
int eleNum;
int constNum;
//......
public:
bool IsKeyword(const char *& keyWord,int &numOfkey);
bool IsIdfollow(const char ch);
int InsertID(const char *& strToken);
int InsertELE(const char *& strToken);
int InsertConst(const char *& strToken);
//......
};
//錯誤記錄
class ERROR
{
public:
int row;
static char * strError;
};
class Error
{
static int errorNum;
//int waringNum;
ERROR error[ERRORSIZE];
public:
Error(void);
~Error(void);
int GetErrornum()const;
void SetError(const char *&strError,int row);
void PrintError();
//......
};
//詞法分析
class Lexer
{
enum Token_value{
KW,ID,ELEMENT,CONST,
EQUAL,INPUT,OUTPUT,
ASSIGN=´=´,PLUS=´+´,MUL=´*´,PRINT=´;´,
LP=´(´,RP=´)´,COMMA=´,´,SEMI=´"´,ROWEND=´\n´
};
char ch; //reading file
char memary[SIZE];//file managed a lettle
char *word;
int realSize; // of memary
int rowCount; //of row in file
int wordCount; //of token
int charCount; //of reading ch in memary
int tokenChCount;//of every tokenWord
std::fstream file;
char *& strToken;//complete word in your code
struct Token{
Token_value tokval;
int codeNum;
int rowNum;
}token[WORDNUM];//result of lexical analysis
public:
Lexer(void);
~Lexer(void);
void Openfile(const char filename[30]);
// 讀一個字符至ch
void Readchar(void);
void ReCheckch();
//字符放入單詞
void Concat();
//
bool IsLetter();
bool IsDigit();
bool IsKeyword(const char* strWord,int &numOfkey,Sources source);
//詞法分析
void DoAnalysis(Sources source,Error error);
//編程需要:檢查中間結果
void Test();
};
//編譯處理
class Compiler
{
public:
Compiler(void);
virtual ~Compiler(void);
private:
//
Error error;
// 所用到的資源
Sources source;
// 詞法分析器
Lexer lexer;
public:
// 讀入待編譯文件
void Readfile(void);
void Test(void);
//.....
};
//另一個文件,實現詞法分析
#include "compiler.h"
#using <mscorlib.dll>
Lexer::Lexer(void):strToken(word)
{
rowCount=0;
charCount=0;
wordCount=0;
tokenChCount=0;
word=new char[200];
}
Lexer::~Lexer(void)
{
file.close();
delete word;
}
void Lexer::Openfile(const char filename[30])
{
char nextCh=´ ´;
int num=0;
// __try{
file.open(filename,ios_base::in|ios_base::out);
/* }
catch(System::NullReferenceException *e)
{
std::cerr<<"Error: Can´t open file "<<filename
<<",please make sure !"<<endl;
exit(-1);
}
*/
while(!file.eof()){
file.get(ch);
memary[num++]=ch;
if(ch==´ ´){
file.get(nextCh);
while(!file.eof()&&nextCh==´ ´)
file.get(nextCh);
memary[num++]=nextCh;
}
}
realSize=num;
}
void Lexer::Readchar()
{
if(charCount<realSize)
ch=memary[charCount++];
if(ch==´\n´&&ch!=´ ´) rowCount++;
}
void Lexer::ReCheckch()
{
while(ch==´ ´)
Readchar();
}
//
void Lexer::Concat()
{
word[tokenChCount++]=ch;
word[tokenChCount]=´\0´;
}
bool Lexer::IsLetter()
{
if(ch>=´A´&&ch<=´Z´)
return true;
if(ch>=´a´&&ch<=´z´)
return true;
return false;
}
bool Lexer::IsDigit()
{
switch(ch){
case ´0´:case ´1´:case ´2´:case ´3´:case ´4´:
case ´5´:case ´6´:case ´7´:case ´8´:case ´9´:
return true;
default:
return false;
}
}
bool Lexer::IsKeyword(const char* strWord,int &numOfkey,Sources source)
{
if(source.IsKeyword(strWord,numOfkey))
return true;
return false;
}
void Lexer::DoAnalysis(Sources source,Error error)
{
int code=-1,value=-1;
while(charCount<realSize)
{
tokenChCount=0;
Readchar();
ReCheckch();
if(IsLetter())
{
while(IsLetter() ||IsDigit())
{
Concat();
Readchar();
}
charCount--;
if(IsKeyword(strToken,code,source))
{
token[wordCount].codeNum=code;
token[wordCount++].rowNum=rowCount;
}
else
if(source.IsIdfollow(ch))
{
token[wordCount].rowNum=rowCount;
token[wordCount].tokval=ID;
value=source.InsertID(strToken);
token[wordCount++].codeNum=value;
}
else {
// error
while(ch!=´\n´)
Readchar();
error.SetError(strToken,rowCount-1);
}
}//if
else {
switch(ch)
{
case ´{´: Readchar();
while(IsDigit())
Readchar();
if(ch==´}´)
{
token[wordCount].rowNum=rowCount;
token[wordCount].tokval=ELEMENT;
value=source.InsertELE(strToken);
token[wordCount++].codeNum=value;
}
else
{
//error
while(ch!=´\n´)
Readchar();
error.SetError(strToken,rowCount-1);
}
break;
case ´=´:Readchar();
if(ch!=´=´)
{
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=ASSIGN;
charCount--;
}
else if(ch==´=´)
{
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=EQUAL;
}
break;
case ´+´:
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=PLUS;
break;
case ´*´:
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=MUL;
break;
case ´<´:
Readchar();
if(ch==´<´)
{
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=OUTPUT;
}
else
{
//error
while(ch!=´\n´)
Readchar();
error.SetError(strToken,rowCount-1);
}
break;
case ´>´:
Readchar();
if(ch==´>´)
{
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=INPUT;
}
else
{
//error
while(ch!=´\n´)
Readchar();
error.SetError(strToken,rowCount-1);
}
break;
case ´"´:Readchar();
while(ch!=´\n´&&ch!=´"´)
Readchar();
if(ch==´"´)
{
token[wordCount].rowNum=rowCount;
token[wordCount].tokval=CONST;
value=source.InsertConst(strToken);
token[wordCount++].codeNum=value;
}
else
{
//error
while(ch!=´\n´)
Readchar();
error.SetError(strToken,rowCount-1);
}
break;
case ´,´:
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=COMMA;
break;
case ´;´:
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=PRINT;
break;
case ´(´:
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=LP;
break;
case ´)´:
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=RP;
break;
case ´ ´:
// Readchar();
break;
case ´\n´:
token[wordCount].rowNum=rowCount;
token[wordCount++].tokval=ROWEND;
break;
default:
{
//error
while(ch!=´\n´)
Readchar();
error.SetError(strToken,rowCount-1);
}
}
}//else
}//while
}
//----------------------------------------------------------------------------
---------
void Lexer::Test()
{
cout<<"wordCount:"<<wordCount<<endl;
for(int i=0;i<wordCount;i++){
cout<<endl<<"row:"<<token[i].rowNum<<endl;
switch(token[i].tokval)
{
case KW:cout<<"keyword";
break;
case ID:cout<<"identifer";
break;
case ELEMENT:cout<<"element";
break;
case CONST:cout<<"const string";
break;
case PLUS:cout<<´+´;
break;
case MUL:cout<<´*´;
break;
case ASSIGN:cout<<´=´;
break;
case EQUAL:cout<<"==";
break;
case PRINT:cout<<´;´;
break;
case LP:cout<<´(´;
break;
case RP:cout<<´)´;
break;
case COMMA:cout<<´,´;
break;
case INPUT:cout<<">>";
break;
case OUTPUT:cout<<"<<";
break;
case SEMI:cout<<´"´;
break;
case ROWEND:cout<<"row_end";
break;
default:
;
}
}
}
祝您工作順利。
percy