icode assembler changes

This commit is contained in:
rginda%netscape.com 2000-10-17 00:41:54 +00:00
parent 42308db283
commit 169089589e
8 changed files with 538 additions and 140 deletions

View File

@ -15,7 +15,9 @@ objs = hash.o \
vmtypes.o \
debugger.o
test_objs = hash.o \
test_objs = hash.o \
icodeasm.o \
ica_test.o \
icodegenerator.o \
interpreter.o \
jsmath.o \
@ -44,8 +46,8 @@ gc.a:
gctest: gc_allocator.o
$(CC) -o $@ -ggdb $^ $(libs)
ica_test:
$(CC) $(CFLAGS) -o ica_test ica_test.cpp icodeasm.cpp $(test_objs) $(libs)
ica_test: $(test_objs)
$(CC) $(CFLAGS) -o $@ $(test_objs) $(libs)
clean:
rm -f $(objs)

View File

@ -36,36 +36,108 @@
#include "icodeasm.h"
void testAlpha (JavaScript::ICodeASM::ICodeParser icp, const string &str,
const string &expect)
{
string *result;
icp.ParseAlpha (str.begin(), str.end(), &result);
if (*result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' alpha parsed as '%s'\n", str.c_str(),
result->c_str());
}
void testBool (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
bool expect)
{
bool b;
icp.ParseBool (str.begin(), str.end(), &b);
if (b == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' bool parsed as %i\n", str.c_str(), b);
}
void testDouble (JavaScript::ICodeASM::ICodeParser icp, const string &str,
double expect)
{
double result;
icp.ParseDouble (str.begin(), str.end(), &result);
if (result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' double parsed as %f\n", str.c_str(),
result);
}
void testString (JavaScript::ICodeASM::ICodeParser icp, const string &str,
const string &expect)
{
string *result;
icp.ParseString (str.begin(), str.end(), &result);
if (*result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' string parsed as '%s'\n", str.c_str(),
result->c_str());
}
void testUInt32 (JavaScript::ICodeASM::ICodeParser icp, const string &str,
uint32 expect)
{
uint32 result;
icp.ParseUInt32 (str.begin(), str.end(), &result);
if (result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' uint32 parsed as %u\n", str.c_str(),
result);
}
int
main (int , char **)
{
JavaScript::ICodeASM::ICodeParser icp;
bool b;
string str;
#define BOOL_TEST(s, expect) \
{ \
b = false; \
str = s; \
icp.ParseBool (str.begin(), str.end(), &b); \
if (b == expect) \
fprintf (stderr, "PASS: "); \
else \
fprintf (stderr, "FAIL: "); \
fprintf (stderr, "string %s bool parsed as %i\n", str.c_str(), b); \
} \
testAlpha (icp, "False", "False");
testAlpha (icp, "fe fi fo fum", "fe");
testAlpha (icp, " bla", "");
BOOL_TEST ("true", true);
BOOL_TEST ("True", true);
BOOL_TEST ("tRue", true);
BOOL_TEST ("TRUE", true);
BOOL_TEST ("True", true);
BOOL_TEST ("false", false);
BOOL_TEST ("False", false);
BOOL_TEST ("fAlSe", false);
BOOL_TEST ("FALSE", false);
BOOL_TEST ("False", false);
testBool (icp, "true", true);
testBool (icp, "True", true);
testBool (icp, "tRue", true);
testBool (icp, "TRUE", true);
testBool (icp, "True", true);
testBool (icp, "false", false);
testBool (icp, "False", false);
testBool (icp, "fAlSe", false);
testBool (icp, "FALSE", false);
testBool (icp, "False", false);
testDouble (icp, "123", 123);
testDouble (icp, "12.3", 12.3);
testDouble (icp, "-123", -123);
testDouble (icp, "-12.3", -12.3);
testString (icp, "\"fe fi fo fum\"", "fe fi fo fum");
testString (icp, "'the tab is ->\\t<- here'", "the tab is ->\t<- here");
testString (icp, "'the newline is ->\\n<- here'", "the newline is ->\n<- here");
testString (icp, "'the cr is ->\\r<- here'", "the cr is ->\r<- here");
testString (icp, "\"an \\\"escaped\\\" string\"", "an \"escaped\" string");
testUInt32 (icp, "123", 123);
testUInt32 (icp, "12.3", 12);
testUInt32 (icp, "-123", 0);
testUInt32 (icp, "-12.3", 0);
/* XXX what to do with the overflow? */
//testUInt32 (icp, "12123687213612873621873438754387934657834", 0);
return 0;
}

View File

@ -38,7 +38,8 @@
namespace JavaScript {
namespace ICodeASM {
static char *keyword_offset = "offset";
int cmp_nocase (const string& s1, string::const_iterator s2_begin,
string::const_iterator s2_end)
{
@ -102,11 +103,21 @@ namespace ICodeASM {
tl.begin = curpos;
return tl;
case '-':
tl.estimate = teMinus;
tl.begin = curpos;
return tl;
case '+':
tl.estimate = tePlus;
tl.begin = curpos;
return tl;
case ',':
tl.estimate = teComma;
tl.begin = curpos;
return tl;
case '"':
case '\'':
tl.estimate = teString;
@ -131,7 +142,7 @@ namespace ICodeASM {
}
iter
ICodeParser::ParseAlpha (iter begin, iter end, string *rval)
ICodeParser::ParseAlpha (iter begin, iter end, string **rval)
{
iter curpos;
string *str = new string();
@ -152,7 +163,7 @@ namespace ICodeASM {
}
scan_done:
rval = str;
*rval = str;
return curpos;
}
@ -187,16 +198,31 @@ namespace ICodeASM {
ICodeParser::ParseDouble (iter begin, iter end, double *rval)
{
/* XXX add overflow checking */
*rval = 0;
uint32 integer;
int sign = 1;
/* pay no attention to the assignment of sign in the test condition :O */
if (*begin == '+' || (*begin == '-' && (sign = -1)) {
TokenLocation tl = SeekTokenStart (++begin, end);
if (tl.estimate != teNumeric)
throw new ICodeParseException ("Expected double value");
begin = tl.begin;
}
iter curpos = ParseUInt32 (begin, end, &integer);
*rval = static_cast<double>(integer);
if (*curpos != '.')
{
*rval *= sign;
return curpos;
}
++curpos;
uint32 position = 0;
int32 position = 0;
for (curpos = begin; curpos < end; ++curpos) {
for (; curpos < end; ++curpos) {
switch (*curpos)
{
case '0'...'9':
@ -209,19 +235,44 @@ namespace ICodeASM {
}
scan_done:
*rval *= sign;
return curpos;
}
iter
ICodeParser::ParseString (iter begin, iter end, string *rval)
ICodeParser::ParseInt32 (iter begin, iter end, int32 *rval)
{
*rval = 0;
int sign = 1;
/* pay no attention to the assignment of sign in the test condition :O */
if ((*begin == '+') || (*begin == '-' && (sign = -1))) {
TokenLocation tl = SeekTokenStart (++begin, end);
if (tl.estimate != teNumeric)
throw new ICodeParseException ("Expected int32 value");
begin = tl.begin;
}
end = ParseUInt32 (begin, end, rval);
*rval *= sign;
return end;
}
iter
ICodeParser::ParseString (iter begin, iter end, string **rval)
{
char delim = *begin;
bool isTerminated = false;
/* XXX not exactly exception safe, string may never get deleted */
string *str = new string();
*rval = 0;
if (delim != '\'' && delim != '"') {
ASSERT ("|begin| does not point at a string");
delete str;
return 0;
}
@ -303,7 +354,7 @@ namespace ICodeASM {
throw new ICodeParseException ("Unterminated string literal.");
}
rval = str;
*rval = str;
return curpos;
}
@ -311,7 +362,8 @@ namespace ICodeASM {
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
{
/* XXX add overflow checking */
int32 position = 0;
*rval = 0;
int32 position = -1;
iter curpos;
for (curpos = begin; curpos < end; ++curpos) {
@ -334,11 +386,17 @@ namespace ICodeASM {
return curpos;
}
iter ICodeParser::ParseInstruction (uint icodeID, iter start, iter end)
iter ICodeParser::ParseInstruction (uint icodeID, iter begin, iter end)
{
iter curpos = start;
iter curpos = begin;
StatementNode *node = new StatementNode();
node->begin = begin;
node->icodeID = icodeID;
/* add the node now, so the parse*operand functions can see it (to add
* it to the fixup vector, for example.)
*/
mStatementNodes.push_back (node);
# define CASE_TYPE(T) \
case ot##T: \
@ -370,7 +428,7 @@ namespace ICodeASM {
}
# undef CASE_TYPE
return curpos;
}
@ -444,7 +502,7 @@ namespace ICodeASM {
if (tl.estimate != teString)
throw new ICodeParseException ("Expected BinaryOp as a quoted string.");
string *str;
end = ParseString (tl.begin, end, str);
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
@ -461,11 +519,15 @@ namespace ICodeASM {
}
iter
ICodeParser::ParseDoubleOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseDoubleOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if ((tl.estimate != teNumeric) && (tl.estimate != teMinus) &&
(tl.estimate != tePlus))
throw new ICodeParseException ("Expected double value.");
return ParseDouble (tl.begin, end, &o->asDouble);
}
iter
@ -477,49 +539,101 @@ namespace ICodeASM {
throw new ICodeParseException ("Expected ICode Module as a quoted string.");
string *str;
end = ParseString (tl.begin, end, str);
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSClassOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSClassOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSClass as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSStringOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSStringOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSString as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSFunctionOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSFunctionOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSFunction as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSTypeOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSTypeOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSType as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseLabelOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseLabelOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teAlpha)
throw new ICodeParseException ("Expected Label Identifier or Offset keyword.");
string *str;
begin = ParseAlpha (tl.begin, end, &str);
if (cmp_nocase(*string, keyword_offset, keyword_offset +
strlen(keyword_offset) + 1) == 0) {
/* label expressed as "Offset +/-N" */
tl = SeekTokenStart (begin, end);
if ((tl.estimate != teNumeric) && (tl.estimate != teMinus) &&
(tl.estimate != tePlus))
throw new ICodeParseException ("Expected numeric value after Offset keyword.");
begin = ParseInt32 (tl.begin, end, &(o->asInt32));
return begin;
} else {
/* label expressed as "label_name" */
LabelMap::const_iterator l = mLabels.find(str->c_string());
if (l == mLabels.end())
{
/* if we can't find the label, mark it as a fixup for later */
o->asString = str;
mFixupNodes.push_back (mStatementNodes.back());
return begin;
}
/* XXX continue here... */
}
}
iter

View File

@ -46,7 +46,9 @@ namespace ICodeASM {
teUnknown,
teIllegal,
teComma,
teMinus,
teNumeric,
tePlus,
teAlpha,
teString,
teNotARegister
@ -84,6 +86,7 @@ namespace ICodeASM {
/* eww */
double asDouble;
uint32 asUInt32;
int32 asInt32;
VM::Register asRegister;
bool asBoolean;
VM::ArgumentList *asArgumentList;
@ -91,6 +94,7 @@ namespace ICodeASM {
};
struct StatementNode {
iter pos;
uint icodeID;
AnyOperand operand[3];
};
@ -100,7 +104,9 @@ namespace ICodeASM {
private:
uint mMaxRegister;
std::vector<StatementNode *> mStatementNodes;
std::map<string, StatementNode **> mLabels;
std::vector<StatementNode *> mFixupNodes;
typedef std::map<const char *, StatementNode **> LabelMap;
LabelMap mLabels;
public:
void ParseSourceFromString (const string source);
@ -108,12 +114,17 @@ namespace ICodeASM {
/* locate the beginning of the next token, and guess what it might be */
TokenLocation SeekTokenStart (iter begin, iter end);
/* general purpose parse functions */
iter ParseAlpha (iter begin, iter end, string *rval);
/* general purpose parse functions; |begin| is expected to point
* at the start of the token to be processed (eg, these routines
* don't call |SeekTokenStart|, and (currently, this might change) no
* initial check is done to ensure that |begin| != |end|.
*/
iter ParseAlpha (iter begin, iter end, string **rval);
iter ParseBool (iter begin, iter end, bool *rval);
iter ParseDouble (iter begin, iter end, double *rval);
iter ParseString (iter begin, iter end, string *rval);
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
iter ParseDouble (iter begin, iter end, double *rval);
iter ParseInt32 (iter begin, iter end, uint32 *rval);
iter ParseString (iter begin, iter end, string **rval);
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
/* "high level" parse functions */
iter ParseInstruction (uint icodeID, iter start, iter end);

View File

@ -15,7 +15,9 @@ objs = hash.o \
vmtypes.o \
debugger.o
test_objs = hash.o \
test_objs = hash.o \
icodeasm.o \
ica_test.o \
icodegenerator.o \
interpreter.o \
jsmath.o \
@ -44,8 +46,8 @@ gc.a:
gctest: gc_allocator.o
$(CC) -o $@ -ggdb $^ $(libs)
ica_test:
$(CC) $(CFLAGS) -o ica_test ica_test.cpp icodeasm.cpp $(test_objs) $(libs)
ica_test: $(test_objs)
$(CC) $(CFLAGS) -o $@ $(test_objs) $(libs)
clean:
rm -f $(objs)

View File

@ -36,36 +36,108 @@
#include "icodeasm.h"
void testAlpha (JavaScript::ICodeASM::ICodeParser icp, const string &str,
const string &expect)
{
string *result;
icp.ParseAlpha (str.begin(), str.end(), &result);
if (*result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' alpha parsed as '%s'\n", str.c_str(),
result->c_str());
}
void testBool (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
bool expect)
{
bool b;
icp.ParseBool (str.begin(), str.end(), &b);
if (b == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' bool parsed as %i\n", str.c_str(), b);
}
void testDouble (JavaScript::ICodeASM::ICodeParser icp, const string &str,
double expect)
{
double result;
icp.ParseDouble (str.begin(), str.end(), &result);
if (result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' double parsed as %f\n", str.c_str(),
result);
}
void testString (JavaScript::ICodeASM::ICodeParser icp, const string &str,
const string &expect)
{
string *result;
icp.ParseString (str.begin(), str.end(), &result);
if (*result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' string parsed as '%s'\n", str.c_str(),
result->c_str());
}
void testUInt32 (JavaScript::ICodeASM::ICodeParser icp, const string &str,
uint32 expect)
{
uint32 result;
icp.ParseUInt32 (str.begin(), str.end(), &result);
if (result == expect)
fprintf (stderr, "PASS: ");
else
fprintf (stderr, "FAIL: ");
fprintf (stderr, "string '%s' uint32 parsed as %u\n", str.c_str(),
result);
}
int
main (int , char **)
{
JavaScript::ICodeASM::ICodeParser icp;
bool b;
string str;
#define BOOL_TEST(s, expect) \
{ \
b = false; \
str = s; \
icp.ParseBool (str.begin(), str.end(), &b); \
if (b == expect) \
fprintf (stderr, "PASS: "); \
else \
fprintf (stderr, "FAIL: "); \
fprintf (stderr, "string %s bool parsed as %i\n", str.c_str(), b); \
} \
testAlpha (icp, "False", "False");
testAlpha (icp, "fe fi fo fum", "fe");
testAlpha (icp, " bla", "");
BOOL_TEST ("true", true);
BOOL_TEST ("True", true);
BOOL_TEST ("tRue", true);
BOOL_TEST ("TRUE", true);
BOOL_TEST ("True", true);
BOOL_TEST ("false", false);
BOOL_TEST ("False", false);
BOOL_TEST ("fAlSe", false);
BOOL_TEST ("FALSE", false);
BOOL_TEST ("False", false);
testBool (icp, "true", true);
testBool (icp, "True", true);
testBool (icp, "tRue", true);
testBool (icp, "TRUE", true);
testBool (icp, "True", true);
testBool (icp, "false", false);
testBool (icp, "False", false);
testBool (icp, "fAlSe", false);
testBool (icp, "FALSE", false);
testBool (icp, "False", false);
testDouble (icp, "123", 123);
testDouble (icp, "12.3", 12.3);
testDouble (icp, "-123", -123);
testDouble (icp, "-12.3", -12.3);
testString (icp, "\"fe fi fo fum\"", "fe fi fo fum");
testString (icp, "'the tab is ->\\t<- here'", "the tab is ->\t<- here");
testString (icp, "'the newline is ->\\n<- here'", "the newline is ->\n<- here");
testString (icp, "'the cr is ->\\r<- here'", "the cr is ->\r<- here");
testString (icp, "\"an \\\"escaped\\\" string\"", "an \"escaped\" string");
testUInt32 (icp, "123", 123);
testUInt32 (icp, "12.3", 12);
testUInt32 (icp, "-123", 0);
testUInt32 (icp, "-12.3", 0);
/* XXX what to do with the overflow? */
//testUInt32 (icp, "12123687213612873621873438754387934657834", 0);
return 0;
}

View File

@ -38,7 +38,8 @@
namespace JavaScript {
namespace ICodeASM {
static char *keyword_offset = "offset";
int cmp_nocase (const string& s1, string::const_iterator s2_begin,
string::const_iterator s2_end)
{
@ -102,11 +103,21 @@ namespace ICodeASM {
tl.begin = curpos;
return tl;
case '-':
tl.estimate = teMinus;
tl.begin = curpos;
return tl;
case '+':
tl.estimate = tePlus;
tl.begin = curpos;
return tl;
case ',':
tl.estimate = teComma;
tl.begin = curpos;
return tl;
case '"':
case '\'':
tl.estimate = teString;
@ -131,7 +142,7 @@ namespace ICodeASM {
}
iter
ICodeParser::ParseAlpha (iter begin, iter end, string *rval)
ICodeParser::ParseAlpha (iter begin, iter end, string **rval)
{
iter curpos;
string *str = new string();
@ -152,7 +163,7 @@ namespace ICodeASM {
}
scan_done:
rval = str;
*rval = str;
return curpos;
}
@ -187,16 +198,31 @@ namespace ICodeASM {
ICodeParser::ParseDouble (iter begin, iter end, double *rval)
{
/* XXX add overflow checking */
*rval = 0;
uint32 integer;
int sign = 1;
/* pay no attention to the assignment of sign in the test condition :O */
if (*begin == '+' || (*begin == '-' && (sign = -1)) {
TokenLocation tl = SeekTokenStart (++begin, end);
if (tl.estimate != teNumeric)
throw new ICodeParseException ("Expected double value");
begin = tl.begin;
}
iter curpos = ParseUInt32 (begin, end, &integer);
*rval = static_cast<double>(integer);
if (*curpos != '.')
{
*rval *= sign;
return curpos;
}
++curpos;
uint32 position = 0;
int32 position = 0;
for (curpos = begin; curpos < end; ++curpos) {
for (; curpos < end; ++curpos) {
switch (*curpos)
{
case '0'...'9':
@ -209,19 +235,44 @@ namespace ICodeASM {
}
scan_done:
*rval *= sign;
return curpos;
}
iter
ICodeParser::ParseString (iter begin, iter end, string *rval)
ICodeParser::ParseInt32 (iter begin, iter end, int32 *rval)
{
*rval = 0;
int sign = 1;
/* pay no attention to the assignment of sign in the test condition :O */
if ((*begin == '+') || (*begin == '-' && (sign = -1))) {
TokenLocation tl = SeekTokenStart (++begin, end);
if (tl.estimate != teNumeric)
throw new ICodeParseException ("Expected int32 value");
begin = tl.begin;
}
end = ParseUInt32 (begin, end, rval);
*rval *= sign;
return end;
}
iter
ICodeParser::ParseString (iter begin, iter end, string **rval)
{
char delim = *begin;
bool isTerminated = false;
/* XXX not exactly exception safe, string may never get deleted */
string *str = new string();
*rval = 0;
if (delim != '\'' && delim != '"') {
ASSERT ("|begin| does not point at a string");
delete str;
return 0;
}
@ -303,7 +354,7 @@ namespace ICodeASM {
throw new ICodeParseException ("Unterminated string literal.");
}
rval = str;
*rval = str;
return curpos;
}
@ -311,7 +362,8 @@ namespace ICodeASM {
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
{
/* XXX add overflow checking */
int32 position = 0;
*rval = 0;
int32 position = -1;
iter curpos;
for (curpos = begin; curpos < end; ++curpos) {
@ -334,11 +386,17 @@ namespace ICodeASM {
return curpos;
}
iter ICodeParser::ParseInstruction (uint icodeID, iter start, iter end)
iter ICodeParser::ParseInstruction (uint icodeID, iter begin, iter end)
{
iter curpos = start;
iter curpos = begin;
StatementNode *node = new StatementNode();
node->begin = begin;
node->icodeID = icodeID;
/* add the node now, so the parse*operand functions can see it (to add
* it to the fixup vector, for example.)
*/
mStatementNodes.push_back (node);
# define CASE_TYPE(T) \
case ot##T: \
@ -370,7 +428,7 @@ namespace ICodeASM {
}
# undef CASE_TYPE
return curpos;
}
@ -444,7 +502,7 @@ namespace ICodeASM {
if (tl.estimate != teString)
throw new ICodeParseException ("Expected BinaryOp as a quoted string.");
string *str;
end = ParseString (tl.begin, end, str);
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
@ -461,11 +519,15 @@ namespace ICodeASM {
}
iter
ICodeParser::ParseDoubleOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseDoubleOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if ((tl.estimate != teNumeric) && (tl.estimate != teMinus) &&
(tl.estimate != tePlus))
throw new ICodeParseException ("Expected double value.");
return ParseDouble (tl.begin, end, &o->asDouble);
}
iter
@ -477,49 +539,101 @@ namespace ICodeASM {
throw new ICodeParseException ("Expected ICode Module as a quoted string.");
string *str;
end = ParseString (tl.begin, end, str);
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSClassOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSClassOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSClass as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSStringOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSStringOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSString as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSFunctionOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSFunctionOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSFunction as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseJSTypeOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseJSTypeOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teString)
throw new ICodeParseException ("Expected JSType as a quoted string.");
string *str;
end = ParseString (tl.begin, end, &str);
o->asString = str;
return end;
}
iter
ICodeParser::ParseLabelOperand (iter begin, iter /*end*/,
AnyOperand */*o*/)
ICodeParser::ParseLabelOperand (iter begin, iter end, AnyOperand *o)
{
ASSERT ("Not Implemented.");
return begin;
TokenLocation tl = SeekTokenStart (begin, end);
if (tl.estimate != teAlpha)
throw new ICodeParseException ("Expected Label Identifier or Offset keyword.");
string *str;
begin = ParseAlpha (tl.begin, end, &str);
if (cmp_nocase(*string, keyword_offset, keyword_offset +
strlen(keyword_offset) + 1) == 0) {
/* label expressed as "Offset +/-N" */
tl = SeekTokenStart (begin, end);
if ((tl.estimate != teNumeric) && (tl.estimate != teMinus) &&
(tl.estimate != tePlus))
throw new ICodeParseException ("Expected numeric value after Offset keyword.");
begin = ParseInt32 (tl.begin, end, &(o->asInt32));
return begin;
} else {
/* label expressed as "label_name" */
LabelMap::const_iterator l = mLabels.find(str->c_string());
if (l == mLabels.end())
{
/* if we can't find the label, mark it as a fixup for later */
o->asString = str;
mFixupNodes.push_back (mStatementNodes.back());
return begin;
}
/* XXX continue here... */
}
}
iter

View File

@ -46,7 +46,9 @@ namespace ICodeASM {
teUnknown,
teIllegal,
teComma,
teMinus,
teNumeric,
tePlus,
teAlpha,
teString,
teNotARegister
@ -84,6 +86,7 @@ namespace ICodeASM {
/* eww */
double asDouble;
uint32 asUInt32;
int32 asInt32;
VM::Register asRegister;
bool asBoolean;
VM::ArgumentList *asArgumentList;
@ -91,6 +94,7 @@ namespace ICodeASM {
};
struct StatementNode {
iter pos;
uint icodeID;
AnyOperand operand[3];
};
@ -100,7 +104,9 @@ namespace ICodeASM {
private:
uint mMaxRegister;
std::vector<StatementNode *> mStatementNodes;
std::map<string, StatementNode **> mLabels;
std::vector<StatementNode *> mFixupNodes;
typedef std::map<const char *, StatementNode **> LabelMap;
LabelMap mLabels;
public:
void ParseSourceFromString (const string source);
@ -108,12 +114,17 @@ namespace ICodeASM {
/* locate the beginning of the next token, and guess what it might be */
TokenLocation SeekTokenStart (iter begin, iter end);
/* general purpose parse functions */
iter ParseAlpha (iter begin, iter end, string *rval);
/* general purpose parse functions; |begin| is expected to point
* at the start of the token to be processed (eg, these routines
* don't call |SeekTokenStart|, and (currently, this might change) no
* initial check is done to ensure that |begin| != |end|.
*/
iter ParseAlpha (iter begin, iter end, string **rval);
iter ParseBool (iter begin, iter end, bool *rval);
iter ParseDouble (iter begin, iter end, double *rval);
iter ParseString (iter begin, iter end, string *rval);
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
iter ParseDouble (iter begin, iter end, double *rval);
iter ParseInt32 (iter begin, iter end, uint32 *rval);
iter ParseString (iter begin, iter end, string **rval);
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
/* "high level" parse functions */
iter ParseInstruction (uint icodeID, iter start, iter end);