Rewrote core algebraic parser

Added trivial float support
Added local labels and vastly improved label support
Fixed some crash bugs
This commit is contained in:
David Anderson 2004-08-11 08:14:54 +00:00
parent 74d278d1c6
commit 7acc70ee62
15 changed files with 444 additions and 185 deletions

View File

@ -308,7 +308,7 @@ bool Compiler::Compile()
char c = (*dmi)->fill;
for (int iter=0; iter<=(*dmi)->e.GetNumber(); iter++)
{
fwrite((void*)&c, sizeof(char), 1, fp);
fwrite((void*)&c, sizeof(int32_t), 1, fp);
}
}
}
@ -334,6 +334,7 @@ bool Compiler::Parse()
std::ifstream fp(filename.c_str());
char buffer[256] = {0};
std::stack<int> DefStack;
std::stack<std::string> LabelStack;
curLine = 0;
AsmSection sec = Asm_None;
lastCip = 0-cellsize;
@ -347,7 +348,7 @@ bool Compiler::Parse()
while (!fp.eof())
{
fp.getline(buffer, 255);
curLine++;
curLine+=1;
/* Check for preprocessor directives */
if (buffer[0] == '#')
@ -440,6 +441,14 @@ bool Compiler::Parse()
sec = Asm_Invalid;
CError->ErrorMsg(Err_Invalid_Section, buffer);
}
/* Update the labels */
CLabels->CompleteQueue(true);
while (!LabelStack.empty())
{
CLabels->EraseLabel(LabelStack.top());
CSymbols->EraseSymbol(LabelStack.top());
LabelStack.pop();
}
} else {
/* Do pre-processing */
CMacros->SearchAndReplace(line);
@ -501,7 +510,7 @@ bool Compiler::Parse()
t.Evaluate();
e.Set(amt);
e.Evaluate();
DAT->Add(symbol, e, false, (char)t.GetNumber());
DAT->Add(symbol, e, false, t.GetNumber());
} else {
e.Set(data);
e.Evaluate();
@ -570,6 +579,7 @@ bool Compiler::Parse()
Asm *ASM = new Asm;
ASM->cip = lastCip + cellsize;
ASM->op = OpCodes["proc"];
ASM->line = curLine;
lastCip += cellsize;
/* Add symbol */
S = CSymbols->AddSymbol(params, Sym_Proc, CurLine());
@ -578,7 +588,16 @@ bool Compiler::Parse()
/* Add to PROC list */
PROC->AddProc(S, ASM);
} else if (code.compare("ENDP") == 0) {
/* This is, in theory, not needed */
/* This is, in theory, not needed
* Nonetheless, we check labels here
*/
CLabels->CompleteQueue(true);
while (!LabelStack.empty())
{
CLabels->EraseLabel(LabelStack.top());
CSymbols->EraseSymbol(LabelStack.top());
LabelStack.pop();
}
} else if (params.size() < 1 && code[code.size()-1] == ':') {
/* Label! */
/* Check if symbol is valid */
@ -604,6 +623,10 @@ bool Compiler::Parse()
}
continue;
}
if (code[0] == '_')
{
LabelStack.push(code);
}
S = CSymbols->AddSymbol(code, Sym_Label, CurLine());
CLabels->AddLabel(S, lastCip+cellsize);
} else {
@ -623,6 +646,7 @@ bool Compiler::Parse()
ASM = new Asm;
ASM->cip = lastCip+cellsize;
ASM->op = OP_LINE;
ASM->line = curLine;
ASM->params.push_back(curLine);
ASM->params.push_back(0);
CodeList.push_back(ASM);
@ -647,6 +671,7 @@ bool Compiler::Parse()
ASM->cip = (lastCip+cellsize);
ASM->op = op;
ASM->line = curLine;
lastCip += cellsize;
switch (op)
@ -1801,7 +1826,7 @@ void Compiler::ProcessDirective(std::string &text)
SymbolList::Symbol *S;
if ((S = CSymbols->FindSymbol(symbol)) != NULL)
{
CError->ErrorMsg(Err_SymbolRedef, curLine, S->sym.c_str(), S->line);
CError->ErrorMsg(Err_SymbolRedef, S->sym.c_str(), S->line);
}
/* Store the argstring, which is the rest of the data */
std::string argstring;
@ -1827,8 +1852,22 @@ void Compiler::ProcessDirective(std::string &text)
CSymbols->AddSymbol(symbol, Sym_Macro, curLine);
//TODO: ClearList(ArgList);
}
} else if (!directive.compare("stacksize")) {
} else if (!directive.compare("pragma")) {
std::string pragma;
std::string entry;
StringBreak(definition, pragma, entry);
if (pragma.compare("stacksize") == 0)
{
int stksz = atoi(entry.c_str());
if (stksz < 100)
{
CError->ErrorMsg(Err_Invalid_Pragma);
} else {
stacksize = stksz;
}
} else {
CError->ErrorMsg(Err_Invalid_Pragma);
}
} else if (!directive.compare("define")) {
std::string symbol;
std::string def;
@ -1859,8 +1898,6 @@ int Compiler::Eval(std::string &str, SymbolType sym)
int i = 0;
rpn *r = new rpn;
int pos = 0;
int val = 0;
CExpr e;
Stack.push(r);
@ -1890,18 +1927,10 @@ int Compiler::Eval(std::string &str, SymbolType sym)
{
bpstr.assign(str.substr(pos, i-pos));
Strip(bpstr);
CExpr e(CError);
e.Set(bpstr);
val = 0;
if (!e.Analyze() && IsValidSymbol(bpstr))
{
val = DerefSymbol(bpstr, sym);
} else if (e.Analyze() && (e.Evaluate() == Val_Number)) {
val = e.GetNumber();
} else {
CError->ErrorMsg(Err_Invalid_Symbol);
return 0;
}
r->vals.push_back(val);
e.Evaluate(sym);
r->vals.push_back(e);
}
r->ops.push_back(str[i]);
if (str[i] == '>' || str[i] == '<')
@ -1917,18 +1946,10 @@ int Compiler::Eval(std::string &str, SymbolType sym)
{
bpstr.assign(str.substr(pos, i-pos));
Strip(bpstr);
CExpr e(CError);
e.Set(bpstr);
val = 0;
if (!e.Analyze() && IsValidSymbol(bpstr))
{
val = DerefSymbol(bpstr, sym);
} else if (e.Analyze() && (e.Evaluate() == Val_Number)) {
val = e.GetNumber();
} else {
CError->ErrorMsg(Err_Invalid_Symbol);
return 0;
}
r->vals.push_back(val);
e.Evaluate(sym);
r->vals.push_back(e);
}
r = new rpn;
Stack.push(r);
@ -1939,20 +1960,13 @@ int Compiler::Eval(std::string &str, SymbolType sym)
{
bpstr.assign(str.substr(pos, i-pos));
Strip(bpstr);
CExpr e(CError);
e.Set(bpstr);
val = 0;
if (!e.Analyze() && IsValidSymbol(bpstr))
{
val = DerefSymbol(bpstr, sym);
} else if (e.Analyze() && (e.Evaluate() == Val_Number)) {
val = e.GetNumber();
} else {
CError->ErrorMsg(Err_Invalid_Symbol);
return 0;
}
r->vals.push_back(val);
e.Evaluate(sym);
r->vals.push_back(e);
}
val = EvalRpn(r, sym);
CExpr t;
t = EvalRpn(r, sym);
delete r;
if (Stack.size() < 2)
{
@ -1967,7 +1981,7 @@ int Compiler::Eval(std::string &str, SymbolType sym)
}
Stack.pop();
r = Stack.top();
r->vals.push_back(val);
r->vals.push_back(t);
pos = i + 1;
} else if (i == (int)(str.size() - 1)) {
if (pos < i)
@ -1979,18 +1993,10 @@ int Compiler::Eval(std::string &str, SymbolType sym)
if (pos < i || pos == i)
{
Strip(bpstr);
CExpr e(CError);
e.Set(bpstr);
val = 0;
if (!e.Analyze() && IsValidSymbol(bpstr))
{
val = DerefSymbol(bpstr, sym);
} else if (e.Analyze() && (e.Evaluate() == Val_Number)) {
val = e.GetNumber();
} else {
CError->ErrorMsg(Err_Invalid_Symbol);
return 0;
}
r->vals.push_back(val);
e.Evaluate(sym);
r->vals.push_back(e);
}
}
}
@ -2009,19 +2015,18 @@ int Compiler::Eval(std::string &str, SymbolType sym)
rpn *r2 = Stack.top();
Stack.pop();
val = EvalRpn(r, sym);
CExpr final;
final = EvalRpn(r, sym);
return val;
return final.GetNumber();
}
int Compiler::EvalRpn(rpn *r, SymbolType sym)
CExpr Compiler::EvalRpn(rpn *r, SymbolType sym)
{
int i = 0, j = 0;
char c = 0;
int lval = 0;
int rval = 0;
int nval = 0;
std::vector<int>::iterator Q;
CExpr er, el;
std::vector<CExpr>::iterator Q;
std::vector<char>::iterator R;
while (r->ops.size())
@ -2035,77 +2040,17 @@ int Compiler::EvalRpn(rpn *r, SymbolType sym)
{
if ((int)r->vals.size() <= j)
assert(0);// Can't have more ops than values
lval = r->vals[j];
el = r->vals[j];
if (i != Token_Not)
{
if ((int)r->vals.size() <= j+1)
{
assert(0);
}
rval = r->vals[j+1];
}
switch (i)
{
case Token_Xor:
{
nval = lval ^ rval;
break;
}
case Token_Shr:
{
nval = lval >> rval;
break;
}
case Token_Sub:
{
nval = lval - rval;
break;
}
case Token_Mod:
{
nval = lval % rval;
break;
}
case Token_Mul:
{
nval = lval * rval;
break;
}
case Token_Div:
{
nval = (int)(lval / rval);
break;
}
case Token_Shl:
{
nval = lval << rval;
break;
}
case Token_And:
{
nval = lval & rval;
break;
}
case Token_Or:
{
nval = lval | rval;
break;
}
case Token_Add:
{
nval = lval + rval;
break;
}
case Token_Not:
{
nval = ~lval;
break;
}
default:
{
nval = 0;
break;
}
er = r->vals[j+1];
el.Oper((OpToken)i, er);
} else {
el.Not();
}
R = r->ops.begin();
Q = r->vals.begin();
@ -2114,13 +2059,13 @@ int Compiler::EvalRpn(rpn *r, SymbolType sym)
R += j;
Q += j;
r->ops.erase(R);
r->vals[j+1] = nval;
r->vals[j+1] = el;
r->vals.erase(Q);
j--;
} else {
R += j;
r->ops.erase(R);
r->vals[j] = nval;
r->vals[j] = el;
}
}
}
@ -2232,4 +2177,14 @@ int Compiler::DerefSymbol(std::string &str, SymbolType sym)
}
return val;
}
}
bool Compiler::IsSymbol(std::string &str)
{
SymbolList::Symbol *S = 0;
if ( (S = CSymbols->FindSymbol(str)) == NULL )
return false;
return true;
}

