Files
Work/as68hc11/Scan.cpp
2024-08-07 09:12:07 -04:00

262 lines
6.3 KiB
C++

#include <as68hc11/scan.hpp>
#include <as68hc11/symbol.hpp>
#include <as68hc11/table.hpp>
#include <common/pointer.hpp>
#include <common/openfile.hpp>
#include <common/filemap.hpp>
#include <common/pview.hpp>
Scan::Scan(PureViewOfFile &inFile,PureViewOfFile &outFile,Table &symbolTable,Block<String> &includePath)
: Emit(inFile,outFile), mSymbolTable(symbolTable), mEmitEndText(true), mIncludePath(includePath)
{
}
Scan::Scan(PureViewOfFile &inFile,PureViewOfFile &outFile,Table &symbolTable,CodePointer &codePointer,Block<String> &includePath)
: Emit(inFile,outFile,codePointer), mSymbolTable(symbolTable), mEmitEndText(false), mIncludePath(includePath)
{
}
Scan::~Scan(void)
{
}
bool Scan::analyze(void)
{
readch();
while((int)mChar!=-1&&mChar!=0x001A)
{
skipSeparators();
if(0xFFFF==mChar||0x001A==mChar)break;
if(isdigit(mChar))scanNumeral();
else if('\r'==mChar)scanNewLine();
else if(','==mChar){emit(comma1);readch();}
else if('['==mChar){emit(leftbracket1);readch();}
else if(']'==mChar){emit(rightbracket1);readch();}
else if('*'==mChar){emit(asterisk1);readch();}
else if('/'==mChar){emit(divide1);readch();}
else if('+'==mChar){emit(plus1);readch();}
else if('-'==mChar){emit(minus1);readch();}
else if('('==mChar){emit(leftparen1);readch();}
else if(')'==mChar){emit(rightparen1);readch();}
else if('\''==mChar)scanCharacter();
else if(';'==mChar)scanComment();
else if(isalpha(mChar)){if(!scanWord())return false;}
else scanUnknown();
}
if(mEmitEndText)emit(endtext1);
return true;
}
void Scan::scanNewLine(void)
{
emit(newline1);
readch();
if(mChar=='\n')readch();
}
void Scan::skipSeparators(void)
{
while(mChar==SpaceChar||mChar==TabChar)readch();
}
void Scan::scanComment(void)
{
readch();
while(mChar!='\r'&&mChar!=0xFFFF)readch();
}
void Scan::scanCharacter(void)
{
int character;
readch();
character=mChar;
readch();
*((char*)mWordString)=0;
mWordString+=character;
while(0xFFFF!=mChar&&'\''!=mChar&&0x0D!=mChar)
{
mWordString+=mChar;
readch();
}
readch();
emit(apostrophe1);
emit(literal1);
emit(mWordString);
emit(apostrophe1);
}
bool Scan::scanNumeral(void)
{
char chBuffer[128];
char chIndex(0);
int value(0);
while(0xFFFF!=mChar&&(isdigit(mChar)||isInHex(mChar)))
{
if(chIndex>=sizeof(chBuffer))return FALSE;
chBuffer[chIndex++]=mChar;
readch();
}
if('h'==mChar||'H'==mChar){hex(chBuffer,chIndex);readch();}
else if('b'==mChar||'B'==mChar){binary(chBuffer,chIndex);readch();}
else if(chIndex>0&&('b'==chBuffer[chIndex-1]||'B'==chBuffer[chIndex-1]))binary(chBuffer,chIndex-1);
else decimal(chBuffer,chIndex);
return TRUE;
}
void Scan::hex(char chBuffer[],int chIndex)
{
int value(0);
int multiplier(1);
for(--chIndex;chIndex>=0;chIndex--)
{
switch(chBuffer[chIndex])
{
case '0' : break;
case '1' : {value+=multiplier;break;}
case '2' : {value+=multiplier*2;break;}
case '3' : {value+=multiplier*3;break;}
case '4' : {value+=multiplier*4;break;}
case '5' : {value+=multiplier*5;break;}
case '6' : {value+=multiplier*6;break;}
case '7' : {value+=multiplier*7;break;}
case '8' : {value+=multiplier*8;break;}
case '9' : {value+=multiplier*9;break;}
case 'a' :
case 'A' : {value+=multiplier*10;break;}
case 'b' :
case 'B' : {value+=multiplier*11;break;}
case 'c' :
case 'C' : {value+=multiplier*12;break;}
case 'd' :
case 'D' : {value+=multiplier*13;break;}
case 'e' :
case 'E' : {value+=multiplier*14;break;}
case 'f' :
case 'F' : {value+=multiplier*15;break;}
default : {emit(unknown1);return;}
}
multiplier*=16;
}
emit(numeral1,value);
}
void Scan::binary(char chBuffer[],int chIndex)
{
int value(0);
int multiplier(1);
for(--chIndex;chIndex>=0;chIndex--)
{
switch(chBuffer[chIndex])
{
case '0' : break;
case '1' : {value+=multiplier;break;}
default : {emit(unknown1);return;}
}
multiplier*=2;
}
emit(numeral1,value);
}
void Scan::decimal(char chBuffer[],int chIndex)
{
int value(0);
int multiplier(1);
for(--chIndex;chIndex>=0;chIndex--)
{
switch(chBuffer[chIndex])
{
case '0' : break;
case '1' : {value+=multiplier;break;}
case '2' : {value+=multiplier*2;break;}
case '3' : {value+=multiplier*3;break;}
case '4' : {value+=multiplier*4;break;}
case '5' : {value+=multiplier*5;break;}
case '6' : {value+=multiplier*6;break;}
case '7' : {value+=multiplier*7;break;}
case '8' : {value+=multiplier*8;break;}
case '9' : {value+=multiplier*9;break;}
default : {emit(unknown1);return;}
}
multiplier*=10;
}
emit(numeral1,value);
}
bool Scan::scanWord(void)
{
SmartPointer<Symbol> symbol;
*((char*)mWordString)=0;
while(0x0D!=mChar&&!isKeySymbol()&&0xFFFF!=mChar&&SpaceChar!=mChar&&TabChar!=mChar)
{
mWordString+=mChar;
readch();
}
if(mWordString.isNull())return true;
if(mSymbolTable.locateSymbol(mWordString,symbol))
{
if(Symbol::DirectiveSymbol==symbol->symbolType())emit(symbol->identifier());
else emit(name1,int((Symbol*)symbol));
}
else if(':'==mChar){emit(label1);emit(mWordString);readch();}
else if(mWordString=="INCLUDE" || mWordString=="include")
{
if(!scanInclude())return false;
}
else {emit(literal1);emit(mWordString);}
return true;
}
bool Scan::scanInclude()
{
FileHandle inFile;
String wordString;
String pathFileName;
bool returnCode;
*((char*)wordString)=0;
readch();
while(0x0D!=mChar&&SpaceChar!=mChar)
{
wordString+=mChar;
readch();
}
if(wordString.isNull())return true;
if(!getIncludeFile(wordString,pathFileName))
{
mLastMessage=String("Cannot locate include file '")+wordString+String("'.");
return false;
}
if(!inFile.open(pathFileName,FileHandle::Read,FileHandle::ShareRead))
{
mLastMessage=String("Cannot open include file '")+pathFileName+String("'.");
return false;
}
FileMap inMap(inFile);
PureViewOfFile inView(inMap);
Scan scan(inView,outputView(),mSymbolTable,codePointer(),mIncludePath);
returnCode=scan.analyze();
if(returnCode)codePointer()=scan.codePointer();
return returnCode;
}
bool Scan::getIncludeFile(const String &fileName,String &pathFileName)
{
FileHandle openFile;
for(int index=0;index<mIncludePath.size();index++)
{
pathFileName=mIncludePath[index]+String("\\")+fileName;
if(openFile.open(pathFileName,FileHandle::Read,FileHandle::ShareRead))
{
openFile.close();
return true;
}
}
return false;
}