mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 21:00:50 +00:00
icode assembler still in progress
This commit is contained in:
parent
cdb2f4b71c
commit
f74b1d34dd
@ -32,6 +32,9 @@ gc.a:
|
||||
gctest: gc_allocator.o
|
||||
$(CC) -o $@ -ggdb $^ $(libs)
|
||||
|
||||
ica_test:
|
||||
$(CC) $(CFLAGS) -o ica_test ica_test.cpp icodeasm.cpp $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f $(objs)
|
||||
|
||||
|
53
js/js2/ica_test.cpp
Normal file
53
js/js2/ica_test.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the JavaScript 2 Prototype.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "icodeasm.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
JavaScript::Debugger::ICodeParser icp;
|
||||
string str = "true";
|
||||
|
||||
bool b = false;
|
||||
icp.ParseBool (str.begin(), str.end(), &b);
|
||||
fprintf (stderr, "bool parsed as %c\n", b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,6 +39,22 @@
|
||||
namespace JavaScript {
|
||||
namespace ICodeASM {
|
||||
|
||||
int cmp_nocase (const string& s1, string::const_iterator s2_begin,
|
||||
string::const_iterator s2_end)
|
||||
{
|
||||
string::const_iterator p1 = s1.begin();
|
||||
string::const_iterator p2 = s2_begin;
|
||||
uint s2_size = s2_end - s2_begin;
|
||||
|
||||
while (p1 != s1.end() && p2 != s2_end) {
|
||||
if (toupper(*p1) != toupper(*p2))
|
||||
return (toupper(*p1) < toupper(*p2)) ? -1 : 1;
|
||||
++p1; ++p2;
|
||||
}
|
||||
|
||||
return (s1.size() == s2_size) ? 0 : (s1.size() < s2_size) ? -1 : 1;
|
||||
}
|
||||
|
||||
void
|
||||
ICodeParser::ParseSourceFromString (string source)
|
||||
{
|
||||
@ -115,36 +131,65 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
|
||||
ICodeParser::ParseAlpha (iter begin, iter end, string *rval)
|
||||
{
|
||||
uint32 position = 0;
|
||||
iter curpos;
|
||||
string *str = new string();
|
||||
|
||||
scan_loop:
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
position++;
|
||||
case '_':
|
||||
*str += *curpos;
|
||||
break;
|
||||
|
||||
default:
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
curpos = begin;
|
||||
for (; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * pow (10, position);
|
||||
|
||||
rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBool (iter begin, iter end, bool *rval)
|
||||
{
|
||||
iter curpos = begin;
|
||||
string *str = new string();
|
||||
|
||||
if ((curpos != end) && (*curpos == "T" || *curpos == "t")) {
|
||||
if ((++curpos != end) && (*curpos == "R" || *curpos == "r"))
|
||||
if ((++curpos != end) && (*curpos == "U" || *curpos == "u"))
|
||||
if ((++curpos != end) &&
|
||||
(*curpos == "E" || *curpos == "e")) {
|
||||
*rval = true;
|
||||
return ++curpos;
|
||||
}
|
||||
} else if ((curpos != end) && (*curpos == "F" || *curpos == "f")) {
|
||||
if ((++curpos != end) && (*curpos == "A" || *curpos == "a"))
|
||||
if ((++curpos != end) && (*curpos == "L" || *curpos == "l"))
|
||||
if ((++curpos != end) && (*curpos == "S" || *curpos == "s"))
|
||||
if ((++curpos != end) &&
|
||||
(*curpos == "E" || *curpos == "e")) {
|
||||
*rval = false;
|
||||
return ++curpos;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ICodeParseException ("Expected boolean value.");
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseDouble (iter begin, iter end, double *rval)
|
||||
{
|
||||
uint32 integer
|
||||
iter curpos = ParseUInt32 (begin, end, *integer);
|
||||
/* XXX add overflow checking */
|
||||
uint32 integer;
|
||||
iter curpos = ParseUInt32 (begin, end, &integer);
|
||||
*rval = static_cast<double>(integer);
|
||||
if (*curpos != '.')
|
||||
return curpos;
|
||||
@ -152,7 +197,6 @@ namespace ICodeASM {
|
||||
++curpos;
|
||||
uint32 position = 0;
|
||||
|
||||
scan_loop:
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
@ -161,56 +205,35 @@ namespace ICodeASM {
|
||||
break;
|
||||
|
||||
default:
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseAlpha (iter begin, iter end, string *rval)
|
||||
{
|
||||
string str = new string();
|
||||
|
||||
scan_loop:
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
case '_':
|
||||
str += *curpos;
|
||||
break;
|
||||
|
||||
default:
|
||||
break scan_loop;
|
||||
}
|
||||
}
|
||||
|
||||
rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (delim != '\'' && delim != '"')
|
||||
if (delim != '\'' && delim != '"') {
|
||||
ASSERT ("|begin| does not point at a string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
scan_loop:
|
||||
for (bool isEscaped = false, iter curpos = ++tl.begin; curpos < end;
|
||||
++curpos) {
|
||||
iter curpos = 0;
|
||||
bool isEscaped = false;
|
||||
for (curpos = ++begin; curpos < end; ++curpos) {
|
||||
|
||||
switch (*curpos) {
|
||||
case '\\':
|
||||
if (isEscaped) {
|
||||
str += '\\';
|
||||
*str += '\\';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
isEscaped = true;
|
||||
@ -219,57 +242,61 @@ namespace ICodeASM {
|
||||
|
||||
case 't':
|
||||
if (isEscaped) {
|
||||
str += '\t';
|
||||
*str += '\t';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
str += 't';
|
||||
*str += 't';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (isEscaped) {
|
||||
str += '\n';
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
str += 'n';
|
||||
*str += 'n';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (isEscaped) {
|
||||
str += '\r';
|
||||
*str += '\r';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
str += 'r';
|
||||
*str += 'r';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (isEscaped) {
|
||||
str += '\r';
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
/* unescaped newline == unterminated string */
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
|
||||
case delim:
|
||||
if (isEscaped) {
|
||||
str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
break scan_loop;
|
||||
case '\'':
|
||||
case '"':
|
||||
if (*curpos == delim) {
|
||||
if (isEscaped) {
|
||||
*str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
isEscaped = false;
|
||||
str += *curpos;
|
||||
*str += *curpos;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (!isTerminated)
|
||||
{
|
||||
@ -282,51 +309,31 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseStatement (iter begin, iter end)
|
||||
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected an alphanumeric token (like maybe an instruction or an opcode.)");
|
||||
|
||||
scan_loop:
|
||||
for (iter curpos = tl.begin; curpos < end; ++curpos) {
|
||||
/* XXX add overflow checking */
|
||||
uint32 position = 0;
|
||||
iter curpos;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ':':
|
||||
tl.type = ttLabel;
|
||||
tl.end = ++curpos;
|
||||
break scan_loop;
|
||||
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
case '_':
|
||||
position++;
|
||||
break;
|
||||
|
||||
default:
|
||||
tl.type = ttInstruction;
|
||||
tl.end = curpos;
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (tl.type = ttUndetermined) {
|
||||
tl.type = ttInstruction;
|
||||
tl.end = end;
|
||||
}
|
||||
|
||||
if (tl.type == ttLabel) {
|
||||
string label_str(tl.begin, tl.end - 1); /* ignore the trailing : */
|
||||
mLabels[label_str] = mStatementNodes.end();
|
||||
return tl.end;
|
||||
} else if (tl.type == ttInstruction) {
|
||||
string icode_str(tl.begin, tl.end);
|
||||
for (uint i = 0; i < icodemap_size; ++i)
|
||||
if (icode_str.compare(icodemap[i]) == 0)
|
||||
return ParseInstruction (i, tl.end, end);
|
||||
throw ("Unknown ICode " + icode_str);
|
||||
}
|
||||
curpos = begin;
|
||||
for (; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * static_cast<uint32>(pow (10, position));
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter ICodeParser::ParseInstruction (uint icodeID, iter start, iter end)
|
||||
@ -370,16 +377,63 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseArgumentListOperand (iter begin, iter end,
|
||||
AnyOperand *rval)
|
||||
ICodeParser::ParseStatement (iter begin, iter end)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected an alphanumeric token (like maybe an instruction or a label.)");
|
||||
|
||||
for (iter curpos = tl.begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ':':
|
||||
tl.type = ttLabel;
|
||||
tl.end = ++curpos;
|
||||
goto scan_done;
|
||||
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
case '_':
|
||||
break;
|
||||
|
||||
default:
|
||||
tl.type = ttInstruction;
|
||||
tl.end = curpos;
|
||||
goto scan_done;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (tl.type = ttUndetermined) {
|
||||
tl.type = ttInstruction;
|
||||
tl.end = end;
|
||||
}
|
||||
|
||||
if (tl.type == ttLabel) {
|
||||
string label_str(tl.begin, tl.end - 1); /* ignore the trailing : */
|
||||
mLabels[label_str] = mStatementNodes.end();
|
||||
return tl.end;
|
||||
} else if (tl.type == ttInstruction) {
|
||||
string icode_str(tl.begin, tl.end);
|
||||
for (uint i = 0; i < icodemap_size; ++i)
|
||||
if (cmp_nocase(icode_str, &icodemap[i].name[0],
|
||||
&icodemap[i].name[0] + strlen(icodemap[i].name) + 1))
|
||||
return ParseInstruction (i, tl.end, end);
|
||||
throw ("Unknown ICode " + icode_str);
|
||||
}
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseArgumentListOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
/* XXX this is hard, lets go shopping */
|
||||
ASSERT ("Not Implemented.");
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBinaryOpOperand (iter begin, iter end,
|
||||
AnyOperand *rval)
|
||||
ICodeParser::ParseBinaryOpOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
@ -387,9 +441,35 @@ namespace ICodeASM {
|
||||
throw new ICodeParseException ("Expected BinaryOp as a quoted string.");
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, str);
|
||||
rval->asString = str;
|
||||
o->asString = str;
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ParseBoolOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected boolean value.");
|
||||
|
||||
return ParseBool (tl.begin, end, &o->asBoolean);
|
||||
}
|
||||
|
||||
iter
|
||||
ParseICodeModuleOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected ICode Module as a quoted string.");
|
||||
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, str);
|
||||
o->asString = str;
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
#include "vmtypes.h"
|
||||
|
||||
#define iter string::const_iterator
|
||||
|
||||
namespace JavaScript {
|
||||
@ -64,10 +66,10 @@ namespace ICodeASM {
|
||||
};
|
||||
|
||||
struct ICodeParseException {
|
||||
ICodeParserException (string aMsg, iter aPos = 0)
|
||||
: msg(aMsg), pos(aPos) {}
|
||||
ICodeParseException (string aMsg, iter aPos = 0)
|
||||
: msg(aMsg), pos(aPos) {}
|
||||
string msg;
|
||||
iter aPos;
|
||||
iter pos;
|
||||
};
|
||||
|
||||
struct TokenLocation {
|
||||
@ -82,32 +84,34 @@ namespace ICodeASM {
|
||||
/* eww */
|
||||
double asDouble;
|
||||
uint32 asUInt32;
|
||||
Register asRegister;
|
||||
VM::Register asRegister;
|
||||
bool asBool;
|
||||
ArgumentList *asArgumentList;
|
||||
VM::ArgumentList *asArgumentList;
|
||||
string *asString;
|
||||
};
|
||||
|
||||
struct StatementNode {
|
||||
uint icodeID;
|
||||
AnyOperand operand[3];
|
||||
}
|
||||
};
|
||||
|
||||
class ICodeParser
|
||||
{
|
||||
private:
|
||||
uint mMaxRegister;
|
||||
std::vector<StatementNode *> mStatementNodes;
|
||||
std::map<string *, uint32> mLabels;
|
||||
std::map<string, StatementNode **> mLabels;
|
||||
|
||||
public:
|
||||
void ParseSourceFromString (const string source);
|
||||
TokenLocation SeekTokenStart (iter begin, iter end);
|
||||
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
|
||||
iter ParseDouble (iter begin, iter end, double *rval);
|
||||
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 ParseStatement (iter begin, iter end);
|
||||
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
|
||||
|
||||
iter ParseInstruction (uint icodeID, iter start, iter end);
|
||||
|
||||
iter ParseArgumentListOperand (iter begin, iter end, AnyOperand *o);
|
||||
|
@ -33,11 +33,14 @@
|
||||
|
||||
/* most of this file will get auto-generated from the icode metadata */
|
||||
|
||||
#include "systemtypes.h"
|
||||
|
||||
enum OperandType {
|
||||
otNone = 0,
|
||||
otArgumentList,
|
||||
otBinaryOp,
|
||||
otBool,
|
||||
otDouble,
|
||||
otICodeModule,
|
||||
otJSClass,
|
||||
otJSString,
|
||||
@ -53,12 +56,12 @@ static uint icodemap_size = 5;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
OperandType otype[3];
|
||||
} icode_map [icodemap_size] =
|
||||
OperandType otype[4];
|
||||
} icodemap [] =
|
||||
{
|
||||
{"LOAD_STRING", {otRegister, otString}},
|
||||
{"CAST", {otRegister, otRegister, otType}},
|
||||
{"SAVE_NAME", {otString, otRegister}},
|
||||
{"CALL", {otRegister, otRegister, otRegister, otRegisterList}},
|
||||
{"LOAD_STRING", {otRegister, otStringAtom}},
|
||||
{"CAST", {otRegister, otRegister, otJSType}},
|
||||
{"SAVE_NAME", {otJSString, otRegister}},
|
||||
{"CALL", {otRegister, otRegister, otRegister, otArgumentList}},
|
||||
{"RETURN", {otRegister}}
|
||||
};
|
||||
|
@ -32,6 +32,9 @@ gc.a:
|
||||
gctest: gc_allocator.o
|
||||
$(CC) -o $@ -ggdb $^ $(libs)
|
||||
|
||||
ica_test:
|
||||
$(CC) $(CFLAGS) -o ica_test ica_test.cpp icodeasm.cpp $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f $(objs)
|
||||
|
||||
|
53
js2/src/ica_test.cpp
Normal file
53
js2/src/ica_test.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the JavaScript 2 Prototype.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "icodeasm.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
JavaScript::Debugger::ICodeParser icp;
|
||||
string str = "true";
|
||||
|
||||
bool b = false;
|
||||
icp.ParseBool (str.begin(), str.end(), &b);
|
||||
fprintf (stderr, "bool parsed as %c\n", b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,6 +39,22 @@
|
||||
namespace JavaScript {
|
||||
namespace ICodeASM {
|
||||
|
||||
int cmp_nocase (const string& s1, string::const_iterator s2_begin,
|
||||
string::const_iterator s2_end)
|
||||
{
|
||||
string::const_iterator p1 = s1.begin();
|
||||
string::const_iterator p2 = s2_begin;
|
||||
uint s2_size = s2_end - s2_begin;
|
||||
|
||||
while (p1 != s1.end() && p2 != s2_end) {
|
||||
if (toupper(*p1) != toupper(*p2))
|
||||
return (toupper(*p1) < toupper(*p2)) ? -1 : 1;
|
||||
++p1; ++p2;
|
||||
}
|
||||
|
||||
return (s1.size() == s2_size) ? 0 : (s1.size() < s2_size) ? -1 : 1;
|
||||
}
|
||||
|
||||
void
|
||||
ICodeParser::ParseSourceFromString (string source)
|
||||
{
|
||||
@ -115,36 +131,65 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
|
||||
ICodeParser::ParseAlpha (iter begin, iter end, string *rval)
|
||||
{
|
||||
uint32 position = 0;
|
||||
iter curpos;
|
||||
string *str = new string();
|
||||
|
||||
scan_loop:
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
position++;
|
||||
case '_':
|
||||
*str += *curpos;
|
||||
break;
|
||||
|
||||
default:
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
curpos = begin;
|
||||
for (; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * pow (10, position);
|
||||
|
||||
rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBool (iter begin, iter end, bool *rval)
|
||||
{
|
||||
iter curpos = begin;
|
||||
string *str = new string();
|
||||
|
||||
if ((curpos != end) && (*curpos == "T" || *curpos == "t")) {
|
||||
if ((++curpos != end) && (*curpos == "R" || *curpos == "r"))
|
||||
if ((++curpos != end) && (*curpos == "U" || *curpos == "u"))
|
||||
if ((++curpos != end) &&
|
||||
(*curpos == "E" || *curpos == "e")) {
|
||||
*rval = true;
|
||||
return ++curpos;
|
||||
}
|
||||
} else if ((curpos != end) && (*curpos == "F" || *curpos == "f")) {
|
||||
if ((++curpos != end) && (*curpos == "A" || *curpos == "a"))
|
||||
if ((++curpos != end) && (*curpos == "L" || *curpos == "l"))
|
||||
if ((++curpos != end) && (*curpos == "S" || *curpos == "s"))
|
||||
if ((++curpos != end) &&
|
||||
(*curpos == "E" || *curpos == "e")) {
|
||||
*rval = false;
|
||||
return ++curpos;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ICodeParseException ("Expected boolean value.");
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseDouble (iter begin, iter end, double *rval)
|
||||
{
|
||||
uint32 integer
|
||||
iter curpos = ParseUInt32 (begin, end, *integer);
|
||||
/* XXX add overflow checking */
|
||||
uint32 integer;
|
||||
iter curpos = ParseUInt32 (begin, end, &integer);
|
||||
*rval = static_cast<double>(integer);
|
||||
if (*curpos != '.')
|
||||
return curpos;
|
||||
@ -152,7 +197,6 @@ namespace ICodeASM {
|
||||
++curpos;
|
||||
uint32 position = 0;
|
||||
|
||||
scan_loop:
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
@ -161,56 +205,35 @@ namespace ICodeASM {
|
||||
break;
|
||||
|
||||
default:
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseAlpha (iter begin, iter end, string *rval)
|
||||
{
|
||||
string str = new string();
|
||||
|
||||
scan_loop:
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
case '_':
|
||||
str += *curpos;
|
||||
break;
|
||||
|
||||
default:
|
||||
break scan_loop;
|
||||
}
|
||||
}
|
||||
|
||||
rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (delim != '\'' && delim != '"')
|
||||
if (delim != '\'' && delim != '"') {
|
||||
ASSERT ("|begin| does not point at a string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
scan_loop:
|
||||
for (bool isEscaped = false, iter curpos = ++tl.begin; curpos < end;
|
||||
++curpos) {
|
||||
iter curpos = 0;
|
||||
bool isEscaped = false;
|
||||
for (curpos = ++begin; curpos < end; ++curpos) {
|
||||
|
||||
switch (*curpos) {
|
||||
case '\\':
|
||||
if (isEscaped) {
|
||||
str += '\\';
|
||||
*str += '\\';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
isEscaped = true;
|
||||
@ -219,57 +242,61 @@ namespace ICodeASM {
|
||||
|
||||
case 't':
|
||||
if (isEscaped) {
|
||||
str += '\t';
|
||||
*str += '\t';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
str += 't';
|
||||
*str += 't';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (isEscaped) {
|
||||
str += '\n';
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
str += 'n';
|
||||
*str += 'n';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (isEscaped) {
|
||||
str += '\r';
|
||||
*str += '\r';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
str += 'r';
|
||||
*str += 'r';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (isEscaped) {
|
||||
str += '\r';
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
/* unescaped newline == unterminated string */
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
|
||||
case delim:
|
||||
if (isEscaped) {
|
||||
str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
break scan_loop;
|
||||
case '\'':
|
||||
case '"':
|
||||
if (*curpos == delim) {
|
||||
if (isEscaped) {
|
||||
*str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
isEscaped = false;
|
||||
str += *curpos;
|
||||
*str += *curpos;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (!isTerminated)
|
||||
{
|
||||
@ -282,51 +309,31 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseStatement (iter begin, iter end)
|
||||
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected an alphanumeric token (like maybe an instruction or an opcode.)");
|
||||
|
||||
scan_loop:
|
||||
for (iter curpos = tl.begin; curpos < end; ++curpos) {
|
||||
/* XXX add overflow checking */
|
||||
uint32 position = 0;
|
||||
iter curpos;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ':':
|
||||
tl.type = ttLabel;
|
||||
tl.end = ++curpos;
|
||||
break scan_loop;
|
||||
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
case '_':
|
||||
position++;
|
||||
break;
|
||||
|
||||
default:
|
||||
tl.type = ttInstruction;
|
||||
tl.end = curpos;
|
||||
break scan_loop;
|
||||
goto scan_done;
|
||||
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (tl.type = ttUndetermined) {
|
||||
tl.type = ttInstruction;
|
||||
tl.end = end;
|
||||
}
|
||||
|
||||
if (tl.type == ttLabel) {
|
||||
string label_str(tl.begin, tl.end - 1); /* ignore the trailing : */
|
||||
mLabels[label_str] = mStatementNodes.end();
|
||||
return tl.end;
|
||||
} else if (tl.type == ttInstruction) {
|
||||
string icode_str(tl.begin, tl.end);
|
||||
for (uint i = 0; i < icodemap_size; ++i)
|
||||
if (icode_str.compare(icodemap[i]) == 0)
|
||||
return ParseInstruction (i, tl.end, end);
|
||||
throw ("Unknown ICode " + icode_str);
|
||||
}
|
||||
curpos = begin;
|
||||
for (; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * static_cast<uint32>(pow (10, position));
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter ICodeParser::ParseInstruction (uint icodeID, iter start, iter end)
|
||||
@ -370,16 +377,63 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseArgumentListOperand (iter begin, iter end,
|
||||
AnyOperand *rval)
|
||||
ICodeParser::ParseStatement (iter begin, iter end)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected an alphanumeric token (like maybe an instruction or a label.)");
|
||||
|
||||
for (iter curpos = tl.begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ':':
|
||||
tl.type = ttLabel;
|
||||
tl.end = ++curpos;
|
||||
goto scan_done;
|
||||
|
||||
case 'a'...'z':
|
||||
case 'A'...'Z':
|
||||
case '0'...'9':
|
||||
case '_':
|
||||
break;
|
||||
|
||||
default:
|
||||
tl.type = ttInstruction;
|
||||
tl.end = curpos;
|
||||
goto scan_done;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (tl.type = ttUndetermined) {
|
||||
tl.type = ttInstruction;
|
||||
tl.end = end;
|
||||
}
|
||||
|
||||
if (tl.type == ttLabel) {
|
||||
string label_str(tl.begin, tl.end - 1); /* ignore the trailing : */
|
||||
mLabels[label_str] = mStatementNodes.end();
|
||||
return tl.end;
|
||||
} else if (tl.type == ttInstruction) {
|
||||
string icode_str(tl.begin, tl.end);
|
||||
for (uint i = 0; i < icodemap_size; ++i)
|
||||
if (cmp_nocase(icode_str, &icodemap[i].name[0],
|
||||
&icodemap[i].name[0] + strlen(icodemap[i].name) + 1))
|
||||
return ParseInstruction (i, tl.end, end);
|
||||
throw ("Unknown ICode " + icode_str);
|
||||
}
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseArgumentListOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
/* XXX this is hard, lets go shopping */
|
||||
ASSERT ("Not Implemented.");
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBinaryOpOperand (iter begin, iter end,
|
||||
AnyOperand *rval)
|
||||
ICodeParser::ParseBinaryOpOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
@ -387,9 +441,35 @@ namespace ICodeASM {
|
||||
throw new ICodeParseException ("Expected BinaryOp as a quoted string.");
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, str);
|
||||
rval->asString = str;
|
||||
o->asString = str;
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ParseBoolOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected boolean value.");
|
||||
|
||||
return ParseBool (tl.begin, end, &o->asBoolean);
|
||||
}
|
||||
|
||||
iter
|
||||
ParseICodeModuleOperand (iter begin, iter end, AnyOperand *o)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected ICode Module as a quoted string.");
|
||||
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, str);
|
||||
o->asString = str;
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
#include "vmtypes.h"
|
||||
|
||||
#define iter string::const_iterator
|
||||
|
||||
namespace JavaScript {
|
||||
@ -64,10 +66,10 @@ namespace ICodeASM {
|
||||
};
|
||||
|
||||
struct ICodeParseException {
|
||||
ICodeParserException (string aMsg, iter aPos = 0)
|
||||
: msg(aMsg), pos(aPos) {}
|
||||
ICodeParseException (string aMsg, iter aPos = 0)
|
||||
: msg(aMsg), pos(aPos) {}
|
||||
string msg;
|
||||
iter aPos;
|
||||
iter pos;
|
||||
};
|
||||
|
||||
struct TokenLocation {
|
||||
@ -82,32 +84,34 @@ namespace ICodeASM {
|
||||
/* eww */
|
||||
double asDouble;
|
||||
uint32 asUInt32;
|
||||
Register asRegister;
|
||||
VM::Register asRegister;
|
||||
bool asBool;
|
||||
ArgumentList *asArgumentList;
|
||||
VM::ArgumentList *asArgumentList;
|
||||
string *asString;
|
||||
};
|
||||
|
||||
struct StatementNode {
|
||||
uint icodeID;
|
||||
AnyOperand operand[3];
|
||||
}
|
||||
};
|
||||
|
||||
class ICodeParser
|
||||
{
|
||||
private:
|
||||
uint mMaxRegister;
|
||||
std::vector<StatementNode *> mStatementNodes;
|
||||
std::map<string *, uint32> mLabels;
|
||||
std::map<string, StatementNode **> mLabels;
|
||||
|
||||
public:
|
||||
void ParseSourceFromString (const string source);
|
||||
TokenLocation SeekTokenStart (iter begin, iter end);
|
||||
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
|
||||
iter ParseDouble (iter begin, iter end, double *rval);
|
||||
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 ParseStatement (iter begin, iter end);
|
||||
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
|
||||
|
||||
iter ParseInstruction (uint icodeID, iter start, iter end);
|
||||
|
||||
iter ParseArgumentListOperand (iter begin, iter end, AnyOperand *o);
|
||||
|
@ -33,11 +33,14 @@
|
||||
|
||||
/* most of this file will get auto-generated from the icode metadata */
|
||||
|
||||
#include "systemtypes.h"
|
||||
|
||||
enum OperandType {
|
||||
otNone = 0,
|
||||
otArgumentList,
|
||||
otBinaryOp,
|
||||
otBool,
|
||||
otDouble,
|
||||
otICodeModule,
|
||||
otJSClass,
|
||||
otJSString,
|
||||
@ -53,12 +56,12 @@ static uint icodemap_size = 5;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
OperandType otype[3];
|
||||
} icode_map [icodemap_size] =
|
||||
OperandType otype[4];
|
||||
} icodemap [] =
|
||||
{
|
||||
{"LOAD_STRING", {otRegister, otString}},
|
||||
{"CAST", {otRegister, otRegister, otType}},
|
||||
{"SAVE_NAME", {otString, otRegister}},
|
||||
{"CALL", {otRegister, otRegister, otRegister, otRegisterList}},
|
||||
{"LOAD_STRING", {otRegister, otStringAtom}},
|
||||
{"CAST", {otRegister, otRegister, otJSType}},
|
||||
{"SAVE_NAME", {otJSString, otRegister}},
|
||||
{"CALL", {otRegister, otRegister, otRegister, otArgumentList}},
|
||||
{"RETURN", {otRegister}}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user