View File

@ -40,30 +40,12 @@
lastCip+=cellsize; \
}
typedef enum
{
Token_None,
Token_Or,
Token_Xor,
Token_And,
Token_Shr,
Token_Shl,
Token_Mod,
Token_Div,
Token_Mul,
Token_Sub,
Token_Add,
Token_Not,
/* End */
Tokens_Total,
} OpToken;
class rpn
{
public:
//TODO: use linked lists, but not std::list
std::vector<char> ops;
std::vector<int> vals;
std::vector<CExpr> vals;
};
class Compiler
@ -91,9 +73,10 @@ public: //private
void Init();
void InitOpcodes();
int Eval(std::string &str, SymbolType sym = Sym_None);
int EvalRpn(rpn *r, SymbolType sym);
CExpr EvalRpn(rpn *r, SymbolType sym);
OpToken OperToken(char c);
char OperChar(OpToken c);
bool IsSymbol(std::string &str);
private:
std::vector<Asm *> CodeList;
std::map<std::string,int> OpCodes;
@ -115,4 +98,4 @@ private:
Asm *curAsm;
};
#endif //_INCLUDE_AMXCOMPILER_H
#endif //_INCLUDE_AMXCOMPILER_H

View File

@ -47,7 +47,7 @@ DataMngr::Datum::Datum()
fill = 0;
}
void DataMngr::Add(std::string &s, CExpr &expr, bool db, char fill)
void DataMngr::Add(std::string &s, CExpr &expr, bool db, int fill)
{
DataMngr::Datum *D = new DataMngr::Datum();
@ -63,7 +63,7 @@ void DataMngr::Add(std::string &s, CExpr &expr, bool db, char fill)
size = ((D->e.GetType() == Val_Number) ?
cellsize : D->e.Size() * cellsize);
} else {
size = D->e.GetNumber();
size = (D->e.GetNumber() * cellsize);
}
if (List.size() == 0)
@ -77,7 +77,7 @@ void DataMngr::Add(std::string &s, CExpr &expr, bool db, char fill)
((p->e.GetType() == Val_Number) ?
cellsize : p->e.Size() * cellsize);
} else {
D->offset = p->offset + p->e.GetNumber();
D->offset = p->offset + (p->e.GetNumber() * cellsize);
}
}

