?? assembler.cpp
字號:
#include "assembler.h"
Assembler::Assembler()
{
InitTwoTables(); //初始化預(yù)測分析表和語法規(guī)則表
InitRegsAlias(); //初始化寄存器編號與別名對應(yīng)表
GenFiles();
TOKEN.TokenID = 0;
TOKEN.TokenName = "";
No_Com = 0; //指令行編號
No_Var = 0; //變量行編號
No_TxtLine = 0;
for ( int z = 0; z < RamSize; z++ )
{
CodeUnitUsed[z] = false;
DataUnitUsed[z] = false;
}
}
Assembler::~Assembler()
{
ShutFiles();
}
void Assembler::Parser( FILE* SourceFileName )
{
int v = SyntacticAnalysis(SourceFileName);
if ( v != 0 )
{
cout << "Error occurs...SyntacticAnalysis' return value: " << v << endl;
ErrorProcess(v);
}
else
cout << "Succeed!" << endl;
}
int Assembler::SyntacticAnalysis( FILE * SourceFileName )
{
int i;
int LastRule;
int dataline = 0; //用以指示數(shù)據(jù)文件的行數(shù)
TOKEN.TokenID = 0;
STACK.push(-1);
STACK.push(N_PRO);
// CMD是32位char類型,存放最新已經(jīng)語法分析得到的指令的二進制碼,初始化為'0'
for ( i = 0; i < 32; i++ )
CMD[i] = '0';
// 調(diào)用詞法分析器Scanner,依據(jù)棧頂符號<N_PRO>,從源程序中讀取第一個
// 單詞入TOKEN中,如果返回-1,表示源程序中有詞法錯誤
if ( Scanner(STACK.top(), SourceFileName) )
return ERROR_LEX;
//cout << TOKEN.TokenID << '\t' << TOKEN.TokenName << endl;
//開始LL(1)分析,包含調(diào)用詞法分析器Scanner和指令翻譯器ConstructCMD
while (1)
{
if ( STACK.top() == -1 ) //若棧空,且當(dāng)前讀入源程序單詞為-1,則語法分析完成,并正確
{
// fprintf( DataFile, "END;" ); //寫入數(shù)據(jù)文件最后一個單詞"END"
// 以下是寫數(shù)據(jù)文件的結(jié)尾,因為程序文件是一次性寫的,所以它的起始和結(jié)尾都是在同一個函數(shù)WriteProg()中完成的
fprintf( DataFile, " [" );
fprintf( DataFile, "% x", No_Var );
fprintf( DataFile, "..3FF] : 00000000;\nENDS;" );
int rrt = WriteProg();
if ( rrt == -1 ) //將指令寫入程序文件,返回值為-1,表示地址交迭
return ERROR_CODE_ADDR_OVERLAPPED;
else if ( rrt == -2 ) //將指令寫入程序文件,返回值為-2,表示有轉(zhuǎn)移指令引用不存在的指令標(biāo)號名
return ERROR_NOTEXIST_SEGID;
return 0; //匯編過程成功退出
}
if ( STACK.top() > CountOfVT )
//如果當(dāng)前棧頂為VN,則查預(yù)測分析表
{
// if ( (STACK.empty()) || (TOKEN.TokenID == -1) )
//若棧空,且當(dāng)前讀入源程序單詞為-1,則語法分析完成,并正確
if ( ForcastTable[STACK.top()-CountOfVT][TOKEN.TokenID] == 0 )
return ERROR_SEMANTIC;
else
{
LastRule = ForcastTable[STACK.top()-CountOfVT][TOKEN.TokenID]; //記錄編號
// cout << "NT:LastRule: " << LastRule << "\tTOKEN.TokenID: " << TOKEN.TokenID << endl;
if ( Deduction(ForcastTable[STACK.top()-CountOfVT][TOKEN.TokenID]) == 5 )
return ERROR_DEDUCTION;
continue;
}
}
else
//當(dāng)前棧頂為VT,則匹配,并翻譯
{
if ( STACK.top() == TOKEN.TokenID )
//當(dāng)棧頂為終結(jié)符,并和當(dāng)前讀取的單詞同,則匹配
{
// store segids with SEGID
if ( LastRule == 27 && TOKEN.TokenID == T_IDNAME )
//如果最近采用的是27號產(chǎn)生式,則IDNAME是指令標(biāo)號,
//順序保存到標(biāo)號表SEGID
if ( AddNormalSegID() )
return ERROR_REIDNAME; //如果標(biāo)號有重復(fù)則錯誤退出
if ( LastRule == 15 && TOKEN.TokenID == T_IDNAME )
//如果最近采用的是15號產(chǎn)生式,則IDNAME是起始指令標(biāo)號,
//保存到標(biāo)號表SEGID的最前面
if ( AddStartSegID() )
return ERROR_REIDNAMES; //如果標(biāo)號有重復(fù)則錯誤退出
if ( ( LastRule == 36 || LastRule == 42 ) && TOKEN.TokenID == T_IDNAME ) //J,JAL,BEQ,BNE中遇到IDNAME,需要回填
//如果最近采用的是36號產(chǎn)生式,則IDNAME是轉(zhuǎn)移的目的標(biāo)號
//保存到回填表BACKTABLE中
if ( AddBackID() )
return ERROR_BACK; //添加失敗則錯誤退出
/////////////TRANSLATATION/////////////////////////////////////
//////////SEMANTICS RULES OF <N_COM> RULES/////////////////////
if ( LastRule == 17 || LastRule == 18 || LastRule == 19
|| LastRule == 20 || LastRule == 21 || LastRule == 22
|| LastRule == 23 || LastRule == 30 || LastRule == 32
|| LastRule == 33 || LastRule == 34 || LastRule == 35
|| LastRule == 37 ||LastRule == 36 || LastRule == 38
|| LastRule == 39 || LastRule == 40 || LastRule == 41 || LastRule == 42 || LastRule == 43 ) //表明當(dāng)前讀取的是指令 LastRule == 36,23|| ??? J,JAL,BEQ,BNE中遇到IDNAME,需要回填
{
/* cout << "VT:LastRule: " << LastRule << endl
<< "STACK.top(): " << STACK.top() << endl
<< "TOKEN.TokenID: " << TOKEN.TokenID << endl
<< "TOKEN.TokenName: " << TOKEN.TokenName << endl;
*/ if ( STACK.top() != T_ENDL ) //如果當(dāng)前讀取的不是指令結(jié)束的單詞,則翻譯
{
if ( ConstructCMD() ) // 將當(dāng)前單詞翻譯為二進制碼,存入CMD,注意這些函數(shù)是成功時才返回0,否則返回非零值
return ERROR_CONCMD; //翻譯失敗退出
}
else if ( STACK.top() == T_ENDL )
//當(dāng)前讀取的是指令結(jié)束的單詞,則CMD保存了一個完整指令的二進制碼,并且當(dāng)前TOKEN.TokenName串中保存的就是用戶解釋
{
if ( ConstructCOMMANDS() )
//將CMD按照指令順序保存到指令鏈COMMANDS
return ERROR_CONCMDS;
// cout << "after concmds: " << endl;
}
}
////////
////////
if ( LastRule == 9 && STACK.top() == T_IDNAME )
//如果當(dāng)前讀取的是標(biāo)識符,且產(chǎn)生式為9號
//則說明當(dāng)前是定義變量,將變量標(biāo)識符保存到VAR
if ( StoreVar() )
return ERROR_DEFVAR; //變量定義錯誤
////////
////////
if ( LastRule == 9 && STACK.top() == T_32NUM )
//如果當(dāng)前讀取的是32位數(shù)據(jù),且產(chǎn)生式為9號
//則說明當(dāng)前是定義變量,將值輸出到數(shù)據(jù)文件
{
if ( DataUnitUsed[No_Var] == true )
return ERROR_DATA_ADDR_OVERLAPPED;
if ( dataline != No_Var )
{
if ( dataline == No_Var - 1 )
{
fprintf( DataFile, "\t" );
fprintf( DataFile, "% x", dataline );
fprintf( DataFile, " : \t00000000;\n" );
}
else
{
fprintf( DataFile, "\t\t[" );
fprintf( DataFile, "% x", dataline );
fprintf( DataFile, ".." );
fprintf( DataFile, "% x", No_Var - 1 );
fprintf( DataFile, "] : 00000000;\n" );
}
dataline = No_Var;
}
fprintf( DataFile, " " );
fprintf( DataFile, "% x", No_Var );
fprintf( DataFile, " : " );
fprintf( DataFile, TOKEN.TokenName );
fprintf( DataFile, ";\n" );
DataUnitUsed[No_Var] = true;
No_Var++;
dataline++;
}
//////////////////////
//////////////////////以下是由讀入的ADDR來設(shè)置指令地址No_Com和數(shù)據(jù)地址No_Var
if ( LastRule == 5 && STACK.top() == T_ADDR ) //數(shù)據(jù)地址
{
int tempv = AddrToInt( TOKEN.TokenName );
if ( tempv % 4 != 0 ) //如果地址不能被4整除,則返回錯誤
return ERROR_DATA_ADDR;
No_Var = tempv/4;
}
if ( LastRule == 13 &&STACK.top() == T_ADDR ) //指令地址
{
int tempc = AddrToInt( TOKEN.TokenName );
// cout << tempc << endl;
if ( tempc % 4 != 0 ) //如果地址不能被4整除,則返回錯誤
return ERROR_CODE_ADDR;
No_Com = tempc/4;
}
///////////////////////////////////////////////////////
STACK.pop(); //匹配完成彈出棧頂元素
if ( STACK.top() == -1 )
{
// cout << "stack is empty" << endl;
continue;
}
// cout << "After pop stack, top is " << STACK.top() << endl;
if ( Scanner(STACK.top(), SourceFileName) )
{
return ERROR_LEX;
}
// cout << "after scanner: " << TOKEN.TokenID << '\t' << TOKEN.TokenName << endl;
}
else //棧頂為終結(jié)符,并和當(dāng)前讀取的單詞不同,則匹配失敗
{
return ERROR_SEMANTIC;
}
}
} // end while
return -1;
}
int Assembler::Scanner(int TypeOfToken,FILE *SourceFileName)
{
int State=0;
static char ret[256];
int i = 0;
int times = 0;
if ( TypeOfToken > CountOfVT ) //當(dāng)前棧頂符號為非終結(jié)符
{
switch ( TypeOfToken-CountOfVT )
{
case 1: //當(dāng)前棧頂符號為<N_PRO>
case 2: //當(dāng)前棧頂符號為<N_DATA>
{ //掃描DATA或CODE單詞
char ch = ReadOneChar(SourceFileName);
if ( ch == '\n' )
No_TxtLine++;
while ( 1 )
{
switch ( ch )
{
case 'd':
case 'D':
{
if(State==0) {State=1;break;}
if(State==6) {State=7;break;}
else return -1;
}
case 'a':
case 'A':
{
if(State==1) {State=2;break;}
if(State==3) {State=4;break;}
else return -1;
}
case 't':
case 'T':
{
if(State==2) {State=3;break;}
else return -1;
}
case 'c':
case 'C':
{
if(State==0) {State=5;break;}
else return -1;
}
case 'o':
case 'O':
{
if(State==5) {State=6;break;}
else return -1;
}
case 'e':
case 'E':
{
if(State==7) {State=8;break;}
else return -1;
}
case ' ':
case '\t':
// case '\n':
{
if(State==4){TOKEN.TokenID=1;TOKEN.TokenName="DATA";return 0;}
if(State==8){TOKEN.TokenID=1;TOKEN.TokenName="CODE";return 0;}
else return -1;
}
default: return -1;
}
ch = getc( SourceFileName );
if ( ch == '\n' )
No_TxtLine++;
}
break;
}
case 4: //當(dāng)前棧頂符號為<N_DATASEG>
case 9: //當(dāng)前棧頂符號為<N_DATAENDS>
{ //根據(jù)預(yù)測分析表,以上兩種情況應(yīng)該掃描DATA單詞
char ch = ReadOneChar(SourceFileName);
if ( ch == '\n' )
No_TxtLine++;
while ( 1 )
{
switch ( ch )
{
case 'd':
case 'D':
{
if(State==0) {State=1;break;}
else return -1;
}
case 'a':
case 'A':
{
if(State==1) {State=2;break;}
if(State==3) {State=4;break;}
else return -1;
}
case 't':
case 'T':
{
if(State==2) {State=3;break;}
else return -1;
}
case ' ':
case '\t':
// case '\n':
{
if(State==4){TOKEN.TokenID=1;TOKEN.TokenName="DATA";return 0;}
else return -1;
}
default: return -1;
}
ch = getc(SourceFileName);
if ( ch == '\n' )
No_TxtLine++;
}
break;
}
case 5: //當(dāng)前棧頂符號為<N_ORG_DATA>
{ //應(yīng)該掃描ORG_DATA單詞
char ch = ReadOneChar(SourceFileName);
if ( ch == '\n' )
No_TxtLine++;
while ( 1 )
{
switch ( ch )
{
case 'o':
case 'O':
{
if(State==0) {State=1;break;}
else return -1;
}
case 'r':
case 'R':
{
if(State==1) {State=2;break;}
else return -1;
}
case 'g':
case 'G':
{
if(State==2) {State=3;break;}
else return -1;
}
case '_':
{
if(State==3) {State=4;break;}
else return -1;
}
case 'd':
case 'D':
{
if(State==4) {State=5;break;}
else return -1;
}
case 'a':
case 'A':
{
if(State==5) {State=6;break;}
if(State==7) {State=8;break;}
else return -1;
}
case 't':
case 'T':
{
if(State==6) {State=7;break;}
else return -1;
}
case ' ':
case '\t':
// case '\n':
{
if(State==8){TOKEN.TokenID=2;TOKEN.TokenName="ORG_DATA";return 0;}
else return -1;
}
default:return -1;
}
ch = getc(SourceFileName);
if ( ch == '\n' )
No_TxtLine++;
}
break;
}
case 6: //當(dāng)前棧頂符號為<N_PRO>
case 8: //當(dāng)前棧頂符號為<N_VAR>
case 13: //當(dāng)前棧頂符號為<N_SEG>
case 14: //當(dāng)前棧頂符號為<N_START SEGID>
case 18: //當(dāng)前棧頂符號為<N_SUBSEGID>
{ //以上五種情況,應(yīng)該掃描IDNAME單詞
i = 0;
char ch = ReadOneChar( SourceFileName );
if ( ch == '\n' )
No_TxtLine++;
ret[i++] = ch;
while ( 1 )
{
if ( ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) && (State==0||State==1) )
{
State = 1;
ch = getc( SourceFileName );
if ( ch == '\n' )
No_TxtLine++;
ret[i++] = ch;
continue;
}
if ( (ch>='0'&&ch<='9') && State == 1 )
{
State = 1;
ch = getc( SourceFileName );
if ( ch == '\n' )
No_TxtLine++;
ret[i++] = ch;
continue;
}
if ( State == 1 )
if ( ungetc(ch, SourceFileName) )
{
if ( ch == '\n' )
No_TxtLine--;
ret[--i]='\0';
TOKEN.TokenID=3;
TOKEN.TokenName=ret;
return 0;
}
else
return -1;
else
return -1;
}
break;
}
case 7: //當(dāng)前棧頂符號為<N_VARS>'
{ //應(yīng)該掃描DATA或IDNAME單詞
i = 0;
char ch=ReadOneChar(SourceFileName);
if ( ungetc(ch, SourceFileName) == 0 ) return -1;
while ( 1 )
{
ch = getc( SourceFileName );
if ( ch == '\n' )
No_TxtLine++;
ret[i++] = ch;
switch ( ch )
{
case 'd':
case 'D':
{
if(State==0) {State=1;break;}
if(State==1) {State=5;break;}
if(State==2) {State=5;break;}
if(State==3) {State=5;break;}
if(State==4) {State=5;break;}
if(State==5) {State=5;break;}
return -1;
}
case 'a':
case 'A':
{
if(State==1) {State=2;break;}
if(State==0) {State=5;break;}
if(State==2) {State=5;break;}
if(State==3) {State=4;break;}
if(State==4) {State=5;break;}
if(State==5) {State=5;break;}
return -1;
}
case 't':
case 'T':
{
if(State==2) {State=3;break;}
if(State==0) {State=5;break;}
if(State==1) {State=5;break;}
if(State==3) {State=5;break;}
if(State==4) {State=5;break;}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -