refactored lexer bits from icodeasm into lexutils
refactored exceptions from icodeasm into exception* fixed LeadingCap method names to be interCapped added string8 and string16 typedefs (as opposed to string vs String) git-svn-id: svn://10.0.0.236/trunk@82601 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
7995becc53
commit
37eb1a8437
@ -30,7 +30,10 @@ test_objs = hash.o \
|
||||
world.o \
|
||||
vmtypes.o \
|
||||
xmlparser.o \
|
||||
debugger.o
|
||||
debugger.o \
|
||||
exception.o \
|
||||
exception_msgs.o \
|
||||
lexutils.o
|
||||
|
||||
gc_path = ../../gc/boehm/
|
||||
|
||||
|
||||
51
mozilla/js/js2/exception.cpp
Normal file
51
mozilla/js/js2/exception.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- 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 "exception.h"
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
extern const char* exception_types[];
|
||||
extern const char* exception_msgs[];
|
||||
|
||||
void
|
||||
JSException::toString8 (string8 &rval)
|
||||
{
|
||||
rval = *exception_types[mType] + " Exception: " +
|
||||
*exception_msgs[mID];
|
||||
if (mSource.size() != 0)
|
||||
rval += " in " + mSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
115
mozilla/js/js2/exception.h
Normal file
115
mozilla/js/js2/exception.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#ifndef exception_h___
|
||||
#define exception_h___
|
||||
#include "utilities.h"
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
enum ExceptionType {
|
||||
etUnknown = 0,
|
||||
etLexer,
|
||||
etParser,
|
||||
etRuntime,
|
||||
etCount
|
||||
};
|
||||
|
||||
enum ExceptionID {
|
||||
eidExpectBool = 0,
|
||||
eidExpectDouble,
|
||||
eidExpectInt32,
|
||||
eidExpectUInt32,
|
||||
eidExpectRegister,
|
||||
eidExpectArgList,
|
||||
eidExpectColon,
|
||||
eidExpectCloseParen,
|
||||
eidExpectBinaryOp,
|
||||
eidExpectString,
|
||||
eidExpectLabel,
|
||||
eidExpectComma,
|
||||
eidExpectNewline,
|
||||
eidExpectIdentifier,
|
||||
eidDuplicateLabel,
|
||||
eidUnknownICode,
|
||||
eidUnknownBinaryOp,
|
||||
eidUnterminatedString,
|
||||
eidCount
|
||||
};
|
||||
|
||||
class JSException {
|
||||
public:
|
||||
JSException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0, ExceptionType type = etUnknown)
|
||||
: mID(ID), mType(type), mPos(pos), mSource(source) {}
|
||||
ExceptionID mID;
|
||||
ExceptionType mType;
|
||||
string8_citer mPos;
|
||||
string8 mSource;
|
||||
|
||||
public:
|
||||
void toString8(string8 &rval);
|
||||
/*
|
||||
private:
|
||||
JSException(const JSException&);
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
class JSLexException : public JSException {
|
||||
public:
|
||||
JSLexException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = "") :
|
||||
JSException(ID, pos, source, etLexer) {}
|
||||
/*
|
||||
private:
|
||||
JSLexException (const JSLexException&);
|
||||
*/
|
||||
};
|
||||
|
||||
class JSParseException : public JSException {
|
||||
public:
|
||||
JSParseException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0) :
|
||||
JSException(ID, pos, source, etParser) {}
|
||||
/*
|
||||
private:
|
||||
JSParseException (const JSParseException&);
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* exception_h___ */
|
||||
|
||||
|
||||
66
mozilla/js/js2/exception_msgs.cpp
Normal file
66
mozilla/js/js2/exception_msgs.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
const char* exception_types[] = {
|
||||
"Unknown",
|
||||
"Lexer",
|
||||
"Parser",
|
||||
"Runtime",
|
||||
0
|
||||
};
|
||||
|
||||
const char* exception_msgs[] = {
|
||||
"Expected boolean value",
|
||||
"Expected double value",
|
||||
"Expected int32 value",
|
||||
"Expected uint32 value",
|
||||
"Expected register value",
|
||||
"Expected argument list value",
|
||||
"Expected colon",
|
||||
"Expected close parenthesis",
|
||||
"Expected binary operator",
|
||||
"Expected string",
|
||||
"Expected label",
|
||||
"Expected comma",
|
||||
"Expected newline",
|
||||
"Expected identifier",
|
||||
"Duplicate label",
|
||||
"Unknown icode",
|
||||
"Unknown binary operator",
|
||||
"Unterminated string literal",
|
||||
0
|
||||
};
|
||||
|
||||
}
|
||||
@ -36,16 +36,16 @@
|
||||
|
||||
#include "utilities.h"
|
||||
#include "icodegenerator.h"
|
||||
#include "lexutils.h"
|
||||
#include "icodeasm.h"
|
||||
|
||||
using namespace JavaScript;
|
||||
|
||||
void
|
||||
testAlpha (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
const string &expect)
|
||||
testAlpha (const string8 &str, const string &expect)
|
||||
{
|
||||
string *result;
|
||||
icp.ParseAlpha (str.begin(), str.end(), &result);
|
||||
LexUtils::lexAlpha (str.begin(), str.end(), &result);
|
||||
if (*result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -55,11 +55,10 @@ testAlpha (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testBool (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
bool expect)
|
||||
testBool (const string8 &str, bool expect)
|
||||
{
|
||||
bool b;
|
||||
icp.ParseBool (str.begin(), str.end(), &b);
|
||||
LexUtils::lexBool (str.begin(), str.end(), &b);
|
||||
if (b == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -68,11 +67,10 @@ testBool (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testDouble (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
double expect)
|
||||
testDouble (const string8 &str, double expect)
|
||||
{
|
||||
double result;
|
||||
icp.ParseDouble (str.begin(), str.end(), &result);
|
||||
LexUtils::lexDouble (str.begin(), str.end(), &result);
|
||||
if (result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -82,11 +80,10 @@ testDouble (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testString (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
const string &expect)
|
||||
testString (const string8 &str, const string &expect)
|
||||
{
|
||||
string *result;
|
||||
icp.ParseString (str.begin(), str.end(), &result);
|
||||
LexUtils::lexString8 (str.begin(), str.end(), &result);
|
||||
if (*result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -96,11 +93,10 @@ testString (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testUInt32 (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
uint32 expect)
|
||||
testUInt32 (const string8 &str, uint32 expect)
|
||||
{
|
||||
uint32 result;
|
||||
icp.ParseUInt32 (str.begin(), str.end(), &result);
|
||||
LexUtils::lexUInt32 (str.begin(), str.end(), &result);
|
||||
if (result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -116,11 +112,12 @@ testParse (JavaScript::ICodeASM::ICodeParser &icp,
|
||||
{
|
||||
using namespace JavaScript;
|
||||
|
||||
icp.ParseSourceFromString (str);
|
||||
icp.parseSourceFromString (str);
|
||||
ICG::ICodeModule icm = ICG::ICodeModule (icp.mInstructions,
|
||||
new ICG::VariableList(),
|
||||
icp.mMaxRegister, 0, 0, false,
|
||||
false, &JSTypes::Any_Type);
|
||||
new ICG::ParameterList(),
|
||||
icp.mMaxRegister, 0,
|
||||
&JSTypes::Any_Type);
|
||||
|
||||
stdOut << icm;
|
||||
|
||||
@ -153,36 +150,36 @@ main (int , char **)
|
||||
Interpreter::Context cx (world, &global);
|
||||
ICodeASM::ICodeParser icp(&cx);
|
||||
|
||||
testAlpha (icp, "False", "False");
|
||||
testAlpha (icp, "fe fi fo fum", "fe");
|
||||
testAlpha (icp, " bla", "");
|
||||
testAlpha ("False", "False");
|
||||
testAlpha ("fe fi fo fum", "fe");
|
||||
testAlpha (" bla", "");
|
||||
|
||||
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);
|
||||
testBool ("true", true);
|
||||
testBool ("True", true);
|
||||
testBool ("tRue", true);
|
||||
testBool ("TRUE", true);
|
||||
testBool ("True", true);
|
||||
testBool ("false", false);
|
||||
testBool ("False", false);
|
||||
testBool ("fAlSe", false);
|
||||
testBool ("FALSE", false);
|
||||
testBool ("False", false);
|
||||
|
||||
testDouble (icp, "123", 123);
|
||||
testDouble (icp, "12.3", 12.3);
|
||||
testDouble (icp, "-123", -123);
|
||||
testDouble (icp, "-12.3", -12.3);
|
||||
testDouble ("123", 123);
|
||||
testDouble ("12.3", 12.3);
|
||||
testDouble ("-123", -123);
|
||||
testDouble ("-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");
|
||||
testString ("\"fe fi fo fum\"", "fe fi fo fum");
|
||||
testString ("'the tab is ->\\t<- here'", "the tab is ->\t<- here");
|
||||
testString ("'the newline is ->\\n<- here'", "the newline is ->\n<- here");
|
||||
testString ("'the cr is ->\\r<- here'", "the cr is ->\r<- here");
|
||||
testString ("\"an \\\"escaped\\\" string\"", "an \"escaped\" string");
|
||||
|
||||
testUInt32 (icp, "123", 123);
|
||||
testUInt32 (icp, "12.3", 12);
|
||||
testUInt32 (icp, "-123", 0);
|
||||
testUInt32 (icp, "-12.3", 0);
|
||||
testUInt32 ("123", 123);
|
||||
testUInt32 ("12.3", 12);
|
||||
testUInt32 ("-123", 0);
|
||||
testUInt32 ("-12.3", 0);
|
||||
/* XXX what to do with the overflow? */
|
||||
//testUInt32 (icp, "12123687213612873621873438754387934657834", 0);
|
||||
|
||||
|
||||
@ -35,9 +35,14 @@
|
||||
|
||||
#include "icodeasm.h"
|
||||
#include "icodemap.h"
|
||||
#include "utilities.h"
|
||||
#include "lexutils.h"
|
||||
#include "exception.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace ICodeASM {
|
||||
using namespace LexUtils;
|
||||
|
||||
static char *keyword_offset = "offset";
|
||||
static char *keyword_binaryops[] = {"add", "subtract", "multiply", "divide",
|
||||
"remainder", "leftshift", "rightshift",
|
||||
@ -45,33 +50,12 @@ namespace ICodeASM {
|
||||
"bitwisexor", "bitwiseand", "less",
|
||||
"lessorequal", "equal", "identical", 0};
|
||||
|
||||
#define IS_ALPHA(ch) ((ch >= 'a' && ch <= 'z') || \
|
||||
(ch >= 'A' && ch <= 'Z') || \
|
||||
(ch == '_'))
|
||||
#define IS_NUMBER(ch) (ch >= '0' && ch <= '9')
|
||||
|
||||
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 - 1;
|
||||
|
||||
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 (const string &source)
|
||||
ICodeParser::parseSourceFromString (const string8 &source)
|
||||
{
|
||||
uint statementNo = 0;
|
||||
iter begin = source.begin();
|
||||
iter end = source.end();
|
||||
string8_citer begin = source.begin();
|
||||
string8_citer end = source.end();
|
||||
|
||||
mInstructions = new VM::InstructionStream();
|
||||
mMaxRegister = 0;
|
||||
@ -84,13 +68,15 @@ namespace ICodeASM {
|
||||
try
|
||||
{
|
||||
++statementNo;
|
||||
begin = ParseNextStatement (begin, end);
|
||||
begin = parseNextStatement (begin, end);
|
||||
}
|
||||
catch (ICodeParseException *e)
|
||||
catch (JSException &e)
|
||||
{
|
||||
fprintf (stderr, "Parse Error: %s at statement %u\n",
|
||||
e->msg.c_str(), statementNo);
|
||||
delete e;
|
||||
string8 etext;
|
||||
e.toString8(etext);
|
||||
|
||||
fprintf (stderr, "%s at statement %u\n",
|
||||
etext.c_str(), statementNo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -99,394 +85,47 @@ namespace ICodeASM {
|
||||
NOT_REACHED ("Overran source buffer!");
|
||||
}
|
||||
|
||||
TokenLocation
|
||||
ICodeParser::SeekTokenStart (iter begin, iter end)
|
||||
{
|
||||
TokenLocation tl;
|
||||
iter curpos;
|
||||
bool inComment = false;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (!inComment) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
/* look past the whitespace */
|
||||
break;
|
||||
|
||||
case ';':
|
||||
inComment = true;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
tl.estimate = teNewline;
|
||||
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;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '<':
|
||||
tl.estimate = teNotARegister;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '(':
|
||||
tl.estimate = teOpenParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ')':
|
||||
tl.estimate = teCloseParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ':':
|
||||
tl.estimate = teColon;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
default:
|
||||
if (IS_ALPHA(*curpos)) {
|
||||
tl.estimate = teAlpha;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else if (IS_NUMBER(*curpos)) {
|
||||
tl.estimate = teNumeric;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else {
|
||||
tl.estimate = teUnknown;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
} else if (*curpos == '\n') {
|
||||
tl.estimate = teNewline;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
|
||||
tl.begin = curpos;
|
||||
tl.estimate = teEOF;
|
||||
return tl;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* general purpose parse functions (see comment in the .h file) ...
|
||||
*/
|
||||
|
||||
iter
|
||||
ICodeParser::ParseAlpha (iter begin, iter end, string **rval)
|
||||
{
|
||||
iter curpos;
|
||||
string *str = new string();
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_ALPHA(*curpos))
|
||||
*str += *curpos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBool (iter begin, iter end, bool *rval)
|
||||
{
|
||||
iter curpos = begin;
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
int32 position = 0;
|
||||
|
||||
for (; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
*rval += (*curpos - '0') * (1 / pow (10, ++position));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval *= sign;
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
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;
|
||||
}
|
||||
|
||||
uint32 i;
|
||||
end = ParseUInt32 (begin, end, &i);
|
||||
|
||||
*rval = i * sign;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseRegister (iter begin, iter end, JSTypes::Register *rval)
|
||||
{
|
||||
if (*begin == 'R' || *begin == 'r') {
|
||||
if (++begin != end) {
|
||||
try
|
||||
{
|
||||
end = ParseUInt32 (begin, end, static_cast<uint32 *>(rval));
|
||||
if (*rval != VM::NotARegister && *rval > mMaxRegister)
|
||||
mMaxRegister = *rval;
|
||||
return end;
|
||||
}
|
||||
catch (ICodeParseException *e)
|
||||
{
|
||||
/* rethrow as an "expected register" in fall through case */
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
} else if (*begin == '<') {
|
||||
if ((++begin != end) && (*begin == 'N' || *begin == 'n'))
|
||||
if ((++begin != end) && (*begin == 'A' || *begin == 'a'))
|
||||
if ((++begin != end) && (*begin == 'R' || *begin == 'r'))
|
||||
if ((++begin != end) && *begin == '>') {
|
||||
*rval = VM::NotARegister;
|
||||
return ++begin;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ICodeParseException ("Expected Register value");
|
||||
}
|
||||
|
||||
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 != '"') {
|
||||
NOT_REACHED ("|begin| does not point at a string");
|
||||
delete str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
iter curpos = 0;
|
||||
bool isEscaped = false;
|
||||
for (curpos = ++begin; curpos < end; ++curpos) {
|
||||
|
||||
switch (*curpos) {
|
||||
case '\\':
|
||||
if (isEscaped) {
|
||||
*str += '\\';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
isEscaped = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (isEscaped) {
|
||||
*str += '\t';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 't';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'n';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (isEscaped) {
|
||||
*str += '\r';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'r';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
/* unescaped newline == unterminated string */
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '"':
|
||||
if (*curpos == delim) {
|
||||
if (isEscaped) {
|
||||
*str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
isEscaped = false;
|
||||
*str += *curpos;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (!isTerminated)
|
||||
{
|
||||
delete str;
|
||||
throw new ICodeParseException ("Unterminated string literal");
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
|
||||
{
|
||||
/* XXX add overflow checking */
|
||||
*rval = 0;
|
||||
int32 position = -1;
|
||||
iter curpos;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
position++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (curpos = begin; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * static_cast<uint32>(pow (10, position));
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* operand parse functions (see comment in the .h file) ...
|
||||
*/
|
||||
|
||||
iter
|
||||
ICodeParser::ParseArgumentListOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseArgumentListOperand (string8_citer begin,
|
||||
string8_citer end,
|
||||
VM::ArgumentList **rval)
|
||||
{
|
||||
/* parse argument list on the format "(['argname': ]register[, ...])" */
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
VM::ArgumentList *al = new VM::ArgumentList();
|
||||
|
||||
if (tl.estimate != teOpenParen)
|
||||
throw new ICodeParseException ("Expected Argument List");
|
||||
throw JSParseException (eidExpectArgList);
|
||||
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
while (tl.estimate == teString || tl.estimate == teAlpha) {
|
||||
string *argName = 0;
|
||||
|
||||
if (tl.estimate == teString) {
|
||||
/* look for the argname in quotes */
|
||||
begin = ParseString (tl.begin, end, &argName);
|
||||
begin = lexString8 (tl.begin, end, &argName);
|
||||
|
||||
/* look for the : */
|
||||
tl = SeekTokenStart (begin, end);
|
||||
tl = seekTokenStart (begin, end);
|
||||
if (tl.estimate != teColon)
|
||||
throw new ICodeParseException ("Expected colon");
|
||||
throw JSParseException (eidExpectColon);
|
||||
|
||||
/* and now the register */
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
}
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected Register value");
|
||||
throw JSParseException (eidExpectRegister);
|
||||
|
||||
JSTypes::Register r;
|
||||
begin = ParseRegister (tl.begin, end, &r);
|
||||
begin = lexRegister (tl.begin, end, &r);
|
||||
if (r != VM::NotARegister && r > mMaxRegister)
|
||||
mMaxRegister = r;
|
||||
|
||||
/* pass 0 (null) as the "type" because it is
|
||||
* not actually used by the interpreter, only in (the current)
|
||||
* codegen (acording to rogerl.)
|
||||
@ -502,32 +141,32 @@ namespace ICodeASM {
|
||||
|
||||
al->push_back(arg);
|
||||
|
||||
tl = SeekTokenStart (begin, end);
|
||||
tl = seekTokenStart (begin, end);
|
||||
/* if the next token is a comma,
|
||||
* seek to the next one and go again */
|
||||
if (tl.estimate == teComma) {
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
}
|
||||
}
|
||||
|
||||
if (tl.estimate != teCloseParen)
|
||||
throw new ICodeParseException ("Expected close paren");
|
||||
throw JSParseException (eidExpectCloseParen);
|
||||
|
||||
*rval = al;
|
||||
|
||||
return tl.begin + 1;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBinaryOpOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseBinaryOpOperand (string8_citer begin, string8_citer end,
|
||||
VM::BinaryOperator::BinaryOp *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected BinaryOp");
|
||||
string *str;
|
||||
end = ParseAlpha (tl.begin, end, &str);
|
||||
throw JSParseException (eidExpectBinaryOp);
|
||||
string8 *str;
|
||||
end = lexAlpha (tl.begin, end, &str);
|
||||
|
||||
for (int i = 0; keyword_binaryops[i] != 0; ++i)
|
||||
if (cmp_nocase (*str, keyword_binaryops[i], keyword_binaryops[i] +
|
||||
@ -538,105 +177,85 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
delete str;
|
||||
throw new ICodeParseException ("Unknown BinaryOp");
|
||||
throw JSParseException (eidUnknownBinaryOp);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBoolOperand (iter begin, iter end, bool *rval)
|
||||
string8_citer
|
||||
ICodeParser::parseBoolOperand (string8_citer begin, string8_citer end,
|
||||
bool *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected boolean value");
|
||||
throw JSParseException (eidExpectBool);
|
||||
|
||||
return ParseBool (tl.begin, end, rval);
|
||||
return lexBool (tl.begin, end, rval);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseDoubleOperand (iter begin, iter end, double *rval)
|
||||
string8_citer
|
||||
ICodeParser::parseDoubleOperand (string8_citer begin, string8_citer end,
|
||||
double *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if ((tl.estimate != teNumeric) && (tl.estimate != teMinus) &&
|
||||
(tl.estimate != tePlus))
|
||||
throw new ICodeParseException ("Expected double value");
|
||||
throw JSParseException (eidExpectDouble);
|
||||
|
||||
return ParseDouble (tl.begin, end, rval);
|
||||
return lexDouble (tl.begin, end, rval);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseICodeModuleOperand (iter /*begin*/, iter end, string ** /*rval*/)
|
||||
string8_citer
|
||||
ICodeParser::parseICodeModuleOperand (string8_citer /*begin*/,
|
||||
string8_citer end, string ** /*rval*/)
|
||||
{
|
||||
NOT_REACHED ("ICode modules are hard, lets go shopping.");
|
||||
return end;
|
||||
/*
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected ICode Module as a quoted string");
|
||||
|
||||
return ParseString (tl.begin, end, rval);
|
||||
*/
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSClassOperand (iter /*begin*/, iter end,
|
||||
string ** /*rval*/)
|
||||
string8_citer
|
||||
ICodeParser::parseJSClassOperand (string8_citer /*begin*/,
|
||||
string8_citer end, string ** /*rval*/)
|
||||
{
|
||||
NOT_REACHED ("JSClasses are hard, lets go shopping.");
|
||||
return end;
|
||||
|
||||
/*
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected JSClass as a quoted string");
|
||||
return ParseString (tl.begin, end, rval);
|
||||
*/
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSStringOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseJSStringOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSString **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
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);
|
||||
throw JSParseException (eidExpectString);
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
*rval = new JSTypes::JSString (str->c_str());
|
||||
delete str;
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSFunctionOperand (iter /*begin*/, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseJSFunctionOperand (string8_citer /*begin*/,
|
||||
string8_citer end,
|
||||
string ** /*rval*/)
|
||||
{
|
||||
NOT_REACHED ("JSFunctions are hard, lets go shopping.");
|
||||
return end;
|
||||
|
||||
/*
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected JSFunction as a quoted string");
|
||||
return ParseString (tl.begin, end, rval);
|
||||
*/
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSTypeOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseJSTypeOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSType **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected JSType as a quoted string");
|
||||
throw JSParseException (eidExpectString);
|
||||
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, &str);
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
StringAtom &typename_atom = mCx->getWorld().identifiers[str->c_str()];
|
||||
delete str;
|
||||
JSTypes::JSValue jsv =
|
||||
@ -649,29 +268,30 @@ namespace ICodeASM {
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseLabelOperand (iter begin, iter end, VM::Label **rval)
|
||||
string8_citer
|
||||
ICodeParser::parseLabelOperand (string8_citer begin, string8_citer end,
|
||||
VM::Label **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected Label Identifier or Offset keyword");
|
||||
throw JSParseException (eidExpectLabel);
|
||||
|
||||
string *str;
|
||||
begin = ParseAlpha (tl.begin, end, &str);
|
||||
string8 *str;
|
||||
begin = lexAlpha (tl.begin, end, &str);
|
||||
|
||||
if (cmp_nocase(*str, keyword_offset, keyword_offset +
|
||||
strlen(keyword_offset) + 1) == 0) {
|
||||
delete str;
|
||||
/* got the "Offset" keyword, treat next thing as a jump offset
|
||||
* expressed as "Offset +/-N" */
|
||||
tl = SeekTokenStart (begin, end);
|
||||
tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teNumeric)
|
||||
throw new ICodeParseException ("Expected numeric value after Offset keyword");
|
||||
throw JSParseException (eidExpectUInt32);
|
||||
|
||||
uint32 ofs;
|
||||
begin = ParseUInt32 (tl.begin, end, &ofs);
|
||||
begin = lexUInt32 (tl.begin, end, &ofs);
|
||||
VM::Label *new_label = new VM::Label(mInstructions);
|
||||
new_label->mOffset = ofs;
|
||||
mLabels.push_back (new_label);
|
||||
@ -697,44 +317,52 @@ namespace ICodeASM {
|
||||
return begin;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseUInt32Operand (iter begin, iter end, uint32 *rval)
|
||||
string8_citer
|
||||
ICodeParser::parseUInt32Operand (string8_citer begin,
|
||||
string8_citer end, uint32 *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teNumeric)
|
||||
throw new ICodeParseException ("Expected UInt32 value");
|
||||
throw JSParseException (eidExpectUInt32);
|
||||
|
||||
return ParseUInt32 (tl.begin, end, rval);
|
||||
return lexUInt32 (tl.begin, end, rval);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseRegisterOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseRegisterOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
return ParseRegister (tl.begin, end, rval);
|
||||
end = lexRegister (tl.begin, end, rval);
|
||||
if (*rval != VM::NotARegister && *rval > mMaxRegister)
|
||||
mMaxRegister = *rval;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseStringAtomOperand (iter begin, iter end, StringAtom **rval)
|
||||
string8_citer
|
||||
ICodeParser::parseStringAtomOperand (string8_citer begin, string8_citer end,
|
||||
StringAtom **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected StringAtom as a quoted string");
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, &str);
|
||||
throw JSParseException (eidExpectString);
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
*rval = &(mCx->getWorld().identifiers[str->c_str()]);
|
||||
delete str;
|
||||
return end;
|
||||
}
|
||||
|
||||
/* "High Level" parse functions ... */
|
||||
iter ICodeParser::ParseInstruction (uint icodeID, iter begin, iter end)
|
||||
string8_citer
|
||||
ICodeParser::parseInstruction (uint icodeID, string8_citer begin,
|
||||
string8_citer end)
|
||||
{
|
||||
iter curpos = begin;
|
||||
string8_citer curpos = begin;
|
||||
StatementNode node;
|
||||
node.icodeID = icodeID;
|
||||
|
||||
@ -743,7 +371,7 @@ namespace ICodeASM {
|
||||
{ \
|
||||
C rval; \
|
||||
node.operand[i].type = ot##T; \
|
||||
curpos = Parse##T##Operand (curpos, end, &rval); \
|
||||
curpos = parse##T##Operand (curpos, end, &rval); \
|
||||
node.operand[i].data = CTYPE<int64>(rval); \
|
||||
break; \
|
||||
}
|
||||
@ -773,10 +401,10 @@ namespace ICodeASM {
|
||||
if (i != 3 && icodemap[icodeID].otype[i + 1] != otNone) {
|
||||
/* if the instruction has more arguments, eat a comma and
|
||||
* locate the next token */
|
||||
TokenLocation tl = SeekTokenStart (curpos, end);
|
||||
TokenLocation tl = seekTokenStart (curpos, end);
|
||||
if (tl.estimate != teComma)
|
||||
throw new ICodeParseException ("Expected comma");
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
throw JSParseException (eidExpectComma);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
curpos = tl.begin;
|
||||
}
|
||||
}
|
||||
@ -786,9 +414,9 @@ namespace ICodeASM {
|
||||
mInstructions->push_back (InstructionFromNode(&node));
|
||||
++mInstructionCount;
|
||||
|
||||
TokenLocation tl = SeekTokenStart (curpos, end);
|
||||
TokenLocation tl = seekTokenStart (curpos, end);
|
||||
if (tl.estimate != teNewline && tl.estimate != teEOF)
|
||||
throw new ICodeParseException ("Expected newline");
|
||||
throw JSParseException (eidExpectNewline);
|
||||
|
||||
if (tl.estimate == teEOF)
|
||||
return tl.begin;
|
||||
@ -796,12 +424,12 @@ namespace ICodeASM {
|
||||
return tl.begin + 1;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseNextStatement (iter begin, iter end)
|
||||
string8_citer
|
||||
ICodeParser::parseNextStatement (string8_citer begin, string8_citer end)
|
||||
{
|
||||
bool isLabel = false;
|
||||
iter firstTokenEnd = end;
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
string8_citer firstTokenEnd = end;
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate == teNewline) {
|
||||
/* empty statement, do nothing */
|
||||
@ -809,9 +437,9 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected alphanumeric token");
|
||||
throw JSParseException (eidExpectIdentifier);
|
||||
|
||||
for (iter curpos = tl.begin; curpos < end; ++curpos) {
|
||||
for (string8_citer curpos = tl.begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ':':
|
||||
@ -831,7 +459,7 @@ namespace ICodeASM {
|
||||
if (isLabel) {
|
||||
/* the thing we scanned was a label...
|
||||
* ignore the trailing : */
|
||||
string label_str(tl.begin, firstTokenEnd - 1);
|
||||
string8 label_str(tl.begin, firstTokenEnd - 1);
|
||||
/* check to see if it was already referenced... */
|
||||
LabelMap::const_iterator l = mNamedLabels.find(label_str.c_str());
|
||||
if (l == mNamedLabels.end()) {
|
||||
@ -848,26 +476,25 @@ namespace ICodeASM {
|
||||
(*l).second->mOffset = mInstructionCount;
|
||||
} else {
|
||||
/* offset was already set, this must be a dupe! */
|
||||
throw new ICodeParseException ("Duplicate label");
|
||||
throw JSParseException (eidDuplicateLabel);
|
||||
}
|
||||
}
|
||||
return firstTokenEnd;
|
||||
} else {
|
||||
/* the thing we scanned was an instruction, search the icode map
|
||||
* for a matching instruction */
|
||||
string icode_str(tl.begin, firstTokenEnd);
|
||||
string8 icode_str(tl.begin, firstTokenEnd);
|
||||
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) == 0)
|
||||
/* if match found, parse it's operands */
|
||||
return ParseInstruction (i, firstTokenEnd, end);
|
||||
return parseInstruction (i, firstTokenEnd, end);
|
||||
/* otherwise, choke on it */
|
||||
throw new ICodeParseException ("Unknown ICode " + icode_str);
|
||||
throw JSParseException (eidUnknownICode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,9 +37,8 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __icodeasm_h
|
||||
|
||||
#define __icodeasm_h
|
||||
#ifndef icodeasm_h___
|
||||
#define icodeasm_h___
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
@ -48,42 +47,8 @@
|
||||
#include "jstypes.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
#define iter string::const_iterator
|
||||
|
||||
namespace JavaScript {
|
||||
namespace ICodeASM {
|
||||
enum TokenEstimation {
|
||||
/* guess at tokentype, based on first character of token */
|
||||
teAlpha,
|
||||
teCloseParen,
|
||||
teComma,
|
||||
teColon,
|
||||
teEOF,
|
||||
teIllegal,
|
||||
teMinus,
|
||||
teNewline,
|
||||
teNotARegister,
|
||||
teNumeric,
|
||||
teOpenParen,
|
||||
tePlus,
|
||||
teString,
|
||||
teUnknown,
|
||||
};
|
||||
|
||||
/*
|
||||
enum TokenType {
|
||||
// verified token type
|
||||
ttUndetermined,
|
||||
ttLabel,
|
||||
ttInstruction,
|
||||
ttRegister,
|
||||
ttRegisterList,
|
||||
ttNotARegister,
|
||||
ttString,
|
||||
ttNumber,
|
||||
ttOffsetKeyword
|
||||
};
|
||||
*/
|
||||
|
||||
enum OperandType {
|
||||
otNone = 0,
|
||||
@ -102,21 +67,6 @@ namespace ICodeASM {
|
||||
otStringAtom
|
||||
};
|
||||
|
||||
struct ICodeParseException {
|
||||
ICodeParseException (string aMsg, iter aPos = 0)
|
||||
: msg(aMsg), pos(aPos) {}
|
||||
string msg;
|
||||
iter pos;
|
||||
};
|
||||
|
||||
struct TokenLocation {
|
||||
TokenLocation () : begin(0), estimate(teIllegal) /*,
|
||||
type(ttUndetermined) */ {}
|
||||
iter begin;
|
||||
TokenEstimation estimate;
|
||||
// TokenType type;
|
||||
};
|
||||
|
||||
struct AnyOperand {
|
||||
OperandType type;
|
||||
int64 data;
|
||||
@ -145,24 +95,7 @@ namespace ICodeASM {
|
||||
|
||||
public:
|
||||
ICodeParser (Interpreter::Context *aCx) : mCx(aCx), mInstructions(0) {}
|
||||
void ParseSourceFromString (const string &source);
|
||||
|
||||
/* locate the beginning of the next token and take a guess at what it
|
||||
* might be */
|
||||
TokenLocation SeekTokenStart (iter begin, iter end);
|
||||
|
||||
/* 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 ParseInt32 (iter begin, iter end, int32 *rval);
|
||||
iter ParseRegister (iter begin, iter end, JSTypes::Register *rval);
|
||||
iter ParseString (iter begin, iter end, string **rval);
|
||||
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
|
||||
void parseSourceFromString (const string8 &source);
|
||||
|
||||
/* operand parse functions; These functions take care of finding
|
||||
* the start of the token with |SeekTokenStart|, and checking the
|
||||
@ -171,31 +104,56 @@ namespace ICodeASM {
|
||||
* token is found, and it is of the expected type, the actual parsing is
|
||||
* carried out by one of the general purpose parse functions.
|
||||
*/
|
||||
iter ParseArgumentListOperand (iter begin, iter end,
|
||||
VM::ArgumentList **rval);
|
||||
iter ParseBinaryOpOperand (iter begin, iter end,
|
||||
VM::BinaryOperator::BinaryOp *rval);
|
||||
iter ParseBoolOperand (iter begin, iter end, bool *rval);
|
||||
iter ParseDoubleOperand (iter begin, iter end, double *rval);
|
||||
iter ParseICodeModuleOperand (iter begin, iter end, string **rval);
|
||||
iter ParseJSClassOperand (iter begin, iter end, string **rval);
|
||||
iter ParseJSStringOperand (iter begin, iter end,
|
||||
JSTypes::JSString **rval);
|
||||
iter ParseJSFunctionOperand (iter begin, iter end, string **rval);
|
||||
iter ParseJSTypeOperand (iter begin, iter end, JSTypes::JSType **rval);
|
||||
iter ParseLabelOperand (iter begin, iter end, VM::Label **rval);
|
||||
iter ParseUInt32Operand (iter begin, iter end, uint32 *rval);
|
||||
iter ParseRegisterOperand (iter begin, iter end,
|
||||
JSTypes::Register *rval);
|
||||
iter ParseStringAtomOperand (iter begin, iter end, StringAtom **rval);
|
||||
string8_citer
|
||||
parseArgumentListOperand (string8_citer begin, string8_citer end,
|
||||
VM::ArgumentList **rval);
|
||||
string8_citer
|
||||
parseBinaryOpOperand (string8_citer begin, string8_citer end,
|
||||
VM::BinaryOperator::BinaryOp *rval);
|
||||
string8_citer
|
||||
parseBoolOperand (string8_citer begin, string8_citer end,
|
||||
bool *rval);
|
||||
string8_citer
|
||||
parseDoubleOperand (string8_citer begin, string8_citer end,
|
||||
double *rval);
|
||||
string8_citer
|
||||
parseICodeModuleOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSClassOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSStringOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSString **rval);
|
||||
string8_citer
|
||||
parseJSFunctionOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSTypeOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSType **rval);
|
||||
string8_citer
|
||||
parseLabelOperand (string8_citer begin, string8_citer end,
|
||||
VM::Label **rval);
|
||||
string8_citer
|
||||
parseUInt32Operand (string8_citer begin, string8_citer end,
|
||||
uint32 *rval);
|
||||
string8_citer
|
||||
parseRegisterOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval);
|
||||
string8_citer
|
||||
parseStringAtomOperand (string8_citer begin, string8_citer end,
|
||||
StringAtom **rval);
|
||||
|
||||
/* "high level" parse functions */
|
||||
iter ParseInstruction (uint icodeID, iter start, iter end);
|
||||
iter ParseNextStatement (iter begin, iter end);
|
||||
string8_citer
|
||||
parseInstruction (uint icodeID, string8_citer start,
|
||||
string8_citer end);
|
||||
string8_citer
|
||||
parseNextStatement (string8_citer begin, string8_citer end);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #ifndef __icodeasm_h */
|
||||
#endif /* #ifndef icodeasm_h___ */
|
||||
|
||||
@ -2499,7 +2499,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
stdOut << "Calling ICodeParser with :\n" << str << "\n";
|
||||
|
||||
icp.ParseSourceFromString(str);
|
||||
icp.parseSourceFromString(str);
|
||||
|
||||
ICodeModule *icm = new ICodeModule(icp.mInstructions,
|
||||
NULL, /* VariableList *variables */
|
||||
|
||||
405
mozilla/js/js2/lexutils.cpp
Normal file
405
mozilla/js/js2/lexutils.cpp
Normal file
@ -0,0 +1,405 @@
|
||||
/* -*- 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 "lexutils.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace LexUtils {
|
||||
|
||||
int cmp_nocase (const string8& s1, string8_citer s2_begin,
|
||||
string8_citer s2_end)
|
||||
{
|
||||
string8_citer p1 = s1.begin();
|
||||
string8_citer p2 = s2_begin;
|
||||
uint s2_size = s2_end - s2_begin - 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
TokenLocation
|
||||
seekTokenStart (string8_citer begin, string8_citer end)
|
||||
{
|
||||
TokenLocation tl;
|
||||
string8_citer curpos;
|
||||
bool inComment = false;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (!inComment) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
/* look past the whitespace */
|
||||
break;
|
||||
|
||||
case ';':
|
||||
inComment = true;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
tl.estimate = teNewline;
|
||||
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;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '<':
|
||||
tl.estimate = teLessThan;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '(':
|
||||
tl.estimate = teOpenParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ')':
|
||||
tl.estimate = teCloseParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ':':
|
||||
tl.estimate = teColon;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
default:
|
||||
if (IS_ALPHA(*curpos)) {
|
||||
tl.estimate = teAlpha;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else if (IS_NUMBER(*curpos)) {
|
||||
tl.estimate = teNumeric;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else {
|
||||
tl.estimate = teUnknown;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
} else if (*curpos == '\n') {
|
||||
tl.estimate = teNewline;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
|
||||
tl.begin = curpos;
|
||||
tl.estimate = teEOF;
|
||||
return tl;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* general purpose lexer functions (see comment in the .h file) ...
|
||||
*/
|
||||
|
||||
string8_citer
|
||||
lexAlpha (string8_citer begin, string8_citer end, string8 **rval)
|
||||
{
|
||||
string8_citer curpos;
|
||||
string8 *str = new string8();
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_ALPHA(*curpos))
|
||||
*str += *curpos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexBool (string8_citer begin, string8_citer end, bool *rval)
|
||||
{
|
||||
string8_citer curpos = begin;
|
||||
|
||||
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 JSLexException (eidExpectBool);
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexDouble (string8_citer begin, string8_citer 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 JSLexException (eidExpectDouble);
|
||||
begin = tl.begin;
|
||||
}
|
||||
|
||||
|
||||
string8_citer curpos = lexUInt32 (begin, end, &integer);
|
||||
*rval = static_cast<double>(integer);
|
||||
if (*curpos != '.') {
|
||||
*rval *= sign;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
++curpos;
|
||||
int32 position = 0;
|
||||
|
||||
for (; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
*rval += (*curpos - '0') * (1 / pow (10, ++position));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval *= sign;
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexInt32 (string8_citer begin, string8_citer 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 JSLexException (eidExpectInt32);
|
||||
begin = tl.begin;
|
||||
}
|
||||
|
||||
uint32 i;
|
||||
end = lexUInt32 (begin, end, &i);
|
||||
|
||||
*rval = i * sign;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexRegister (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval)
|
||||
{
|
||||
if (*begin == 'R' || *begin == 'r') {
|
||||
if (++begin != end) {
|
||||
try
|
||||
{
|
||||
end = lexUInt32 (begin, end, static_cast<uint32 *>(rval));
|
||||
return end;
|
||||
}
|
||||
catch (JSLexException &e)
|
||||
{
|
||||
/* rethrow as an "expected register" in fall through case */
|
||||
}
|
||||
}
|
||||
} else if (*begin == '<') {
|
||||
if ((++begin != end) && (*begin == 'N' || *begin == 'n'))
|
||||
if ((++begin != end) && (*begin == 'A' || *begin == 'a'))
|
||||
if ((++begin != end) && (*begin == 'R' || *begin == 'r'))
|
||||
if ((++begin != end) && *begin == '>') {
|
||||
*rval = VM::NotARegister;
|
||||
return ++begin;
|
||||
}
|
||||
}
|
||||
|
||||
throw JSLexException (eidExpectRegister);
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexString8 (string8_citer begin, string8_citer end, string8 **rval)
|
||||
{
|
||||
char delim = *begin;
|
||||
bool isTerminated = false;
|
||||
/* XXX not exactly exception safe, string may never get deleted */
|
||||
string8 *str = new string8();
|
||||
*rval = 0;
|
||||
|
||||
if (delim != '\'' && delim != '"') {
|
||||
NOT_REACHED ("|begin| does not point at a string");
|
||||
delete str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
string8_citer curpos = 0;
|
||||
bool isEscaped = false;
|
||||
for (curpos = ++begin; curpos < end; ++curpos) {
|
||||
|
||||
switch (*curpos) {
|
||||
case '\\':
|
||||
if (isEscaped) {
|
||||
*str += '\\';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
isEscaped = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (isEscaped) {
|
||||
*str += '\t';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 't';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'n';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (isEscaped) {
|
||||
*str += '\r';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'r';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
/* unescaped newline == unterminated string */
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '"':
|
||||
if (*curpos == delim) {
|
||||
if (isEscaped) {
|
||||
*str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
isEscaped = false;
|
||||
*str += *curpos;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (!isTerminated)
|
||||
{
|
||||
delete str;
|
||||
throw new JSLexException (eidUnterminatedString);
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexUInt32 (string8_citer begin, string8_citer end, uint32 *rval)
|
||||
{
|
||||
/* XXX add overflow checking */
|
||||
*rval = 0;
|
||||
int32 position = -1;
|
||||
string8_citer curpos;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
position++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (curpos = begin; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * static_cast<uint32>(pow (10, position));
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
107
mozilla/js/js2/lexutils.h
Normal file
107
mozilla/js/js2/lexutils.h
Normal file
@ -0,0 +1,107 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#ifndef lexutils_h___
|
||||
#define lexutils_h___
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
#include "utilities.h"
|
||||
#include "exception.h"
|
||||
#include "vmtypes.h"
|
||||
#include "jstypes.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace LexUtils {
|
||||
|
||||
#define IS_ALPHA(ch) ((ch >= 'a' && ch <= 'z') || \
|
||||
(ch >= 'A' && ch <= 'Z') || \
|
||||
(ch == '_'))
|
||||
#define IS_NUMBER(ch) (ch >= '0' && ch <= '9')
|
||||
|
||||
enum TokenEstimation {
|
||||
/* guess at tokentype, based on first character of token */
|
||||
teAlpha,
|
||||
teCloseParen,
|
||||
teComma,
|
||||
teColon,
|
||||
teEOF,
|
||||
teIllegal,
|
||||
teLessThan,
|
||||
teMinus,
|
||||
teNewline,
|
||||
teNumeric,
|
||||
teOpenParen,
|
||||
tePlus,
|
||||
teString,
|
||||
teUnknown,
|
||||
};
|
||||
|
||||
struct TokenLocation {
|
||||
TokenLocation () : begin(0), estimate(teIllegal) {}
|
||||
string8_citer begin;
|
||||
TokenEstimation estimate;
|
||||
};
|
||||
|
||||
/* compare, ignoring case */
|
||||
int cmp_nocase (const string8& s1, string8_citer s2_begin,
|
||||
string8_citer s2_end);
|
||||
|
||||
/* locate the beginning of the next token and take a guess at what it
|
||||
* might be */
|
||||
TokenLocation seekTokenStart (string8_citer begin, string8_citer end);
|
||||
|
||||
/* general purpose lexer functions; |begin| is expected to point
|
||||
* at the start of the token to be processed (eg, these routines
|
||||
* don't call |seekTokenStart|, and no initial check is done to ensure
|
||||
* that |begin| != |end|.
|
||||
*/
|
||||
string8_citer lexAlpha (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer lexBool (string8_citer begin, string8_citer end, bool *rval);
|
||||
string8_citer lexDouble (string8_citer begin, string8_citer end,
|
||||
double *rval);
|
||||
string8_citer lexInt32 (string8_citer begin, string8_citer end,
|
||||
int32 *rval);
|
||||
string8_citer lexRegister (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval);
|
||||
string8_citer lexString8 (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer lexUInt32 (string8_citer begin, string8_citer end,
|
||||
uint32 *rval);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* lexutils_h___ */
|
||||
@ -151,7 +151,10 @@ namespace JavaScript {
|
||||
// code bloat and separates the concepts of a fixed, read-only string from a mutable buffer that
|
||||
// is expanding. For now, though, we use the standard basic_string.
|
||||
typedef std::basic_string<char16> String;
|
||||
|
||||
typedef String string16;
|
||||
typedef string16::const_iterator string16_citer;
|
||||
typedef string string8;
|
||||
typedef string8::const_iterator string8_citer;
|
||||
|
||||
typedef uint32 char16orEOF; // A type that can hold any char16 plus one special value: ueof.
|
||||
const char16orEOF char16eof = static_cast<char16orEOF>(-1);
|
||||
|
||||
@ -30,7 +30,10 @@ test_objs = hash.o \
|
||||
world.o \
|
||||
vmtypes.o \
|
||||
xmlparser.o \
|
||||
debugger.o
|
||||
debugger.o \
|
||||
exception.o \
|
||||
exception_msgs.o \
|
||||
lexutils.o
|
||||
|
||||
gc_path = ../../gc/boehm/
|
||||
|
||||
|
||||
51
mozilla/js2/src/exception.cpp
Normal file
51
mozilla/js2/src/exception.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- 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 "exception.h"
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
extern const char* exception_types[];
|
||||
extern const char* exception_msgs[];
|
||||
|
||||
void
|
||||
JSException::toString8 (string8 &rval)
|
||||
{
|
||||
rval = *exception_types[mType] + " Exception: " +
|
||||
*exception_msgs[mID];
|
||||
if (mSource.size() != 0)
|
||||
rval += " in " + mSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
115
mozilla/js2/src/exception.h
Normal file
115
mozilla/js2/src/exception.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#ifndef exception_h___
|
||||
#define exception_h___
|
||||
#include "utilities.h"
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
enum ExceptionType {
|
||||
etUnknown = 0,
|
||||
etLexer,
|
||||
etParser,
|
||||
etRuntime,
|
||||
etCount
|
||||
};
|
||||
|
||||
enum ExceptionID {
|
||||
eidExpectBool = 0,
|
||||
eidExpectDouble,
|
||||
eidExpectInt32,
|
||||
eidExpectUInt32,
|
||||
eidExpectRegister,
|
||||
eidExpectArgList,
|
||||
eidExpectColon,
|
||||
eidExpectCloseParen,
|
||||
eidExpectBinaryOp,
|
||||
eidExpectString,
|
||||
eidExpectLabel,
|
||||
eidExpectComma,
|
||||
eidExpectNewline,
|
||||
eidExpectIdentifier,
|
||||
eidDuplicateLabel,
|
||||
eidUnknownICode,
|
||||
eidUnknownBinaryOp,
|
||||
eidUnterminatedString,
|
||||
eidCount
|
||||
};
|
||||
|
||||
class JSException {
|
||||
public:
|
||||
JSException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0, ExceptionType type = etUnknown)
|
||||
: mID(ID), mType(type), mPos(pos), mSource(source) {}
|
||||
ExceptionID mID;
|
||||
ExceptionType mType;
|
||||
string8_citer mPos;
|
||||
string8 mSource;
|
||||
|
||||
public:
|
||||
void toString8(string8 &rval);
|
||||
/*
|
||||
private:
|
||||
JSException(const JSException&);
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
class JSLexException : public JSException {
|
||||
public:
|
||||
JSLexException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = "") :
|
||||
JSException(ID, pos, source, etLexer) {}
|
||||
/*
|
||||
private:
|
||||
JSLexException (const JSLexException&);
|
||||
*/
|
||||
};
|
||||
|
||||
class JSParseException : public JSException {
|
||||
public:
|
||||
JSParseException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0) :
|
||||
JSException(ID, pos, source, etParser) {}
|
||||
/*
|
||||
private:
|
||||
JSParseException (const JSParseException&);
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* exception_h___ */
|
||||
|
||||
|
||||
66
mozilla/js2/src/exception_msgs.cpp
Normal file
66
mozilla/js2/src/exception_msgs.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
const char* exception_types[] = {
|
||||
"Unknown",
|
||||
"Lexer",
|
||||
"Parser",
|
||||
"Runtime",
|
||||
0
|
||||
};
|
||||
|
||||
const char* exception_msgs[] = {
|
||||
"Expected boolean value",
|
||||
"Expected double value",
|
||||
"Expected int32 value",
|
||||
"Expected uint32 value",
|
||||
"Expected register value",
|
||||
"Expected argument list value",
|
||||
"Expected colon",
|
||||
"Expected close parenthesis",
|
||||
"Expected binary operator",
|
||||
"Expected string",
|
||||
"Expected label",
|
||||
"Expected comma",
|
||||
"Expected newline",
|
||||
"Expected identifier",
|
||||
"Duplicate label",
|
||||
"Unknown icode",
|
||||
"Unknown binary operator",
|
||||
"Unterminated string literal",
|
||||
0
|
||||
};
|
||||
|
||||
}
|
||||
@ -36,16 +36,16 @@
|
||||
|
||||
#include "utilities.h"
|
||||
#include "icodegenerator.h"
|
||||
#include "lexutils.h"
|
||||
#include "icodeasm.h"
|
||||
|
||||
using namespace JavaScript;
|
||||
|
||||
void
|
||||
testAlpha (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
const string &expect)
|
||||
testAlpha (const string8 &str, const string &expect)
|
||||
{
|
||||
string *result;
|
||||
icp.ParseAlpha (str.begin(), str.end(), &result);
|
||||
LexUtils::lexAlpha (str.begin(), str.end(), &result);
|
||||
if (*result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -55,11 +55,10 @@ testAlpha (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testBool (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
bool expect)
|
||||
testBool (const string8 &str, bool expect)
|
||||
{
|
||||
bool b;
|
||||
icp.ParseBool (str.begin(), str.end(), &b);
|
||||
LexUtils::lexBool (str.begin(), str.end(), &b);
|
||||
if (b == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -68,11 +67,10 @@ testBool (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testDouble (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
double expect)
|
||||
testDouble (const string8 &str, double expect)
|
||||
{
|
||||
double result;
|
||||
icp.ParseDouble (str.begin(), str.end(), &result);
|
||||
LexUtils::lexDouble (str.begin(), str.end(), &result);
|
||||
if (result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -82,11 +80,10 @@ testDouble (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testString (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
const string &expect)
|
||||
testString (const string8 &str, const string &expect)
|
||||
{
|
||||
string *result;
|
||||
icp.ParseString (str.begin(), str.end(), &result);
|
||||
LexUtils::lexString8 (str.begin(), str.end(), &result);
|
||||
if (*result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -96,11 +93,10 @@ testString (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
}
|
||||
|
||||
void
|
||||
testUInt32 (JavaScript::ICodeASM::ICodeParser &icp, const string &str,
|
||||
uint32 expect)
|
||||
testUInt32 (const string8 &str, uint32 expect)
|
||||
{
|
||||
uint32 result;
|
||||
icp.ParseUInt32 (str.begin(), str.end(), &result);
|
||||
LexUtils::lexUInt32 (str.begin(), str.end(), &result);
|
||||
if (result == expect)
|
||||
fprintf (stderr, "PASS: ");
|
||||
else
|
||||
@ -116,11 +112,12 @@ testParse (JavaScript::ICodeASM::ICodeParser &icp,
|
||||
{
|
||||
using namespace JavaScript;
|
||||
|
||||
icp.ParseSourceFromString (str);
|
||||
icp.parseSourceFromString (str);
|
||||
ICG::ICodeModule icm = ICG::ICodeModule (icp.mInstructions,
|
||||
new ICG::VariableList(),
|
||||
icp.mMaxRegister, 0, 0, false,
|
||||
false, &JSTypes::Any_Type);
|
||||
new ICG::ParameterList(),
|
||||
icp.mMaxRegister, 0,
|
||||
&JSTypes::Any_Type);
|
||||
|
||||
stdOut << icm;
|
||||
|
||||
@ -153,36 +150,36 @@ main (int , char **)
|
||||
Interpreter::Context cx (world, &global);
|
||||
ICodeASM::ICodeParser icp(&cx);
|
||||
|
||||
testAlpha (icp, "False", "False");
|
||||
testAlpha (icp, "fe fi fo fum", "fe");
|
||||
testAlpha (icp, " bla", "");
|
||||
testAlpha ("False", "False");
|
||||
testAlpha ("fe fi fo fum", "fe");
|
||||
testAlpha (" bla", "");
|
||||
|
||||
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);
|
||||
testBool ("true", true);
|
||||
testBool ("True", true);
|
||||
testBool ("tRue", true);
|
||||
testBool ("TRUE", true);
|
||||
testBool ("True", true);
|
||||
testBool ("false", false);
|
||||
testBool ("False", false);
|
||||
testBool ("fAlSe", false);
|
||||
testBool ("FALSE", false);
|
||||
testBool ("False", false);
|
||||
|
||||
testDouble (icp, "123", 123);
|
||||
testDouble (icp, "12.3", 12.3);
|
||||
testDouble (icp, "-123", -123);
|
||||
testDouble (icp, "-12.3", -12.3);
|
||||
testDouble ("123", 123);
|
||||
testDouble ("12.3", 12.3);
|
||||
testDouble ("-123", -123);
|
||||
testDouble ("-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");
|
||||
testString ("\"fe fi fo fum\"", "fe fi fo fum");
|
||||
testString ("'the tab is ->\\t<- here'", "the tab is ->\t<- here");
|
||||
testString ("'the newline is ->\\n<- here'", "the newline is ->\n<- here");
|
||||
testString ("'the cr is ->\\r<- here'", "the cr is ->\r<- here");
|
||||
testString ("\"an \\\"escaped\\\" string\"", "an \"escaped\" string");
|
||||
|
||||
testUInt32 (icp, "123", 123);
|
||||
testUInt32 (icp, "12.3", 12);
|
||||
testUInt32 (icp, "-123", 0);
|
||||
testUInt32 (icp, "-12.3", 0);
|
||||
testUInt32 ("123", 123);
|
||||
testUInt32 ("12.3", 12);
|
||||
testUInt32 ("-123", 0);
|
||||
testUInt32 ("-12.3", 0);
|
||||
/* XXX what to do with the overflow? */
|
||||
//testUInt32 (icp, "12123687213612873621873438754387934657834", 0);
|
||||
|
||||
|
||||
@ -35,9 +35,14 @@
|
||||
|
||||
#include "icodeasm.h"
|
||||
#include "icodemap.h"
|
||||
#include "utilities.h"
|
||||
#include "lexutils.h"
|
||||
#include "exception.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace ICodeASM {
|
||||
using namespace LexUtils;
|
||||
|
||||
static char *keyword_offset = "offset";
|
||||
static char *keyword_binaryops[] = {"add", "subtract", "multiply", "divide",
|
||||
"remainder", "leftshift", "rightshift",
|
||||
@ -45,33 +50,12 @@ namespace ICodeASM {
|
||||
"bitwisexor", "bitwiseand", "less",
|
||||
"lessorequal", "equal", "identical", 0};
|
||||
|
||||
#define IS_ALPHA(ch) ((ch >= 'a' && ch <= 'z') || \
|
||||
(ch >= 'A' && ch <= 'Z') || \
|
||||
(ch == '_'))
|
||||
#define IS_NUMBER(ch) (ch >= '0' && ch <= '9')
|
||||
|
||||
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 - 1;
|
||||
|
||||
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 (const string &source)
|
||||
ICodeParser::parseSourceFromString (const string8 &source)
|
||||
{
|
||||
uint statementNo = 0;
|
||||
iter begin = source.begin();
|
||||
iter end = source.end();
|
||||
string8_citer begin = source.begin();
|
||||
string8_citer end = source.end();
|
||||
|
||||
mInstructions = new VM::InstructionStream();
|
||||
mMaxRegister = 0;
|
||||
@ -84,13 +68,15 @@ namespace ICodeASM {
|
||||
try
|
||||
{
|
||||
++statementNo;
|
||||
begin = ParseNextStatement (begin, end);
|
||||
begin = parseNextStatement (begin, end);
|
||||
}
|
||||
catch (ICodeParseException *e)
|
||||
catch (JSException &e)
|
||||
{
|
||||
fprintf (stderr, "Parse Error: %s at statement %u\n",
|
||||
e->msg.c_str(), statementNo);
|
||||
delete e;
|
||||
string8 etext;
|
||||
e.toString8(etext);
|
||||
|
||||
fprintf (stderr, "%s at statement %u\n",
|
||||
etext.c_str(), statementNo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -99,394 +85,47 @@ namespace ICodeASM {
|
||||
NOT_REACHED ("Overran source buffer!");
|
||||
}
|
||||
|
||||
TokenLocation
|
||||
ICodeParser::SeekTokenStart (iter begin, iter end)
|
||||
{
|
||||
TokenLocation tl;
|
||||
iter curpos;
|
||||
bool inComment = false;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (!inComment) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
/* look past the whitespace */
|
||||
break;
|
||||
|
||||
case ';':
|
||||
inComment = true;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
tl.estimate = teNewline;
|
||||
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;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '<':
|
||||
tl.estimate = teNotARegister;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '(':
|
||||
tl.estimate = teOpenParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ')':
|
||||
tl.estimate = teCloseParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ':':
|
||||
tl.estimate = teColon;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
default:
|
||||
if (IS_ALPHA(*curpos)) {
|
||||
tl.estimate = teAlpha;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else if (IS_NUMBER(*curpos)) {
|
||||
tl.estimate = teNumeric;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else {
|
||||
tl.estimate = teUnknown;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
} else if (*curpos == '\n') {
|
||||
tl.estimate = teNewline;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
|
||||
tl.begin = curpos;
|
||||
tl.estimate = teEOF;
|
||||
return tl;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* general purpose parse functions (see comment in the .h file) ...
|
||||
*/
|
||||
|
||||
iter
|
||||
ICodeParser::ParseAlpha (iter begin, iter end, string **rval)
|
||||
{
|
||||
iter curpos;
|
||||
string *str = new string();
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_ALPHA(*curpos))
|
||||
*str += *curpos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBool (iter begin, iter end, bool *rval)
|
||||
{
|
||||
iter curpos = begin;
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
int32 position = 0;
|
||||
|
||||
for (; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
*rval += (*curpos - '0') * (1 / pow (10, ++position));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval *= sign;
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
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;
|
||||
}
|
||||
|
||||
uint32 i;
|
||||
end = ParseUInt32 (begin, end, &i);
|
||||
|
||||
*rval = i * sign;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseRegister (iter begin, iter end, JSTypes::Register *rval)
|
||||
{
|
||||
if (*begin == 'R' || *begin == 'r') {
|
||||
if (++begin != end) {
|
||||
try
|
||||
{
|
||||
end = ParseUInt32 (begin, end, static_cast<uint32 *>(rval));
|
||||
if (*rval != VM::NotARegister && *rval > mMaxRegister)
|
||||
mMaxRegister = *rval;
|
||||
return end;
|
||||
}
|
||||
catch (ICodeParseException *e)
|
||||
{
|
||||
/* rethrow as an "expected register" in fall through case */
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
} else if (*begin == '<') {
|
||||
if ((++begin != end) && (*begin == 'N' || *begin == 'n'))
|
||||
if ((++begin != end) && (*begin == 'A' || *begin == 'a'))
|
||||
if ((++begin != end) && (*begin == 'R' || *begin == 'r'))
|
||||
if ((++begin != end) && *begin == '>') {
|
||||
*rval = VM::NotARegister;
|
||||
return ++begin;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ICodeParseException ("Expected Register value");
|
||||
}
|
||||
|
||||
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 != '"') {
|
||||
NOT_REACHED ("|begin| does not point at a string");
|
||||
delete str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
iter curpos = 0;
|
||||
bool isEscaped = false;
|
||||
for (curpos = ++begin; curpos < end; ++curpos) {
|
||||
|
||||
switch (*curpos) {
|
||||
case '\\':
|
||||
if (isEscaped) {
|
||||
*str += '\\';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
isEscaped = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (isEscaped) {
|
||||
*str += '\t';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 't';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'n';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (isEscaped) {
|
||||
*str += '\r';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'r';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
/* unescaped newline == unterminated string */
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '"':
|
||||
if (*curpos == delim) {
|
||||
if (isEscaped) {
|
||||
*str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
isEscaped = false;
|
||||
*str += *curpos;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (!isTerminated)
|
||||
{
|
||||
delete str;
|
||||
throw new ICodeParseException ("Unterminated string literal");
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseUInt32 (iter begin, iter end, uint32 *rval)
|
||||
{
|
||||
/* XXX add overflow checking */
|
||||
*rval = 0;
|
||||
int32 position = -1;
|
||||
iter curpos;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
position++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (curpos = begin; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * static_cast<uint32>(pow (10, position));
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* operand parse functions (see comment in the .h file) ...
|
||||
*/
|
||||
|
||||
iter
|
||||
ICodeParser::ParseArgumentListOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseArgumentListOperand (string8_citer begin,
|
||||
string8_citer end,
|
||||
VM::ArgumentList **rval)
|
||||
{
|
||||
/* parse argument list on the format "(['argname': ]register[, ...])" */
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
VM::ArgumentList *al = new VM::ArgumentList();
|
||||
|
||||
if (tl.estimate != teOpenParen)
|
||||
throw new ICodeParseException ("Expected Argument List");
|
||||
throw JSParseException (eidExpectArgList);
|
||||
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
while (tl.estimate == teString || tl.estimate == teAlpha) {
|
||||
string *argName = 0;
|
||||
|
||||
if (tl.estimate == teString) {
|
||||
/* look for the argname in quotes */
|
||||
begin = ParseString (tl.begin, end, &argName);
|
||||
begin = lexString8 (tl.begin, end, &argName);
|
||||
|
||||
/* look for the : */
|
||||
tl = SeekTokenStart (begin, end);
|
||||
tl = seekTokenStart (begin, end);
|
||||
if (tl.estimate != teColon)
|
||||
throw new ICodeParseException ("Expected colon");
|
||||
throw JSParseException (eidExpectColon);
|
||||
|
||||
/* and now the register */
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
}
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected Register value");
|
||||
throw JSParseException (eidExpectRegister);
|
||||
|
||||
JSTypes::Register r;
|
||||
begin = ParseRegister (tl.begin, end, &r);
|
||||
begin = lexRegister (tl.begin, end, &r);
|
||||
if (r != VM::NotARegister && r > mMaxRegister)
|
||||
mMaxRegister = r;
|
||||
|
||||
/* pass 0 (null) as the "type" because it is
|
||||
* not actually used by the interpreter, only in (the current)
|
||||
* codegen (acording to rogerl.)
|
||||
@ -502,32 +141,32 @@ namespace ICodeASM {
|
||||
|
||||
al->push_back(arg);
|
||||
|
||||
tl = SeekTokenStart (begin, end);
|
||||
tl = seekTokenStart (begin, end);
|
||||
/* if the next token is a comma,
|
||||
* seek to the next one and go again */
|
||||
if (tl.estimate == teComma) {
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
}
|
||||
}
|
||||
|
||||
if (tl.estimate != teCloseParen)
|
||||
throw new ICodeParseException ("Expected close paren");
|
||||
throw JSParseException (eidExpectCloseParen);
|
||||
|
||||
*rval = al;
|
||||
|
||||
return tl.begin + 1;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBinaryOpOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseBinaryOpOperand (string8_citer begin, string8_citer end,
|
||||
VM::BinaryOperator::BinaryOp *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected BinaryOp");
|
||||
string *str;
|
||||
end = ParseAlpha (tl.begin, end, &str);
|
||||
throw JSParseException (eidExpectBinaryOp);
|
||||
string8 *str;
|
||||
end = lexAlpha (tl.begin, end, &str);
|
||||
|
||||
for (int i = 0; keyword_binaryops[i] != 0; ++i)
|
||||
if (cmp_nocase (*str, keyword_binaryops[i], keyword_binaryops[i] +
|
||||
@ -538,105 +177,85 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
delete str;
|
||||
throw new ICodeParseException ("Unknown BinaryOp");
|
||||
throw JSParseException (eidUnknownBinaryOp);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseBoolOperand (iter begin, iter end, bool *rval)
|
||||
string8_citer
|
||||
ICodeParser::parseBoolOperand (string8_citer begin, string8_citer end,
|
||||
bool *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected boolean value");
|
||||
throw JSParseException (eidExpectBool);
|
||||
|
||||
return ParseBool (tl.begin, end, rval);
|
||||
return lexBool (tl.begin, end, rval);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseDoubleOperand (iter begin, iter end, double *rval)
|
||||
string8_citer
|
||||
ICodeParser::parseDoubleOperand (string8_citer begin, string8_citer end,
|
||||
double *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if ((tl.estimate != teNumeric) && (tl.estimate != teMinus) &&
|
||||
(tl.estimate != tePlus))
|
||||
throw new ICodeParseException ("Expected double value");
|
||||
throw JSParseException (eidExpectDouble);
|
||||
|
||||
return ParseDouble (tl.begin, end, rval);
|
||||
return lexDouble (tl.begin, end, rval);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseICodeModuleOperand (iter /*begin*/, iter end, string ** /*rval*/)
|
||||
string8_citer
|
||||
ICodeParser::parseICodeModuleOperand (string8_citer /*begin*/,
|
||||
string8_citer end, string ** /*rval*/)
|
||||
{
|
||||
NOT_REACHED ("ICode modules are hard, lets go shopping.");
|
||||
return end;
|
||||
/*
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected ICode Module as a quoted string");
|
||||
|
||||
return ParseString (tl.begin, end, rval);
|
||||
*/
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSClassOperand (iter /*begin*/, iter end,
|
||||
string ** /*rval*/)
|
||||
string8_citer
|
||||
ICodeParser::parseJSClassOperand (string8_citer /*begin*/,
|
||||
string8_citer end, string ** /*rval*/)
|
||||
{
|
||||
NOT_REACHED ("JSClasses are hard, lets go shopping.");
|
||||
return end;
|
||||
|
||||
/*
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected JSClass as a quoted string");
|
||||
return ParseString (tl.begin, end, rval);
|
||||
*/
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSStringOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseJSStringOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSString **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
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);
|
||||
throw JSParseException (eidExpectString);
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
*rval = new JSTypes::JSString (str->c_str());
|
||||
delete str;
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSFunctionOperand (iter /*begin*/, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseJSFunctionOperand (string8_citer /*begin*/,
|
||||
string8_citer end,
|
||||
string ** /*rval*/)
|
||||
{
|
||||
NOT_REACHED ("JSFunctions are hard, lets go shopping.");
|
||||
return end;
|
||||
|
||||
/*
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected JSFunction as a quoted string");
|
||||
return ParseString (tl.begin, end, rval);
|
||||
*/
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseJSTypeOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseJSTypeOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSType **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected JSType as a quoted string");
|
||||
throw JSParseException (eidExpectString);
|
||||
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, &str);
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
StringAtom &typename_atom = mCx->getWorld().identifiers[str->c_str()];
|
||||
delete str;
|
||||
JSTypes::JSValue jsv =
|
||||
@ -649,29 +268,30 @@ namespace ICodeASM {
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseLabelOperand (iter begin, iter end, VM::Label **rval)
|
||||
string8_citer
|
||||
ICodeParser::parseLabelOperand (string8_citer begin, string8_citer end,
|
||||
VM::Label **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected Label Identifier or Offset keyword");
|
||||
throw JSParseException (eidExpectLabel);
|
||||
|
||||
string *str;
|
||||
begin = ParseAlpha (tl.begin, end, &str);
|
||||
string8 *str;
|
||||
begin = lexAlpha (tl.begin, end, &str);
|
||||
|
||||
if (cmp_nocase(*str, keyword_offset, keyword_offset +
|
||||
strlen(keyword_offset) + 1) == 0) {
|
||||
delete str;
|
||||
/* got the "Offset" keyword, treat next thing as a jump offset
|
||||
* expressed as "Offset +/-N" */
|
||||
tl = SeekTokenStart (begin, end);
|
||||
tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teNumeric)
|
||||
throw new ICodeParseException ("Expected numeric value after Offset keyword");
|
||||
throw JSParseException (eidExpectUInt32);
|
||||
|
||||
uint32 ofs;
|
||||
begin = ParseUInt32 (tl.begin, end, &ofs);
|
||||
begin = lexUInt32 (tl.begin, end, &ofs);
|
||||
VM::Label *new_label = new VM::Label(mInstructions);
|
||||
new_label->mOffset = ofs;
|
||||
mLabels.push_back (new_label);
|
||||
@ -697,44 +317,52 @@ namespace ICodeASM {
|
||||
return begin;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseUInt32Operand (iter begin, iter end, uint32 *rval)
|
||||
string8_citer
|
||||
ICodeParser::parseUInt32Operand (string8_citer begin,
|
||||
string8_citer end, uint32 *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teNumeric)
|
||||
throw new ICodeParseException ("Expected UInt32 value");
|
||||
throw JSParseException (eidExpectUInt32);
|
||||
|
||||
return ParseUInt32 (tl.begin, end, rval);
|
||||
return lexUInt32 (tl.begin, end, rval);
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseRegisterOperand (iter begin, iter end,
|
||||
string8_citer
|
||||
ICodeParser::parseRegisterOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
return ParseRegister (tl.begin, end, rval);
|
||||
end = lexRegister (tl.begin, end, rval);
|
||||
if (*rval != VM::NotARegister && *rval > mMaxRegister)
|
||||
mMaxRegister = *rval;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseStringAtomOperand (iter begin, iter end, StringAtom **rval)
|
||||
string8_citer
|
||||
ICodeParser::parseStringAtomOperand (string8_citer begin, string8_citer end,
|
||||
StringAtom **rval)
|
||||
{
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw new ICodeParseException ("Expected StringAtom as a quoted string");
|
||||
string *str;
|
||||
end = ParseString (tl.begin, end, &str);
|
||||
throw JSParseException (eidExpectString);
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
*rval = &(mCx->getWorld().identifiers[str->c_str()]);
|
||||
delete str;
|
||||
return end;
|
||||
}
|
||||
|
||||
/* "High Level" parse functions ... */
|
||||
iter ICodeParser::ParseInstruction (uint icodeID, iter begin, iter end)
|
||||
string8_citer
|
||||
ICodeParser::parseInstruction (uint icodeID, string8_citer begin,
|
||||
string8_citer end)
|
||||
{
|
||||
iter curpos = begin;
|
||||
string8_citer curpos = begin;
|
||||
StatementNode node;
|
||||
node.icodeID = icodeID;
|
||||
|
||||
@ -743,7 +371,7 @@ namespace ICodeASM {
|
||||
{ \
|
||||
C rval; \
|
||||
node.operand[i].type = ot##T; \
|
||||
curpos = Parse##T##Operand (curpos, end, &rval); \
|
||||
curpos = parse##T##Operand (curpos, end, &rval); \
|
||||
node.operand[i].data = CTYPE<int64>(rval); \
|
||||
break; \
|
||||
}
|
||||
@ -773,10 +401,10 @@ namespace ICodeASM {
|
||||
if (i != 3 && icodemap[icodeID].otype[i + 1] != otNone) {
|
||||
/* if the instruction has more arguments, eat a comma and
|
||||
* locate the next token */
|
||||
TokenLocation tl = SeekTokenStart (curpos, end);
|
||||
TokenLocation tl = seekTokenStart (curpos, end);
|
||||
if (tl.estimate != teComma)
|
||||
throw new ICodeParseException ("Expected comma");
|
||||
tl = SeekTokenStart (tl.begin + 1, end);
|
||||
throw JSParseException (eidExpectComma);
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
curpos = tl.begin;
|
||||
}
|
||||
}
|
||||
@ -786,9 +414,9 @@ namespace ICodeASM {
|
||||
mInstructions->push_back (InstructionFromNode(&node));
|
||||
++mInstructionCount;
|
||||
|
||||
TokenLocation tl = SeekTokenStart (curpos, end);
|
||||
TokenLocation tl = seekTokenStart (curpos, end);
|
||||
if (tl.estimate != teNewline && tl.estimate != teEOF)
|
||||
throw new ICodeParseException ("Expected newline");
|
||||
throw JSParseException (eidExpectNewline);
|
||||
|
||||
if (tl.estimate == teEOF)
|
||||
return tl.begin;
|
||||
@ -796,12 +424,12 @@ namespace ICodeASM {
|
||||
return tl.begin + 1;
|
||||
}
|
||||
|
||||
iter
|
||||
ICodeParser::ParseNextStatement (iter begin, iter end)
|
||||
string8_citer
|
||||
ICodeParser::parseNextStatement (string8_citer begin, string8_citer end)
|
||||
{
|
||||
bool isLabel = false;
|
||||
iter firstTokenEnd = end;
|
||||
TokenLocation tl = SeekTokenStart (begin, end);
|
||||
string8_citer firstTokenEnd = end;
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate == teNewline) {
|
||||
/* empty statement, do nothing */
|
||||
@ -809,9 +437,9 @@ namespace ICodeASM {
|
||||
}
|
||||
|
||||
if (tl.estimate != teAlpha)
|
||||
throw new ICodeParseException ("Expected alphanumeric token");
|
||||
throw JSParseException (eidExpectIdentifier);
|
||||
|
||||
for (iter curpos = tl.begin; curpos < end; ++curpos) {
|
||||
for (string8_citer curpos = tl.begin; curpos < end; ++curpos) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ':':
|
||||
@ -831,7 +459,7 @@ namespace ICodeASM {
|
||||
if (isLabel) {
|
||||
/* the thing we scanned was a label...
|
||||
* ignore the trailing : */
|
||||
string label_str(tl.begin, firstTokenEnd - 1);
|
||||
string8 label_str(tl.begin, firstTokenEnd - 1);
|
||||
/* check to see if it was already referenced... */
|
||||
LabelMap::const_iterator l = mNamedLabels.find(label_str.c_str());
|
||||
if (l == mNamedLabels.end()) {
|
||||
@ -848,26 +476,25 @@ namespace ICodeASM {
|
||||
(*l).second->mOffset = mInstructionCount;
|
||||
} else {
|
||||
/* offset was already set, this must be a dupe! */
|
||||
throw new ICodeParseException ("Duplicate label");
|
||||
throw JSParseException (eidDuplicateLabel);
|
||||
}
|
||||
}
|
||||
return firstTokenEnd;
|
||||
} else {
|
||||
/* the thing we scanned was an instruction, search the icode map
|
||||
* for a matching instruction */
|
||||
string icode_str(tl.begin, firstTokenEnd);
|
||||
string8 icode_str(tl.begin, firstTokenEnd);
|
||||
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) == 0)
|
||||
/* if match found, parse it's operands */
|
||||
return ParseInstruction (i, firstTokenEnd, end);
|
||||
return parseInstruction (i, firstTokenEnd, end);
|
||||
/* otherwise, choke on it */
|
||||
throw new ICodeParseException ("Unknown ICode " + icode_str);
|
||||
throw JSParseException (eidUnknownICode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,9 +37,8 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __icodeasm_h
|
||||
|
||||
#define __icodeasm_h
|
||||
#ifndef icodeasm_h___
|
||||
#define icodeasm_h___
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
@ -48,42 +47,8 @@
|
||||
#include "jstypes.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
#define iter string::const_iterator
|
||||
|
||||
namespace JavaScript {
|
||||
namespace ICodeASM {
|
||||
enum TokenEstimation {
|
||||
/* guess at tokentype, based on first character of token */
|
||||
teAlpha,
|
||||
teCloseParen,
|
||||
teComma,
|
||||
teColon,
|
||||
teEOF,
|
||||
teIllegal,
|
||||
teMinus,
|
||||
teNewline,
|
||||
teNotARegister,
|
||||
teNumeric,
|
||||
teOpenParen,
|
||||
tePlus,
|
||||
teString,
|
||||
teUnknown,
|
||||
};
|
||||
|
||||
/*
|
||||
enum TokenType {
|
||||
// verified token type
|
||||
ttUndetermined,
|
||||
ttLabel,
|
||||
ttInstruction,
|
||||
ttRegister,
|
||||
ttRegisterList,
|
||||
ttNotARegister,
|
||||
ttString,
|
||||
ttNumber,
|
||||
ttOffsetKeyword
|
||||
};
|
||||
*/
|
||||
|
||||
enum OperandType {
|
||||
otNone = 0,
|
||||
@ -102,21 +67,6 @@ namespace ICodeASM {
|
||||
otStringAtom
|
||||
};
|
||||
|
||||
struct ICodeParseException {
|
||||
ICodeParseException (string aMsg, iter aPos = 0)
|
||||
: msg(aMsg), pos(aPos) {}
|
||||
string msg;
|
||||
iter pos;
|
||||
};
|
||||
|
||||
struct TokenLocation {
|
||||
TokenLocation () : begin(0), estimate(teIllegal) /*,
|
||||
type(ttUndetermined) */ {}
|
||||
iter begin;
|
||||
TokenEstimation estimate;
|
||||
// TokenType type;
|
||||
};
|
||||
|
||||
struct AnyOperand {
|
||||
OperandType type;
|
||||
int64 data;
|
||||
@ -145,24 +95,7 @@ namespace ICodeASM {
|
||||
|
||||
public:
|
||||
ICodeParser (Interpreter::Context *aCx) : mCx(aCx), mInstructions(0) {}
|
||||
void ParseSourceFromString (const string &source);
|
||||
|
||||
/* locate the beginning of the next token and take a guess at what it
|
||||
* might be */
|
||||
TokenLocation SeekTokenStart (iter begin, iter end);
|
||||
|
||||
/* 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 ParseInt32 (iter begin, iter end, int32 *rval);
|
||||
iter ParseRegister (iter begin, iter end, JSTypes::Register *rval);
|
||||
iter ParseString (iter begin, iter end, string **rval);
|
||||
iter ParseUInt32 (iter begin, iter end, uint32 *rval);
|
||||
void parseSourceFromString (const string8 &source);
|
||||
|
||||
/* operand parse functions; These functions take care of finding
|
||||
* the start of the token with |SeekTokenStart|, and checking the
|
||||
@ -171,31 +104,56 @@ namespace ICodeASM {
|
||||
* token is found, and it is of the expected type, the actual parsing is
|
||||
* carried out by one of the general purpose parse functions.
|
||||
*/
|
||||
iter ParseArgumentListOperand (iter begin, iter end,
|
||||
VM::ArgumentList **rval);
|
||||
iter ParseBinaryOpOperand (iter begin, iter end,
|
||||
VM::BinaryOperator::BinaryOp *rval);
|
||||
iter ParseBoolOperand (iter begin, iter end, bool *rval);
|
||||
iter ParseDoubleOperand (iter begin, iter end, double *rval);
|
||||
iter ParseICodeModuleOperand (iter begin, iter end, string **rval);
|
||||
iter ParseJSClassOperand (iter begin, iter end, string **rval);
|
||||
iter ParseJSStringOperand (iter begin, iter end,
|
||||
JSTypes::JSString **rval);
|
||||
iter ParseJSFunctionOperand (iter begin, iter end, string **rval);
|
||||
iter ParseJSTypeOperand (iter begin, iter end, JSTypes::JSType **rval);
|
||||
iter ParseLabelOperand (iter begin, iter end, VM::Label **rval);
|
||||
iter ParseUInt32Operand (iter begin, iter end, uint32 *rval);
|
||||
iter ParseRegisterOperand (iter begin, iter end,
|
||||
JSTypes::Register *rval);
|
||||
iter ParseStringAtomOperand (iter begin, iter end, StringAtom **rval);
|
||||
string8_citer
|
||||
parseArgumentListOperand (string8_citer begin, string8_citer end,
|
||||
VM::ArgumentList **rval);
|
||||
string8_citer
|
||||
parseBinaryOpOperand (string8_citer begin, string8_citer end,
|
||||
VM::BinaryOperator::BinaryOp *rval);
|
||||
string8_citer
|
||||
parseBoolOperand (string8_citer begin, string8_citer end,
|
||||
bool *rval);
|
||||
string8_citer
|
||||
parseDoubleOperand (string8_citer begin, string8_citer end,
|
||||
double *rval);
|
||||
string8_citer
|
||||
parseICodeModuleOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSClassOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSStringOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSString **rval);
|
||||
string8_citer
|
||||
parseJSFunctionOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSTypeOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSType **rval);
|
||||
string8_citer
|
||||
parseLabelOperand (string8_citer begin, string8_citer end,
|
||||
VM::Label **rval);
|
||||
string8_citer
|
||||
parseUInt32Operand (string8_citer begin, string8_citer end,
|
||||
uint32 *rval);
|
||||
string8_citer
|
||||
parseRegisterOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval);
|
||||
string8_citer
|
||||
parseStringAtomOperand (string8_citer begin, string8_citer end,
|
||||
StringAtom **rval);
|
||||
|
||||
/* "high level" parse functions */
|
||||
iter ParseInstruction (uint icodeID, iter start, iter end);
|
||||
iter ParseNextStatement (iter begin, iter end);
|
||||
string8_citer
|
||||
parseInstruction (uint icodeID, string8_citer start,
|
||||
string8_citer end);
|
||||
string8_citer
|
||||
parseNextStatement (string8_citer begin, string8_citer end);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #ifndef __icodeasm_h */
|
||||
#endif /* #ifndef icodeasm_h___ */
|
||||
|
||||
@ -2499,7 +2499,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
stdOut << "Calling ICodeParser with :\n" << str << "\n";
|
||||
|
||||
icp.ParseSourceFromString(str);
|
||||
icp.parseSourceFromString(str);
|
||||
|
||||
ICodeModule *icm = new ICodeModule(icp.mInstructions,
|
||||
NULL, /* VariableList *variables */
|
||||
|
||||
405
mozilla/js2/src/lexutils.cpp
Normal file
405
mozilla/js2/src/lexutils.cpp
Normal file
@ -0,0 +1,405 @@
|
||||
/* -*- 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 "lexutils.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace LexUtils {
|
||||
|
||||
int cmp_nocase (const string8& s1, string8_citer s2_begin,
|
||||
string8_citer s2_end)
|
||||
{
|
||||
string8_citer p1 = s1.begin();
|
||||
string8_citer p2 = s2_begin;
|
||||
uint s2_size = s2_end - s2_begin - 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
TokenLocation
|
||||
seekTokenStart (string8_citer begin, string8_citer end)
|
||||
{
|
||||
TokenLocation tl;
|
||||
string8_citer curpos;
|
||||
bool inComment = false;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (!inComment) {
|
||||
switch (*curpos)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
/* look past the whitespace */
|
||||
break;
|
||||
|
||||
case ';':
|
||||
inComment = true;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
tl.estimate = teNewline;
|
||||
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;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '<':
|
||||
tl.estimate = teLessThan;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case '(':
|
||||
tl.estimate = teOpenParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ')':
|
||||
tl.estimate = teCloseParen;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
case ':':
|
||||
tl.estimate = teColon;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
|
||||
default:
|
||||
if (IS_ALPHA(*curpos)) {
|
||||
tl.estimate = teAlpha;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else if (IS_NUMBER(*curpos)) {
|
||||
tl.estimate = teNumeric;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
} else {
|
||||
tl.estimate = teUnknown;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
} else if (*curpos == '\n') {
|
||||
tl.estimate = teNewline;
|
||||
tl.begin = curpos;
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
|
||||
tl.begin = curpos;
|
||||
tl.estimate = teEOF;
|
||||
return tl;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* general purpose lexer functions (see comment in the .h file) ...
|
||||
*/
|
||||
|
||||
string8_citer
|
||||
lexAlpha (string8_citer begin, string8_citer end, string8 **rval)
|
||||
{
|
||||
string8_citer curpos;
|
||||
string8 *str = new string8();
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_ALPHA(*curpos))
|
||||
*str += *curpos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexBool (string8_citer begin, string8_citer end, bool *rval)
|
||||
{
|
||||
string8_citer curpos = begin;
|
||||
|
||||
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 JSLexException (eidExpectBool);
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexDouble (string8_citer begin, string8_citer 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 JSLexException (eidExpectDouble);
|
||||
begin = tl.begin;
|
||||
}
|
||||
|
||||
|
||||
string8_citer curpos = lexUInt32 (begin, end, &integer);
|
||||
*rval = static_cast<double>(integer);
|
||||
if (*curpos != '.') {
|
||||
*rval *= sign;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
++curpos;
|
||||
int32 position = 0;
|
||||
|
||||
for (; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
*rval += (*curpos - '0') * (1 / pow (10, ++position));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*rval *= sign;
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexInt32 (string8_citer begin, string8_citer 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 JSLexException (eidExpectInt32);
|
||||
begin = tl.begin;
|
||||
}
|
||||
|
||||
uint32 i;
|
||||
end = lexUInt32 (begin, end, &i);
|
||||
|
||||
*rval = i * sign;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexRegister (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval)
|
||||
{
|
||||
if (*begin == 'R' || *begin == 'r') {
|
||||
if (++begin != end) {
|
||||
try
|
||||
{
|
||||
end = lexUInt32 (begin, end, static_cast<uint32 *>(rval));
|
||||
return end;
|
||||
}
|
||||
catch (JSLexException &e)
|
||||
{
|
||||
/* rethrow as an "expected register" in fall through case */
|
||||
}
|
||||
}
|
||||
} else if (*begin == '<') {
|
||||
if ((++begin != end) && (*begin == 'N' || *begin == 'n'))
|
||||
if ((++begin != end) && (*begin == 'A' || *begin == 'a'))
|
||||
if ((++begin != end) && (*begin == 'R' || *begin == 'r'))
|
||||
if ((++begin != end) && *begin == '>') {
|
||||
*rval = VM::NotARegister;
|
||||
return ++begin;
|
||||
}
|
||||
}
|
||||
|
||||
throw JSLexException (eidExpectRegister);
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexString8 (string8_citer begin, string8_citer end, string8 **rval)
|
||||
{
|
||||
char delim = *begin;
|
||||
bool isTerminated = false;
|
||||
/* XXX not exactly exception safe, string may never get deleted */
|
||||
string8 *str = new string8();
|
||||
*rval = 0;
|
||||
|
||||
if (delim != '\'' && delim != '"') {
|
||||
NOT_REACHED ("|begin| does not point at a string");
|
||||
delete str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
string8_citer curpos = 0;
|
||||
bool isEscaped = false;
|
||||
for (curpos = ++begin; curpos < end; ++curpos) {
|
||||
|
||||
switch (*curpos) {
|
||||
case '\\':
|
||||
if (isEscaped) {
|
||||
*str += '\\';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
isEscaped = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (isEscaped) {
|
||||
*str += '\t';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 't';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'n';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (isEscaped) {
|
||||
*str += '\r';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
*str += 'r';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (isEscaped) {
|
||||
*str += '\n';
|
||||
isEscaped = false;
|
||||
} else {
|
||||
/* unescaped newline == unterminated string */
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '"':
|
||||
if (*curpos == delim) {
|
||||
if (isEscaped) {
|
||||
*str += delim;
|
||||
isEscaped = false;
|
||||
} else {
|
||||
++curpos;
|
||||
isTerminated = true;
|
||||
goto scan_done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
isEscaped = false;
|
||||
*str += *curpos;
|
||||
}
|
||||
}
|
||||
scan_done:
|
||||
|
||||
if (!isTerminated)
|
||||
{
|
||||
delete str;
|
||||
throw new JSLexException (eidUnterminatedString);
|
||||
}
|
||||
|
||||
*rval = str;
|
||||
return curpos;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
lexUInt32 (string8_citer begin, string8_citer end, uint32 *rval)
|
||||
{
|
||||
/* XXX add overflow checking */
|
||||
*rval = 0;
|
||||
int32 position = -1;
|
||||
string8_citer curpos;
|
||||
|
||||
for (curpos = begin; curpos < end; ++curpos) {
|
||||
if (IS_NUMBER(*curpos))
|
||||
position++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (curpos = begin; position >= 0; --position)
|
||||
*rval += (*curpos++ - '0') * static_cast<uint32>(pow (10, position));
|
||||
|
||||
return curpos;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
107
mozilla/js2/src/lexutils.h
Normal file
107
mozilla/js2/src/lexutils.h
Normal file
@ -0,0 +1,107 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#ifndef lexutils_h___
|
||||
#define lexutils_h___
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
#include "utilities.h"
|
||||
#include "exception.h"
|
||||
#include "vmtypes.h"
|
||||
#include "jstypes.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace LexUtils {
|
||||
|
||||
#define IS_ALPHA(ch) ((ch >= 'a' && ch <= 'z') || \
|
||||
(ch >= 'A' && ch <= 'Z') || \
|
||||
(ch == '_'))
|
||||
#define IS_NUMBER(ch) (ch >= '0' && ch <= '9')
|
||||
|
||||
enum TokenEstimation {
|
||||
/* guess at tokentype, based on first character of token */
|
||||
teAlpha,
|
||||
teCloseParen,
|
||||
teComma,
|
||||
teColon,
|
||||
teEOF,
|
||||
teIllegal,
|
||||
teLessThan,
|
||||
teMinus,
|
||||
teNewline,
|
||||
teNumeric,
|
||||
teOpenParen,
|
||||
tePlus,
|
||||
teString,
|
||||
teUnknown,
|
||||
};
|
||||
|
||||
struct TokenLocation {
|
||||
TokenLocation () : begin(0), estimate(teIllegal) {}
|
||||
string8_citer begin;
|
||||
TokenEstimation estimate;
|
||||
};
|
||||
|
||||
/* compare, ignoring case */
|
||||
int cmp_nocase (const string8& s1, string8_citer s2_begin,
|
||||
string8_citer s2_end);
|
||||
|
||||
/* locate the beginning of the next token and take a guess at what it
|
||||
* might be */
|
||||
TokenLocation seekTokenStart (string8_citer begin, string8_citer end);
|
||||
|
||||
/* general purpose lexer functions; |begin| is expected to point
|
||||
* at the start of the token to be processed (eg, these routines
|
||||
* don't call |seekTokenStart|, and no initial check is done to ensure
|
||||
* that |begin| != |end|.
|
||||
*/
|
||||
string8_citer lexAlpha (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer lexBool (string8_citer begin, string8_citer end, bool *rval);
|
||||
string8_citer lexDouble (string8_citer begin, string8_citer end,
|
||||
double *rval);
|
||||
string8_citer lexInt32 (string8_citer begin, string8_citer end,
|
||||
int32 *rval);
|
||||
string8_citer lexRegister (string8_citer begin, string8_citer end,
|
||||
JSTypes::Register *rval);
|
||||
string8_citer lexString8 (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
string8_citer lexUInt32 (string8_citer begin, string8_citer end,
|
||||
uint32 *rval);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* lexutils_h___ */
|
||||
@ -151,7 +151,10 @@ namespace JavaScript {
|
||||
// code bloat and separates the concepts of a fixed, read-only string from a mutable buffer that
|
||||
// is expanding. For now, though, we use the standard basic_string.
|
||||
typedef std::basic_string<char16> String;
|
||||
|
||||
typedef String string16;
|
||||
typedef string16::const_iterator string16_citer;
|
||||
typedef string string8;
|
||||
typedef string8::const_iterator string8_citer;
|
||||
|
||||
typedef uint32 char16orEOF; // A type that can hold any char16 plus one special value: ueof.
|
||||
const char16orEOF char16eof = static_cast<char16orEOF>(-1);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user