diff --git a/mozilla/js/js2/Makefile b/mozilla/js/js2/Makefile index 07cf4a596e3..474bb016933 100644 --- a/mozilla/js/js2/Makefile +++ b/mozilla/js/js2/Makefile @@ -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/ diff --git a/mozilla/js/js2/exception.cpp b/mozilla/js/js2/exception.cpp new file mode 100644 index 00000000000..3a00ec1b554 --- /dev/null +++ b/mozilla/js/js2/exception.cpp @@ -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; + } + +} + diff --git a/mozilla/js/js2/exception.h b/mozilla/js/js2/exception.h new file mode 100644 index 00000000000..21fd8a989fb --- /dev/null +++ b/mozilla/js/js2/exception.h @@ -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___ */ + + diff --git a/mozilla/js/js2/exception_msgs.cpp b/mozilla/js/js2/exception_msgs.cpp new file mode 100644 index 00000000000..d097143967f --- /dev/null +++ b/mozilla/js/js2/exception_msgs.cpp @@ -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 + }; + +} diff --git a/mozilla/js/js2/ica_test.cpp b/mozilla/js/js2/ica_test.cpp index 47ac42a3da3..e47963864a8 100644 --- a/mozilla/js/js2/ica_test.cpp +++ b/mozilla/js/js2/ica_test.cpp @@ -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); diff --git a/mozilla/js/js2/icodeasm.cpp b/mozilla/js/js2/icodeasm.cpp index 012510ee7cb..6592d172687 100644 --- a/mozilla/js/js2/icodeasm.cpp +++ b/mozilla/js/js2/icodeasm.cpp @@ -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(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(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(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(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); } } - } } diff --git a/mozilla/js/js2/icodeasm.h b/mozilla/js/js2/icodeasm.h index caab06b6e46..68044c77517 100644 --- a/mozilla/js/js2/icodeasm.h +++ b/mozilla/js/js2/icodeasm.h @@ -37,9 +37,8 @@ #endif -#ifndef __icodeasm_h - -#define __icodeasm_h +#ifndef icodeasm_h___ +#define icodeasm_h___ #include #include @@ -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___ */ diff --git a/mozilla/js/js2/icodegenerator.cpp b/mozilla/js/js2/icodegenerator.cpp index 4b99be90533..bbf5609e49e 100644 --- a/mozilla/js/js2/icodegenerator.cpp +++ b/mozilla/js/js2/icodegenerator.cpp @@ -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 */ diff --git a/mozilla/js/js2/lexutils.cpp b/mozilla/js/js2/lexutils.cpp new file mode 100644 index 00000000000..0d8cb48d235 --- /dev/null +++ b/mozilla/js/js2/lexutils.cpp @@ -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(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(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(pow (10, position)); + + return curpos; + } + +} +} diff --git a/mozilla/js/js2/lexutils.h b/mozilla/js/js2/lexutils.h new file mode 100644 index 00000000000..4a6ac467edf --- /dev/null +++ b/mozilla/js/js2/lexutils.h @@ -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 +#include + +#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___ */ diff --git a/mozilla/js/js2/utilities.h b/mozilla/js/js2/utilities.h index 7aee0c16c22..58c8b1215c3 100644 --- a/mozilla/js/js2/utilities.h +++ b/mozilla/js/js2/utilities.h @@ -151,7 +151,10 @@ namespace JavaScript { // code bloat and separates the concepts of a fixed, read-only string from a mutable buffer that // is expanding. For now, though, we use the standard basic_string. typedef std::basic_string 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(-1); diff --git a/mozilla/js2/src/Makefile b/mozilla/js2/src/Makefile index 07cf4a596e3..474bb016933 100644 --- a/mozilla/js2/src/Makefile +++ b/mozilla/js2/src/Makefile @@ -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/ diff --git a/mozilla/js2/src/exception.cpp b/mozilla/js2/src/exception.cpp new file mode 100644 index 00000000000..3a00ec1b554 --- /dev/null +++ b/mozilla/js2/src/exception.cpp @@ -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; + } + +} + diff --git a/mozilla/js2/src/exception.h b/mozilla/js2/src/exception.h new file mode 100644 index 00000000000..21fd8a989fb --- /dev/null +++ b/mozilla/js2/src/exception.h @@ -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___ */ + + diff --git a/mozilla/js2/src/exception_msgs.cpp b/mozilla/js2/src/exception_msgs.cpp new file mode 100644 index 00000000000..d097143967f --- /dev/null +++ b/mozilla/js2/src/exception_msgs.cpp @@ -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 + }; + +} diff --git a/mozilla/js2/src/ica_test.cpp b/mozilla/js2/src/ica_test.cpp index 47ac42a3da3..e47963864a8 100644 --- a/mozilla/js2/src/ica_test.cpp +++ b/mozilla/js2/src/ica_test.cpp @@ -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); diff --git a/mozilla/js2/src/icodeasm.cpp b/mozilla/js2/src/icodeasm.cpp index 012510ee7cb..6592d172687 100644 --- a/mozilla/js2/src/icodeasm.cpp +++ b/mozilla/js2/src/icodeasm.cpp @@ -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(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(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(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(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); } } - } } diff --git a/mozilla/js2/src/icodeasm.h b/mozilla/js2/src/icodeasm.h index caab06b6e46..68044c77517 100644 --- a/mozilla/js2/src/icodeasm.h +++ b/mozilla/js2/src/icodeasm.h @@ -37,9 +37,8 @@ #endif -#ifndef __icodeasm_h - -#define __icodeasm_h +#ifndef icodeasm_h___ +#define icodeasm_h___ #include #include @@ -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___ */ diff --git a/mozilla/js2/src/icodegenerator.cpp b/mozilla/js2/src/icodegenerator.cpp index 4b99be90533..bbf5609e49e 100644 --- a/mozilla/js2/src/icodegenerator.cpp +++ b/mozilla/js2/src/icodegenerator.cpp @@ -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 */ diff --git a/mozilla/js2/src/lexutils.cpp b/mozilla/js2/src/lexutils.cpp new file mode 100644 index 00000000000..0d8cb48d235 --- /dev/null +++ b/mozilla/js2/src/lexutils.cpp @@ -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(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(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(pow (10, position)); + + return curpos; + } + +} +} diff --git a/mozilla/js2/src/lexutils.h b/mozilla/js2/src/lexutils.h new file mode 100644 index 00000000000..4a6ac467edf --- /dev/null +++ b/mozilla/js2/src/lexutils.h @@ -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 +#include + +#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___ */ diff --git a/mozilla/js2/src/utilities.h b/mozilla/js2/src/utilities.h index 7aee0c16c22..58c8b1215c3 100644 --- a/mozilla/js2/src/utilities.h +++ b/mozilla/js2/src/utilities.h @@ -151,7 +151,10 @@ namespace JavaScript { // code bloat and separates the concepts of a fixed, read-only string from a mutable buffer that // is expanding. For now, though, we use the standard basic_string. typedef std::basic_string 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(-1);