View File

@ -34,13 +34,13 @@ public:
CExpr e;
bool db;
int offset;
char fill;
int fill;
};
public:
~DataMngr();
DataMngr() { cellsize = 4; lastOffset = 0; cursize = 0; }
DataMngr(int cell) { lastOffset = 0; cellsize = cell; cursize = 0; }
void Add(std::string &s, CExpr &expr, bool db = false, char fill = 0);
void Add(std::string &s, CExpr &expr, bool db = false, int fill = 0);
DataMngr::Datum *FindData(std::string &sym);
void GetData(std::vector<DataMngr::Datum *> &dList);
int GetOffset(std::string &sym);

View File

@ -26,6 +26,7 @@ ErrorMngr::ErrorMngr()
{
printf("Not instantiated with a compiler.");
Cmp = NULL;
line = -1;
assert(Cmp);
}
@ -56,6 +57,7 @@ ErrorMngr::ErrorMngr(void *c)
Totals[1] = 0;
Totals[2] = 0;
Totals[3] = 0;
line = -1;
HighestError = Err_None;
}
@ -95,6 +97,9 @@ void ErrorMngr::DefineErrors()
List.at(Err_Unknown_Define) = "Unknown define referenced";
List.at(Err_Misplaced_Directive) = "Misplaced preprocessor directive";
List.at(Err_Bad_Label) = "Label referenced without being created";
List.at(Err_Bad_Not) = "Wrong type argument to bit-complement";
List.at(Err_Invalid_Operator) = "Operator used on bad type";
List.at(Err_Invalid_Pragma) = "Invalid pragma";
List.at(Err_FileNone) = "No file specified";
List.at(Err_FileOpen) = "Could not open file \"%s\"";
@ -131,13 +136,23 @@ void ErrorMngr::ErrorMsg(ErrorCode error, ...)
if (type == -1)
return;
int curLine = 0;
if (line == -1)
{
curLine = ((Compiler *)Cmp)->CurLine();
} else {
curLine = line;
line = -1;
}
va_list argptr;
va_start(argptr, error);
if (((Compiler *)Cmp)->CurLine() == -1)
sprintf(errbuf, "%s(%d): %s\n", ErrorSwi[type], error, GetError(error));
else
sprintf(errbuf, "%s(%d) on line %d: %s\n", ErrorSwi[type], error, ((Compiler *)Cmp)->CurLine(), GetError(error));
sprintf(errbuf, "%s(%d) on line %d: %s\n", ErrorSwi[type], error, curLine, GetError(error));
vprintf(errbuf, argptr);
va_end(argptr);
@ -163,4 +178,19 @@ const char *ErrorMngr::GetError(ErrorCode id)
if (id < notices_start || id > fatals_end)
return NULL;
return List.at(id);
}
int ErrorMngr::DerefSymbol(std::string &str, int sym)
{
return ((Compiler *)Cmp)->DerefSymbol(str, (SymbolType)sym);
}
bool ErrorMngr::IsSymbol(std::string &str)
{
return ((Compiler *)Cmp)->IsSymbol(str);
}
void ErrorMngr::SetLine(int ln)
{
line = ln;
}

View File

@ -60,6 +60,9 @@ typedef enum
Err_Unknown_Define,
Err_Misplaced_Directive,
Err_Bad_Label,
Err_Bad_Not,
Err_Invalid_Operator,
Err_Invalid_Pragma,
errors_end,
fatals_start,
@ -87,6 +90,7 @@ private:
ErrorType HighestError;
void *Cmp;
int Totals[4];
int line;
public:
ErrorMngr();
ErrorMngr(void *c);
@ -96,6 +100,9 @@ public:
void PrintReport();
int CurLine();
int CurCip();
void SetLine(int ln);
int DerefSymbol(std::string &str, int sym = 0);
bool IsSymbol(std::string &str);
};
#endif //_INCLUDE_AMX_ERROR

View File

@ -91,7 +91,7 @@ void LabelMngr::QueueLabel(std::string &sym, Asm *ASM)
LQ[d].push(ASM);
}
void LabelMngr::CompleteQueue()
void LabelMngr::CompleteQueue(bool isLocal)
{
std::map<std::string,std::stack<Asm *> >::iterator i;
std::stack<Asm *> *stk = 0;
@ -106,13 +106,22 @@ void LabelMngr::CompleteQueue()
stk = &((*i).second);
if (p == NULL || p->cip == LabelMngr::ncip)
{
CError->ErrorMsg(Err_Bad_Label);
}
while (!stk->empty())
{
ASM = stk->top();
ASM->params[0] = p->cip;
stk->pop();
if ((!isLocal || (isLocal && search[0]=='_')) && CError)
{
while (!stk->empty())
{
CError->SetLine(stk->top()->line);
CError->ErrorMsg(Err_Bad_Lbel);
stk->pop();
}
}
} else {
while (!stk->empty())
{
ASM = stk->top();
ASM->params[0] = p->cip;
stk->pop();
}
}
}
@ -129,4 +138,20 @@ int LabelMngr::GetCip(std::string &sym)
return ncip;
return p->cip;
}
bool LabelMngr::EraseLabel(std::string &sym)
{
std::vector<LabelMngr::Label *>::iterator i;
for (i=List.begin(); i!=List.end(); i++)
{
if ( (*i)->sym->IsEqual(sym) )
{
List.erase(i);
return true;
}
}
return false;
}

View File

@ -43,7 +43,8 @@ public:
void Clear();
bool SetCip(std::string &sym, int cip);
void QueueLabel(std::string &sym, Asm *ASM);
void CompleteQueue();
void CompleteQueue(bool isLocal = false);
bool EraseLabel(std::string &sym);
private:
std::vector<LabelMngr::Label *> List;
std::map<std::string, std::stack<Asm *> > LQ;

View File

@ -67,9 +67,9 @@ bool ProcMngr::SetPublic(std::string &sym)
void ProcMngr::GetPublics(std::vector<ProcMngr::AsmProc *> &pbList)
{
std::vector<ProcMngr::AsmProc *>::iterator i;
std::vector<ProcMngr::AsmProc *>::reverse_iterator i;
for (i=List.begin(); i!=List.end(); i++)
for (i=List.rbegin(); i!=List.rend(); i++)
{
if ((*i)->pb == true)
{

View File

@ -118,3 +118,18 @@ void SymbolList::PrintTable()
printf("Symbol \"%s\" defined on line %d\n", (*i)->sym.c_str(), (*i)->line);
}
}
bool SymbolList::EraseSymbol(std::string &sym)
{
std::vector<SymbolList::Symbol *>::iterator i;
for (i=List.begin(); i!=List.end(); i++)
{
if ( (*i)->IsEqual(sym) )
{
List.erase(i);
return true;
}
}
return false;
}

View File

@ -54,6 +54,7 @@ public:
SymbolList::Symbol* AddSymbol(std::string &sym, SymbolType type, int line);
SymbolList::Symbol* AddSymbol(const char *szSym, SymbolType type, int line);
SymbolList::Symbol* FindSymbol(std::string &sym);
bool EraseSymbol(std::string &sym);
void PrintTable();
void Clear();
private:

View File

@ -28,6 +28,8 @@ int main(int argc, char **argv)
{
Compiler Program;
getchar();
get_options(argc, argv, Program);
if (filename.size() < 1)
@ -38,8 +40,16 @@ int main(int argc, char **argv)
Program.Load(filename);
if (Program.Parse())
{
//Program.PrintCodeList();
if (Program.Compile())
printf("Done.\n");
}
/*ErrorMngr CError(&Program);
std::string f("232+4*4");
int val = Program.Eval(f);
printf("Evaluation: %d\n", val);*/
exit(0);
}

View File

@ -44,6 +44,7 @@ public:
int op;
std::vector<int> params;
int cip;
int line;
};
#include "amx.h"

