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:
rginda%netscape.com 2000-11-14 03:11:54 +00:00
parent 7995becc53
commit 37eb1a8437
22 changed files with 1934 additions and 1270 deletions

View File

@ -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/

View 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
View 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___ */

View 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
};
}

View File

@ -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);

View File

@ -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);
}
}
}
}

View File

@ -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___ */

View File

@ -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
View 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
View 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___ */

View File

@ -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);

View File

@ -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/

View 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
View 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___ */

View 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
};
}

View File

@ -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);

View File

@ -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);
}
}
}
}

View File

@ -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___ */

View File

@ -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 */

View 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
View 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___ */

View File

@ -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);