This commit is contained in:
marketideas 2019-11-18 11:34:20 -08:00
parent 3fd0c7bcb5
commit 0a5f52a2d0
4 changed files with 149 additions and 30 deletions

59
asm.cpp
View File

@ -291,7 +291,7 @@ void CLASS::clear()
operand_expr = "";
operand_expr2 = "";
addrtext = "";
merlinerrors=false;
merlinerrors = false;
linemx = 0;
bytect = 0;
opflags = 0;
@ -376,10 +376,12 @@ void CLASS::set(std::string line)
}
break;
case 3:
{
if (c > ' ')
{
opcode += c;
}
#if 1
else
{
// SGQ
@ -417,7 +419,41 @@ void CLASS::set(std::string line)
state = 4;
}
break;
#else
else
{
// SGQ
// this is bad, but the only way I currently know how to do this.
// the problem is, is that the ASCII generating psuedo-ops in Merlin
// use any char > space and less than apostrophe, and > apostrophe
// as delimiters.
// however, those characters also contain valid opcode expression characters
// so we see a character here, it looks like a delim, and we keep reading to EOL
// which might include a comment. All of that, then goes into the operand, and
// comments cause errors on evaluation.
// So, at this point in the code, we must determine if the opcode is one of our
// ascii psuedo-ops and treat the first char as a delim.
// otherwise, we must parse the operand as an express.
// this parser should know NOTHING about what the code does...but it needs to in
// this case.
opupper = Poco::toUpper(opcode);
auto itr = a.opcodes.find(op);
if (itr != a.opcodes.end())
{
TSymbol s = itr->second;
if (1)
{
isascii = true;
}
}
state = 4;
}
#endif
}
break;
case 4: // read whitespace between opcode and operand
if (c == ';')
{
@ -986,11 +1022,18 @@ void CLASS::pushopcode(std::string op, uint8_t opcode, uint16_t flags, TOpCallba
opcodes.insert(p);
}
TSymbol *CLASS::addSymbol(std::string sym, uint32_t val, bool replace)
TSymbol *CLASS::addSymbol(std::string symname, uint32_t val, bool replace)
{
TSymbol *res = NULL;
TSymbol *fnd = NULL;
std::string sym = symname;
if (!casesen)
{
sym = Poco::toUpper(sym);
}
//printf("addSymbol: |%s|\n",sym.c_str());
if (sym.length() > 0)
{
TSymbol s;
@ -1001,7 +1044,7 @@ TSymbol *CLASS::addSymbol(std::string sym, uint32_t val, bool replace)
s.value = val;
s.used = false;
s.cb = NULL;
std::pair<std::string, TSymbol> p(Poco::toUpper(sym), s);
std::pair<std::string, TSymbol> p(sym, s);
if (sym[0] == ':')
{
@ -1061,10 +1104,10 @@ TSymbol *CLASS::findSymbol(std::string symname)
{
TSymbol *res = NULL;
std::string sym=symname;
std::string sym = symname;
if (!casesen)
{
sym=Poco::toUpper(sym);
sym = Poco::toUpper(sym);
}
if (symname.length() > 0)
{
@ -1105,10 +1148,10 @@ TSymbol *CLASS::addVariable(std::string symname, std::string val, bool replace)
TSymbol *res = NULL;
TSymbol *fnd = NULL;
std::string sym=symname;
std::string sym = symname;
if (!casesen)
{
sym=Poco::toUpper(sym);
sym = Poco::toUpper(sym);
}
//printf("addvariable\n");

115
eval.cpp
View File

@ -27,16 +27,18 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
int state = 0;
char c;
char delim;
std::string ident, asc;
std::string ident;
//, asc;
std::string ops = "+-*//^!.&()";
std::string c1;
char *tokptr;
char *tptr;
bool numexpect;
bool highascii = false;
Token::Type t;
delim=0;
delim = 0;
numexpect = true;
for (const auto* p = expr.c_str(); *p; ++p)
{
@ -56,18 +58,20 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
if ((c < ' ') || (c == delim))
{
// SGQ - convert ascii to a number here
asc = "0";
//printf("ident=|%s|\n",ident.c_str());
//asc = "0";
//printf("ascii ident=|%s|\n", ident.c_str());
if (ident.length() > 0)
{
// SGQ - convert ascii to a number here
}
t = Token::Type::Number;
ident = delim + ident + delim;
t = Token::Type::Ascii;
int pr = 1; // precedence
bool ra = false; // rightAssociative
bool ra = false;
tokens.push_back(Token
{
t, asc, pr, ra
t, ident, pr, ra
});
ident = "";
state = 0;
@ -75,6 +79,8 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
{
p--;
}
highascii = false;
delim = 0;
}
else
{
@ -150,6 +156,7 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
{
delim = c;
state = 11;
highascii = true;
numexpect = false;
}
else if (((c == '-') || (c == '+')) && (numexpect))
@ -220,7 +227,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
token.type = Token::Type::Number;
if (token.str == "*")
{
sprintf(buff, "%u", assembler.PC.currentpc);
sprintf(buff, "$%X", assembler.PC.currentpc);
token.str = buff;
}
else
@ -231,7 +238,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
if (sym != NULL)
{
sym->used = true;
sprintf(buff, "%d", sym->value);
sprintf(buff, "$%X", sym->value);
token.str = buff;
}
else
@ -243,6 +250,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
}
queue.push_back(token);
break;
case Token::Type::Ascii:
case Token::Type::Number:
// If the token is a number, then add it to the output queue
queue.push_back(token);
@ -363,9 +371,54 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
return queue;
}
int CLASS::parseAscii(std::string n, int64_t &val)
{
int res = -1;
val = 0;
bool err = false;
uint64_t tval = 0;
bool high = false;
uint8_t c;
uint32_t l = n.length();
for (uint32_t i = 0; i < l - 1; i++)
{
c = n[i];
if (i == 0)
{
if (c == '"')
{
high = true;
}
}
else
{
tval <<= 8;
if (high)
{
c |= 0x80;
}
else
{
c &= 0x7F;
}
tval = ((tval & 0xFFFFFF00) | c);
}
}
if (!err)
{
val = (uint32_t)(tval & 0xFFFFFFFF);
res = 0;
}
//printf("parseASCII |%s| %d %016lX\n", n.c_str(), res, val);
return (res);
}
int CLASS::parseNumber(std::string n, int64_t &val)
{
int res = DEF_VAL;
int res = -1;
int state = 0;
char c;
std::string s;
@ -376,8 +429,7 @@ int CLASS::parseNumber(std::string n, int64_t &val)
int64_t tval = 0;
val = 0;
//printf("parseNumber |%s|\n",n.c_str());
i = 0;
l = n.length();
s = "";
@ -483,12 +535,13 @@ int CLASS::parseNumber(std::string n, int64_t &val)
}
}
if (tval > (int64_t)0xFFFFFFFF)
uint32_t tv = (uint32_t)tval;
uint64_t tv1 = tv;
if (tv1 > (int64_t)0xFFFFFFFF)
{
setError(Token::overflowErr);
}
//printf("parsenumber: |%s|\n",s.c_str());
if ((state == 99) || (err))
{
@ -507,6 +560,13 @@ int CLASS::parseNumber(std::string n, int64_t &val)
//printf("value=%08lX\n", val);
res = 0;
}
if (res != 0)
{
if (isDebug() > 2)
{
printf("parsenumber error result: %d\n", res);
}
}
return (res);
}
@ -527,7 +587,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
// const std::string expr = "3+4*2/(1-5)^2^3"; // Wikipedia's example
// const std::string expr = "20-30/3+4*2^3";
_shiftmode=shiftmode=0;
_shiftmode = shiftmode = 0;
res = DEF_VAL;
setError(Token::noError);
@ -560,6 +620,19 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
//op = "Push " + token.str;
//printf("shouldn't get this kind of token\n");
break;
case Token::Type::Ascii:
val = 0;
u = parseAscii(token.str, val);
if (u < 0)
{
setError(Token::numberErr);
val = DEF_VAL;
}
stack.push_back(val);
//op = "Push " + token.str;
break;
case Token::Type::Number:
val = 0;
u = parseNumber(token.str, val);
@ -580,21 +653,21 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
{
rhs = stack.back();
stack.pop_back();
shiftmode=token.str[0];
shiftmode = token.str[0];
if (token.str=="^")
if (token.str == "^")
{
//rhs = (rhs >> 16) &0xFFFF ;
}
else if (token.str=="|")
else if (token.str == "|")
{
//rhs = (rhs >> 16) & 0xFFFF;
}
else if (token.str=="<")
else if (token.str == "<")
{
//rhs = (rhs << 8 ) & 0xFFFF;
}
else if (token.str==">")
else if (token.str == ">")
{
//rhs=(rhs>>8) & 0xFFFF;
}
@ -698,7 +771,7 @@ out:
{
setError(Token::syntaxErr);
}
_shiftmode=shiftmode;
_shiftmode = shiftmode;
res = v;
return (evalerror);
}

3
eval.h
View File

@ -41,6 +41,7 @@ public:
Unknown = 0,
Number,
Symbol,
Ascii,
Shift,
Operator,
LeftParen,
@ -71,6 +72,8 @@ public:
std::deque<Token> shuntingYard(const std::deque<Token>& tokens);
std::deque<Token> exprToTokens(const std::string& expr);
int parseNumber(std::string n, int64_t &val);
int parseAscii(std::string n, int64_t &val);
int evaluate(std::string &expr, int64_t &res, uint8_t &_shiftmode);
};

View File

@ -20,7 +20,7 @@ path4=
path5=dirpath5
[asm]
casesen=false
casesen=true
showmx=true
startmx=3
lst=true