View File

@ -28,6 +28,7 @@ CExpr::CExpr()
numVal = 0;
type = Val_None;
block = 0;
bDone = false;
CError = NULL;
}
@ -36,6 +37,7 @@ CExpr::CExpr(ErrorMngr *e)
numVal = 0;
type = Val_None;
block = 0;
bDone = false;
CError = e;
}
@ -45,6 +47,7 @@ CExpr::CExpr(ErrorMngr *e, std::string &text)
type = Val_None;
block = 0;
CError = e;
bDone = false;
data.assign(text);
}
@ -59,7 +62,7 @@ void CExpr::Clear()
CExpr::~CExpr()
{
if (block)
if (block && type == Val_Block)
delete [] block;
}
@ -180,13 +183,17 @@ const char *CExpr::GetString(int *d)
int CExpr::GetNumber()
{
if (type == Val_Float)
{
memcpy((void*)&numVal, (void*)&fData, sizeof(float));
}
return numVal;
}
/* Returns true if the expr can be evaluated */
int CExpr::Analyze()
{
size_t pos = 0, xc = 0, xpos = 0;
size_t pos = 0, xc = 0, xpos = 0, fd = 0;
/* run through the characters */
if (data.compare("$") == 0)
{
@ -194,10 +201,14 @@ int CExpr::Analyze()
}
for (pos = 0; pos < data.size(); pos++)
{
if (data[pos] == 'x')
if (data[pos] == '.')
{
fd++;
if (fd > 1 || xc)
return 0;
} else if (data[pos] == 'x') {
xc++;
if (xc > 1)
if (xc > 1 || fd)
return 0;
xpos = pos;
} else if (data[pos] != ' '
@ -210,7 +221,7 @@ int CExpr::Analyze()
return 1;
}
cExprType CExpr::Evaluate()
cExprType CExpr::Evaluate(int symNum)
{
size_t i = 0, blk = 0;
char litc = 0, c = 0, csave = 0;
@ -218,14 +229,22 @@ cExprType CExpr::Evaluate()
std::string num;
block = new char[2];
bDone = true;
if (data.compare("$") == 0)
{
t = Val_Number;
type = Val_Number;
numVal = CError->CurCip();
char buf[32];
sprintf(buf, "%d", numVal);
data.assign(buf);
Update();
return t;
} else {
if (CError->IsSymbol(data) || (IsValidSymbol(data) && symNum == Sym_Label))
{
type = Val_Number;
numVal = CError->DerefSymbol(data, symNum);
Update();
return t;
}
}
if (data.find('\'', 0) != std::string::npos || data.find('"', 0) != std::string::npos)
@ -307,13 +326,20 @@ cExprType CExpr::Evaluate()
numVal++;
}
} else {
/* Just get the number */
t = Val_Number;
numVal = DeHex(data);
char buf[32];
sprintf(buf, "%d", numVal);
data.assign(buf);
if (data.find('.', 0) != std::string::npos)
{
/* Get as a float */
fData = (float)atof(data.c_str());
t = Val_Float;
memcpy((void*)&numVal, (void*)&fData, sizeof(float));
} else {
/* Just get the number */
t = Val_Number;
numVal = DeHex(data);
char buf[32];
sprintf(buf, "%d", numVal);
data.assign(buf);
}
}
if (litc)
@ -326,3 +352,183 @@ cExprType CExpr::Evaluate()
return t;
}
void CExpr::Not()
{
if (type != Val_Number)
{
if (CError)
CError->ErrorMsg(Err_Bad_Not);
}
numVal = ~numVal;
}
void CExpr::Oper(OpToken op, CExpr &e)
{
switch (op)
{
case Token_Xor:
{
if (e.GetType() != Val_Number)
{
if (CError)
CError->ErrorMsg(Err_Invalid_Operator);
}
numVal = numVal ^ e.GetNumber();
break;
}
case Token_Shr:
{
if (e.GetType() != Val_Number)
{
if (CError)
CError->ErrorMsg(Err_Invalid_Operator);
}
numVal >>= e.GetNumber();
break;
}
case Token_Sub:
{
if (GetType() == Val_Number)
{
if (e.GetType() == Val_Number)
{
numVal -= e.GetNumber();
} else if (e.GetType() == Val_Float) {
numVal -= (int)e.GetFloat();
}
} else if (GetType() == Val_Float) {
if (e.GetType() == Val_Number)
{
fData -= (float)e.GetNumber();
} else if (e.GetType() == Val_Float) {
fData -= e.GetFloat();
}
}
break;
}
case Token_Mod:
{
if (e.GetType() != Val_Number)
{
if (CError)
CError->ErrorMsg(Err_Invalid_Operator);
}
numVal = numVal % e.GetNumber();
break;
}
case Token_Mul:
{
if (GetType() == Val_Number)
{
if (e.GetType() == Val_Number)
{
numVal *= e.GetNumber();
} else if (e.GetType() == Val_Float) {
numVal *= (int)e.GetFloat();
}
} else if (GetType() == Val_Float) {
if (e.GetType() == Val_Number)
{
fData *= (float)e.GetNumber();
} else if (e.GetType() == Val_Float) {
fData *= e.GetFloat();
}
}
break;
}
case Token_Div:
{
if (GetType() == Val_Number)
{
if (e.GetType() == Val_Number)
{
numVal /= e.GetNumber();
} else if (e.GetType() == Val_Float) {
numVal /= (int)e.GetFloat();
}
} else if (GetType() == Val_Float) {
if (e.GetType() == Val_Number)
{
fData /= (float)e.GetNumber();
} else if (e.GetType() == Val_Float) {
fData /= e.GetFloat();
}
}
break;
}
case Token_Shl:
{
if (e.GetType() != Val_Number)
{
if (CError)
CError->ErrorMsg(Err_Invalid_Operator);
}
numVal <<= e.GetNumber();
break;
}
case Token_And:
{
if (e.GetType() != Val_Number)
{
if (CError)
CError->ErrorMsg(Err_Invalid_Operator);
}
numVal &= e.GetNumber();
break;
}
case Token_Or:
{
if (e.GetType() != Val_Number)
{
if (CError)
CError->ErrorMsg(Err_Invalid_Operator);
}
numVal |= e.GetNumber();
break;
}
case Token_Add:
{
if (GetType() == Val_Number)
{
if (e.GetType() == Val_Number)
{
numVal += e.GetNumber();
} else if (e.GetType() == Val_Float) {
numVal += (int)e.GetFloat();
}
} else if (GetType() == Val_Float) {
if (e.GetType() == Val_Number)
{
fData += (float)e.GetNumber();
} else if (e.GetType() == Val_Float) {
fData += e.GetFloat();
}
}
break;
}
default:
{
numVal = 0;
break;
}
}
Update();
}
void CExpr::Update()
{
if (type == Val_Float)
{
numVal = (int)fData;
} else if (type == Val_Number) {
fData = (float)numVal;
}
if (type != Val_String && type != Val_Block)
{
char buf[24];
sprintf(buf, "%d", numVal);
data.assign(buf);
}
}

View File

@ -27,6 +27,24 @@
* It reads in a symbol and evaluates it.
*/
typedef enum
{
Token_None,
Token_Or,
Token_Xor,
Token_And,
Token_Shr,
Token_Shl,
Token_Mod,
Token_Div,
Token_Mul,
Token_Sub,
Token_Add,
Token_Not,
/* End */
Tokens_Total,
} OpToken;
typedef enum
{
Val_None,
@ -38,6 +56,7 @@ typedef enum
Val_Number,
Val_Block,
Val_Hex,
Val_Float,
} cExprType;
class CExpr
@ -49,13 +68,17 @@ public:
void Set(std::string &text);
const char *GetString(int *d=NULL);
int Analyze();
cExprType Evaluate();
cExprType Evaluate(int symNum = 0);
cExprType GetType();
int GetNumber();
float GetFloat() { return fData; }
int Size();
void Clear();
void Not();
void Oper(OpToken op, CExpr &e);
~CExpr();
private:
void Update();
char IsHex(char c);
char IsLiteral(char c);
int DeHex(std::string blk);
@ -63,7 +86,9 @@ private:
char *block;
std::string data;
cExprType type;
float fData;
int numVal;
bool bDone;
private:
ErrorMngr *CError;
};