📄 compiler.cpp
字号:
// Compiler.cpp: implementation of the CCompiler class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DFYSimulator.h"
#include "Compiler.h"
#include "MainFrm.h"
#include "OutputWindow.h"
#include"fstream"
using namespace std;
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCompiler::CCompiler()
{
m_uErrorNum=0;
m_uCodeSegSize=0;
m_uDataSegSize=0;
m_wDFYexeFileSize=0;
m_wPdfRecordNum=0;
m_uCodeLineNum=0;
_instructions[0]="LD";
_instructions[1]="ST";
_instructions[2]="LEA";
_instructions[3]="ADD";
_instructions[4]="SUB";
_instructions[5]="SLA";
_instructions[6]="SRA";
_instructions[7]="AND";
_instructions[8]="OR";
_instructions[9]="EOR";
_instructions[10]="NOT";
_instructions[11]="SLL";
_instructions[12]="SRL";
_instructions[13]="CPA";
_instructions[14]="CPL";
_instructions[15]="JMP";
_instructions[16]="JPZ";
_instructions[17]="JMI";
_instructions[18]="JNZ";
_instructions[19]="JZE";
_instructions[20]="PUSH";
_instructions[21]="POP";
_instructions[22]="CALL";
_instructions[23]="RET";
_instructions[24]="INPORT";
_instructions[25]="OUTPORT";
_instructions[26]="EXIT";
_instructions[27]="INTR";
_instructions[28]="IRET";
_instructions[29]="STI";
_instructions[30]="CLI";
_registers[0]="GR0";
_registers[1]="GR1";
_registers[2]="GR2";
_registers[3]="GR3";
_registers[4]="GR4";
_flagsMap=NULL;
_varInfo=NULL;
}
CCompiler::~CCompiler()
{
FlagsMap* p=_flagsMap;
FlagsMap* q=NULL;
if(p!=NULL)
{
q=p->next;
delete p;
p=q;
}
VariableInfo* pp=_varInfo;
VariableInfo* qq=NULL;
if(pp!=NULL)
{
qq=pp->next;
delete pp;
pp=qq;
}
}
BOOL CCompiler::Compile(char* asmSource,char* pdfFile,char* DFYexeFile)
{
CMainFrame* pMainFrame=(CMainFrame*)AfxGetMainWnd();
COutputWindow* pOutputWindow=pMainFrame->GetOutputWindow();
pOutputWindow->ResetContent();
ReportState("Assembling...");
if(FirstScan(asmSource,pdfFile))
{
return SecondScan(asmSource,DFYexeFile);
}
else
return FALSE;
}
void CCompiler::ReportState(CString strState)
{
CMainFrame* pMainFrame=(CMainFrame*)AfxGetMainWnd();
COutputWindow* pOutputWindow=pMainFrame->GetOutputWindow();
if(pOutputWindow)
pOutputWindow->ShowState(strState);
}
BOOL CCompiler::IsLegal(char* str)
{
if(!str)return FALSE;
int n=strlen(str);
if(n==0)return FALSE;
for(int i=0;i<n;i++)
{
if(str[i]=='_')
continue;
if(str[i]>='0'&&str[i]<='9')
continue;
if(str[i]>='a'&&str[i]<='z')
continue;
if(str[i]>='A'&&str[i]<='Z')
continue;
return FALSE;
}
return TRUE;
}
BOOL CCompiler::IsNumber(char* strWord)
{
if(!strWord)return FALSE;
int n=strlen(strWord);
if(n==0)return FALSE;
for(int i=0;i<n;i++)
{
if(strWord[i]>='0'&&strWord[i]<='9')
continue;
return FALSE;
}
return TRUE;
}
BOOL CCompiler::IsInstruction(char *strWord)
{
if(!strWord)return FALSE;
int n=strlen(strWord);
if(n==0)return FALSE;
for(int i=0;i<35;i++)
{
if(strcmp(strWord,_instructions[i])==0)
return i+1;//return the instruction code
}
return FALSE;
}
BOOL CCompiler::IsRegister(char *strWord)
{
if(!strWord)return FALSE;
int n=strlen(strWord);
if(n==0)return FALSE;
for(int i=0;i<5;i++)
{
if(strcmp(strWord,_registers[i])==0)
return i+1;//reture the number of the register ,but not
//register code
}
return FALSE;
}
BOOL CCompiler::FirstScan(char *asmSourceName, char *pdfFileName)
{
BOOL bStart=FALSE;
BOOL bData= FALSE;
char* word=new char[20];
char* word2=new char[20];
UNSHORT uAddr=0;//keep the current instruction address
UNSHORT uLine=0;//the line number
m_wPdfRecordNum=0;
CString str;
ifstream asmFile;
char* pBuf=new char[200];
ReportState("first scaning...");
str.Format("scanling file:%s...",asmSourceName);
ReportState(str);
asmFile.open(asmSourceName);
if(!asmFile)
{
str.Format("fatal error:can't open the file %s or the file is not exist",asmSourceName);
m_uErrorNum+=1;
ReportState(str);
delete[] word;
delete[]word2;
delete[] pBuf;
return FALSE;
}//end:!admFile
while(!asmFile.eof())
{
uLine+=1;//line number +1
str.Format("anylize line:%d...",uLine);
ReportState(str);
asmFile.getline(pBuf,200);
word=GetWordFromLine(0,pBuf);
if(IsEmpty(word))continue;//if the line is empty
if(IsComment(word))continue;//if the line is comment
if(!IsLegal(word))//if the word is not legal
{
str.Format("fatal error:Line %d \'%s\'is illegal",uLine,word);
m_uErrorNum+=1;
ReportState(str);
continue;
}//end:the word is not legal
else//is the word is a legal identifier
{
if(!bStart)//if haven't find the 'START'
{
if(strcmp(word,"START")==0)
{
bStart=TRUE;
continue;
}
else
{
m_uErrorNum+=1;
ReportState("fatal error:cant't find 'START' ");
delete[] word;
delete[]word2;
delete[] pBuf;
return FALSE;
}
}
else//have been find the 'START'
{
if(strcmp(word,"END")==0)//if go to the end
{
uAddr-=1;
break;
}
else if(strcmp(word,"DATA")==0)
{
bData=TRUE;
continue;
}
if(!bData)//haven't find the 'DATA'
{
if(!IsInstruction(word))//is flag
{
AddFlag(word,uAddr);
}
uAddr+=2;
m_wDFYexeFileSize+=2;
m_uCodeSegSize+=2;
}
else//have find the 'DATA',,into the data segment
{
word2=GetWordFromLine(1,pBuf);
if(strcmp(word2,"DC")==0)
{
word2=GetWordFromLine(2,pBuf);
if(IsNumber(word2))
{
AddVariable(word,uAddr,atoi(word2));
uAddr+=1;
m_uDataSegSize+=1;
m_wDFYexeFileSize+=1;
m_wPdfRecordNum+=1;
}
else
{
str.Format("fatal error: Line %d,the variable value haven't initialized",uLine);
m_uErrorNum+=1;
ReportState(str);
continue;
}//end:IsNumber
}//end:strcmp
else
{
str.Format("fatal error: Line %d,the second word should be \'DC\'",uLine);
m_uErrorNum+=1;
ReportState(str);
continue;
}
}//end:have find the data
continue;
}//end:have find the 'START'
}//legal
}//while
m_uCodeLineNum=uLine;
asmFile.close();
if(!bStart)
{
ReportState("fatal error: can't find \'START\'");
return FALSE;
}
str.Format("generate file: %s",pdfFileName);
ReportState(str);
ofstream pdffile;
pdffile.open(pdfFileName);
if(!pdffile)
{
str.Format("fatal error:can't create the file %s or the file is not exist",pdfFileName);
m_uErrorNum+=1;
ReportState(str);
}
PdfFileHeader head;
head.wFileVersion=1;
head.wRecordNumber=m_wPdfRecordNum;
pdffile<<head.wFileVersion<<' '<<head.wRecordNumber<<' ';
VariableInfo *p=_varInfo;
while(p!=NULL)
{
pdffile<<' '<<p->strVarName<<' '<<p->uVarAddr<<' '<<p->wValue<<' ';
p=p->next;
}
pdffile.close();
delete[] word;
delete[]word2;
delete[] pBuf;
if(m_uErrorNum==0)
{
ReportState("first scan succeed");
return TRUE;
}
else
{
ReportState("first scan failed");
str.Format("%d errors",m_uErrorNum);
ReportState(str);
return FALSE;
}
}
char* CCompiler::GetWordFromLine(int nIndex, char *strSrc)
{
char c;
char* str;//used to reserve the return value
int wordSize=0;
int index=0;
int pos=0;//record the current char pos
int lineSize=strlen(strSrc);
if(lineSize==0) return NULL;
//filter the backspace first
c=strSrc[pos];
while(c==' ')
{
pos++;
if(pos)break;
c=strSrc[pos];
}
if(pos>=lineSize)return NULL;
//filter the other word and backspace
if(nIndex<0)nIndex=0;
while(index<nIndex)
{
while(c!=' ')//filter the next word
{
pos++;
if(pos>=lineSize)break;
c=strSrc[pos];
}
while(c==' ')//filter the next backspace
{
pos++;
if(pos>=lineSize)break;
c=strSrc[pos];
}
index+=1;
}
if(pos>=lineSize)return NULL;
//into the word
while(c!=' ')
{
wordSize++;
if(pos+wordSize>=lineSize)break;
c=strSrc[pos+wordSize];
}
str=new char[wordSize+1];
for(int i=0;i<wordSize;i++)
str[i]=strSrc[pos+i];
str[wordSize]='\0';
return str;
}
BOOL CCompiler::FindFlag(char *flag, UNSHORT &uAddr)//the flag should not be NULL
{
if(!flag)return FALSE;
if(strlen(flag)==0)return FALSE;
FlagsMap* p=_flagsMap;
if(!p)return FALSE;
while(p!=NULL)
{
if(strcmp(p->strFlagName,flag)==0)
{
uAddr=p->uFlagAddr;
return TRUE;
}
p=p->next;
}
return FALSE;
}
BOOL CCompiler::FindVariable(char *var, UNSHORT &uAddr,WORD& wVar)//the flag should not be NULL
{
if(!var)return FALSE;
if(strlen(var)==0)return FALSE;
VariableInfo* p=_varInfo;
if(!p)return FALSE;
while(p!=NULL)
{
if(strcmp(p->strVarName,var)==0)
{
uAddr=p->uVarAddr;
wVar=p->wValue;
return TRUE;
}
p=p->next;
}
return FALSE;
}
BOOL CCompiler::IsEmpty(char *strWord)
{
if(!strWord)return TRUE;
if(strlen(strWord)==0)
return TRUE;
return FALSE;
}
BOOL CCompiler::IsComment(char *strWord)
{
if(!strWord)return FALSE;
if(strlen(strWord)==0)
return FALSE;
if(strWord[0]==';')
return TRUE;
return FALSE;
}
void CCompiler::AddFlag(char *flag, UNSHORT uAddr)
{
FlagsMap* p=_flagsMap;
FlagsMap* newNode=NULL;
FlagsMap* q=NULL;
if(p==NULL)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -