Updated parser: attributes can be expressions, added new attributes, disallowed nested ::'s, deleted Eval nodes, added const and void nodes, deleted package attribute, deleted super::id syntax, and added super, super(expr), and super(args) syntax

This commit is contained in:
waldemar%netscape.com 2001-06-13 21:24:27 +00:00
Родитель 8e0358e13a
Коммит c3cb31ba54
16 изменённых файлов: 5601 добавлений и 9954 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -13,11 +13,11 @@
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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
@ -43,7 +43,7 @@
#include "utilities.h"
#include "strings.h"
namespace JavaScript
namespace JavaScript
{
//
// Output
@ -51,332 +51,271 @@ namespace JavaScript
// Print the characters between begin and end to the given file. These
// characters may include nulls.
size_t printChars(FILE *file, const char *begin, const char *end);
size_t printChars(FILE *file, const char *begin, const char *end);
#ifndef XP_MAC_MPW
inline size_t printChars(FILE *file, const char *begin, const char *end) {
ASSERT(end >= begin);
return STD::fwrite(begin, 1, static_cast<size_t>(end - begin), file);
}
inline size_t printChars(FILE *file, const char *begin, const char *end) {
ASSERT(end >= begin);
return STD::fwrite(begin, 1, static_cast<size_t>(end - begin), file);
}
#endif
// A Formatter is an abstract base class representing a simplified output stream.
// One can print text to a Formatter by using << and the various global
// print... methods below. Formatters accept both char and char16 text and
// convert as appropriate to their actual stream.
class Formatter {
protected:
virtual void printChar8(char ch);
virtual void printChar16(char16 ch);
virtual void printZStr8(const char *str);
virtual void printStr8(const char *strBegin, const char *strEnd) = 0;
virtual void printStr16(const char16 *strBegin,
const char16 *strEnd) = 0;
virtual void printString16(const String &s);
virtual void printVFormat8(const char *format, va_list args);
public:
Formatter &operator<<(char ch) {printChar8(ch); return *this;}
Formatter &operator<<(char16 ch) {printChar16(ch); return *this;}
Formatter &operator<<(const char *str) {printZStr8(str); return *this;}
Formatter &operator<<(const String &s) {printString16(s); return *this;}
Formatter &operator<<(uint32 i) {
printFormat(*this, "%u", i);
return *this;
}
class Formatter {
protected:
virtual void printChar8(char ch);
virtual void printChar16(char16 ch);
virtual void printZStr8(const char *str);
virtual void printStr8(const char *strBegin, const char *strEnd) = 0;
virtual void printStr16(const char16 *strBegin, const char16 *strEnd) = 0;
virtual void printString16(const String &s);
virtual void printVFormat8(const char *format, va_list args);
public:
friend void printString(Formatter &f, const char *strBegin,
const char *strEnd) {
f.printStr8(strBegin, strEnd);
}
Formatter &operator<<(char ch) {printChar8(ch); return *this;}
Formatter &operator<<(char16 ch) {printChar16(ch); return *this;}
Formatter &operator<<(const char *str) {printZStr8(str); return *this;}
Formatter &operator<<(const String &s) {printString16(s); return *this;}
Formatter &operator<<(uint32 i) {
printFormat(*this, "%u", i);
return *this;
}
friend void printString(Formatter &f, const char16 *strBegin,
const char16 *strEnd) {
f.printStr16(strBegin, strEnd);
}
friend void printFormat(Formatter &f, const char *format, ...) {
va_list args;
va_start(args, format);
f.printVFormat8(format, args);
va_end(args);
}
};
void printNum(Formatter &f, uint32 i, int nDigits, char pad,
const char *format);
void printChar(Formatter &f, char ch, int count);
void printChar(Formatter &f, char16 ch, int count);
friend void printString(Formatter &f, const char *strBegin, const char *strEnd) {
f.printStr8(strBegin, strEnd);
}
inline void printDec(Formatter &f, int32 i, int nDigits = 0,
char pad = ' ') {
printNum(f, (uint32)i, nDigits, pad, "%i");
}
inline void printDec(Formatter &f, uint32 i, int nDigits = 0,
char pad = ' ') {
printNum(f, i, nDigits, pad, "%u");
}
inline void printHex(Formatter &f, int32 i, int nDigits = 0,
char pad = '0') {
printNum(f, (uint32)i, nDigits, pad, "%X");
}
inline void printHex(Formatter &f, uint32 i, int nDigits = 0,
char pad = '0') {
printNum(f, i, nDigits, pad, "%X");
}
void printPtr(Formatter &f, void *p);
friend void printString(Formatter &f, const char16 *strBegin, const char16 *strEnd) {
f.printStr16(strBegin, strEnd);
}
friend void printFormat(Formatter &f, const char *format, ...) {
va_list args;
va_start(args, format);
f.printVFormat8(format, args);
va_end(args);
}
};
void printNum(Formatter &f, uint32 i, int nDigits, char pad, const char *format);
void printChar(Formatter &f, char ch, int count);
void printChar(Formatter &f, char16 ch, int count);
inline void printDec(Formatter &f, int32 i, int nDigits = 0, char pad = ' ') {printNum(f, (uint32)i, nDigits, pad, "%i");}
inline void printDec(Formatter &f, uint32 i, int nDigits = 0, char pad = ' ') {printNum(f, i, nDigits, pad, "%u");}
inline void printHex(Formatter &f, int32 i, int nDigits = 0, char pad = '0') {printNum(f, (uint32)i, nDigits, pad, "%X");}
inline void printHex(Formatter &f, uint32 i, int nDigits = 0, char pad = '0') {printNum(f, i, nDigits, pad, "%X");}
void printPtr(Formatter &f, void *p);
// An AsciiFileFormatter is a Formatter that prints to a standard ASCII
// file or stream. Characters with Unicode values of 256 or higher are
// converted to escape sequences. Selected lower characters can also be
// converted to escape sequences; these are specified by set bits in the
// BitSet passed to the constructor.
class AsciiFileFormatter: public Formatter {
FILE *file;
BitSet<256> filter; // Set of first 256 characters that are to be
// converted to escape sequences
bool filterEmpty; // True if filter passes all 256 characters
public:
static BitSet<256> defaultFilter; // Default value of filter when not
// given in the constructor
explicit AsciiFileFormatter(FILE *file, BitSet<256> *filter = 0);
// An AsciiFileFormatter is a Formatter that prints to a standard ASCII
// file or stream. Characters with Unicode values of 256 or higher are
// converted to escape sequences. Selected lower characters can also be
// converted to escape sequences; these are specified by set bits in the
// BitSet passed to the constructor.
class AsciiFileFormatter: public Formatter {
FILE *file;
BitSet<256> filter; // Set of first 256 characters that are to be converted to escape sequences
bool filterEmpty; // True if filter passes all 256 characters
public:
static BitSet<256> defaultFilter; // Default value of filter when not given in the constructor
private:
bool filterChar(char ch) {return filter[static_cast<uchar>(ch)];}
bool filterChar(char16 ch) {
return char16Value(ch) >= 0x100 || filter[char16Value(ch)];
}
protected:
void printChar8(char ch);
void printChar16(char16 ch);
void printZStr8(const char *str);
void printStr8(const char *strBegin, const char *strEnd);
void printStr16(const char16 *strBegin, const char16 *strEnd);
};
explicit AsciiFileFormatter(FILE *file, BitSet<256> *filter = 0);
extern AsciiFileFormatter stdOut;
extern AsciiFileFormatter stdErr;
private:
bool filterChar(char ch) {return filter[static_cast<uchar>(ch)];}
bool filterChar(char16 ch) {
return char16Value(ch) >= 0x100 || filter[char16Value(ch)];
}
protected:
void printChar8(char ch);
void printChar16(char16 ch);
void printZStr8(const char *str);
void printStr8(const char *strBegin, const char *strEnd);
void printStr16(const char16 *strBegin, const char16 *strEnd);
};
extern AsciiFileFormatter stdOut;
extern AsciiFileFormatter stdErr;
// A StringFormatter is a Formatter that prints to a String.
class StringFormatter: public Formatter {
String s;
// A StringFormatter is a Formatter that prints to a String.
class StringFormatter: public Formatter {
String s;
public:
const String& getString() { return s; }
void clear() {JavaScript::clear(s);}
protected:
void printChar8(char ch);
void printChar16(char16 ch);
void printZStr8(const char *str);
void printStr8(const char *strBegin, const char *strEnd);
void printStr16(const char16 *strBegin, const char16 *strEnd);
void printString16(const String &str);
};
public:
const String& getString() { return s; }
void clear() {JavaScript::clear(s);}
protected:
void printChar8(char ch);
void printChar16(char16 ch);
void printZStr8(const char *str);
void printStr8(const char *strBegin, const char *strEnd);
void printStr16(const char16 *strBegin, const char16 *strEnd);
void printString16(const String &str);
};
//
// Formatted Output
//
class PrettyPrinter: public Formatter {
public:
STATIC_CONST(uint32, unlimitedLineWidth = 0x7FFFFFFF);
class Region;
class Indent;
class Block;
class PrettyPrinter: public Formatter {
public:
STATIC_CONST(uint32, unlimitedLineWidth = 0x7FFFFFFF);
class Region;
class Indent;
class Block;
private:
STATIC_CONST(uint32, infiniteLength = 0x80000000);
const uint32 lineWidth; // Current maximum desired line width
private:
STATIC_CONST(uint32, infiniteLength = 0x80000000);
const uint32 lineWidth; // Current maximum desired line width
struct BlockInfo {
uint32 margin; // Saved margin before this block's beginning
uint32 lastBreak; // Saved lastBreak before this block's beginning
bool fits; // True if this entire block fits on one line
};
// Variables for the back end that prints to the destination
Formatter &outputFormatter; // Destination formatter on which the
// result should be printed
uint32 outputPos; // Number of characters printed on current
// output line
uint32 lineNum; // Serial number of current line
uint32 lastBreak; // Number of line just after the last
// break that occurred in this block
uint32 margin; // Current left margin in spaces
ArrayBuffer<BlockInfo, 20> savedBlocks; // Stack of saved information
// about partially printed blocks
struct BlockInfo {
uint32 margin; // Saved margin before this block's beginning
uint32 lastBreak; // Saved lastBreak before this block's beginning
bool fits; // True if this entire block fits on one line
};
// Variables for the front end that calculates block sizes
struct Item: ListQueueEntry {
enum Kind {text, blockBegin, indentBlockBegin, blockEnd, indent,
linearBreak, fillBreak};
// Variables for the back end that prints to the destination
Formatter &outputFormatter; // Destination formatter on which the result should be printed
uint32 outputPos; // Number of characters printed on current output line
uint32 lineNum; // Serial number of current line
uint32 lastBreak; // Number of line just after the last break that occurred in this block
uint32 margin; // Current left margin in spaces
ArrayBuffer<BlockInfo, 20> savedBlocks; // Stack of saved information about partially printed blocks
const Kind kind; // The kind of this text sequence
bool lengthKnown; // True if totalLength is known; always true for
// text, blockEnd, and indent Items
uint32 length; // Length of this text sequence, number of spaces
// for this break, or delta for indent or
// indentBlockBegin
uint32 totalLength; // Total length of this block (for blockBegin)
// or length of this break plus following clump
// (for breaks)
// If lengthKnown is false, this is the
// serialPos of this Item instead of a length
bool hasKind(Kind k) const {return kind == k;}
explicit Item(Kind kind) :
kind(kind), lengthKnown(true) {}
Item(Kind kind, uint32 length) :
kind(kind), lengthKnown(true), length(length) {}
Item(Kind kind, uint32 length, uint32 beginSerialPos):
kind(kind), lengthKnown(false), length(length),
totalLength(beginSerialPos) {}
void computeTotalLength(uint32 endSerialPos) {
ASSERT(!lengthKnown);
lengthKnown = true;
totalLength = endSerialPos - totalLength;
}
};
// Variables for the front end that calculates block sizes
struct Item: ListQueueEntry {
enum Kind {text, blockBegin, indentBlockBegin, blockEnd, indent, linearBreak, fillBreak};
const Kind kind; // The kind of this text sequence
bool lengthKnown; // True if totalLength is known; always true for text, blockEnd, and indent Items
uint32 length; // Length of this text sequence, number of spaces for this break, or delta for indent or indentBlockBegin
uint32 totalLength; // Total length of this block (for blockBegin) or length of this break plus following clump (for breaks);
// If lengthKnown is false, this is the serialPos of this Item instead of a length
bool hasKind(Kind k) const {return kind == k;}
explicit Item(Kind kind): kind(kind), lengthKnown(true) {}
Item(Kind kind, uint32 length): kind(kind), lengthKnown(true), length(length) {}
Item(Kind kind, uint32 length, uint32 beginSerialPos):
kind(kind), lengthKnown(false), length(length), totalLength(beginSerialPos) {}
void computeTotalLength(uint32 endSerialPos) {
ASSERT(!lengthKnown);
lengthKnown = true;
totalLength = endSerialPos - totalLength;
}
};
#ifdef DEBUG
Region *topRegion; // Most deeply nested Region
Region *topRegion; // Most deeply nested Region
#endif
uint32 nNestedBlocks; // Number of nested Blocks
uint32 leftSerialPos; // The difference rightSerialPos-
uint32 rightSerialPos; // leftSerialPos is always the number of
// characters that would be output by
// printing activeItems if they all fit
// on one line; only the difference
// matters -- the absolute values are
// irrelevant and may wrap around 2^32.
ArrayQueue<Item *, 20> itemStack; // Stack of enclosing nested Items
// whose lengths have not yet been
// determined itemStack always has
// room for at least nNestedBlocks
// extra entries so that end Items
// may be added without throwing an
// exception.
Pool<Item> itemPool; // Pool from which to allocate
// activeItems
ListQueue<Item> activeItems; // Queue of items left to be printed
ArrayQueue<char16, 256> itemText; // Text of text items in activeItems,
// in the same order as in activeItems
uint32 nNestedBlocks; // Number of nested Blocks
public:
static uint32 defaultLineWidth; // Default for lineWidth if not given
// to the constructor
uint32 leftSerialPos; // The difference rightSerialPos-
uint32 rightSerialPos; // leftSerialPos is always the number of characters that would be output by
// printing activeItems if they all fit on one line; only the difference
// matters -- the absolute values are irrelevant and may wrap around 2^32.
explicit PrettyPrinter(Formatter &f,
uint32 lineWidth = defaultLineWidth);
private:
PrettyPrinter(const PrettyPrinter&); // No copy constructor
void operator=(const PrettyPrinter&); // No assignment operator
public:
~PrettyPrinter();
private:
void outputBreak(bool sameLine, uint32 nSpaces);
bool reduceLeftActiveItems(uint32 rightOffset);
void reduceRightActiveItems();
ArrayQueue<Item *, 20> itemStack; // Stack of enclosing nested Items whose lengths have not yet been determined;
// itemStack always has room for at least nNestedBlocks extra entries so that end Items
// may be added without throwing an exception.
Pool<Item> itemPool; // Pool from which to allocate activeItems
ListQueue<Item> activeItems; // Queue of items left to be printed
ArrayQueue<char16, 256> itemText; // Text of text items in activeItems, in the same order as in activeItems
Item &beginIndent(int32 offset);
void endIndent(Item &i);
public:
static uint32 defaultLineWidth; // Default for lineWidth if not given to the constructor
Item &beginBlock(Item::Kind kind, int32 offset);
void endBlock(Item &i);
explicit PrettyPrinter(Formatter &f, uint32 lineWidth = defaultLineWidth);
private:
PrettyPrinter(const PrettyPrinter&); // No copy constructor
void operator=(const PrettyPrinter&); // No assignment operator
public:
~PrettyPrinter();
void conditionalBreak(uint32 nSpaces, Item::Kind kind);
private:
void outputBreak(bool sameLine, uint32 nSpaces);
bool reduceLeftActiveItems(uint32 rightOffset);
void reduceRightActiveItems();
protected:
void printStr8(const char *strBegin, const char *strEnd);
void printStr16(const char16 *strBegin, const char16 *strEnd);
public:
Item &beginIndent(int32 offset);
void endIndent(Item &i);
void requiredBreak();
void linearBreak(uint32 nSpaces) {conditionalBreak(nSpaces,
Item::linearBreak);}
void linearBreak(uint32 nSpaces, bool required);
void fillBreak(uint32 nSpaces) {
conditionalBreak(nSpaces, Item::fillBreak);
}
void end();
Item &beginBlock(Item::Kind kind, int32 offset);
void endBlock(Item &i);
friend class Region;
friend class Indent;
friend class Block;
void conditionalBreak(uint32 nSpaces, Item::Kind kind);
class Region {
protected:
void printStr8(const char *strBegin, const char *strEnd);
void printStr16(const char16 *strBegin, const char16 *strEnd);
public:
void requiredBreak();
void linearBreak(uint32 nSpaces) {conditionalBreak(nSpaces, Item::linearBreak);}
void linearBreak(uint32 nSpaces, bool required);
void fillBreak(uint32 nSpaces) {conditionalBreak(nSpaces, Item::fillBreak);}
void end();
friend class Region;
friend class Indent;
friend class Block;
class Region {
#ifdef DEBUG
Region *next; // Link to next most deeply nested Region
Region *next; // Link to next most deeply nested Region
#endif
protected:
PrettyPrinter &pp;
protected:
PrettyPrinter &pp;
Region(PrettyPrinter &pp) : pp(pp) {
DEBUG_ONLY(next = pp.topRegion; pp.topRegion = this;);
}
private:
Region(const Region&); // No copy constructor
void operator=(const Region&); // No assignment operator
protected:
Region(PrettyPrinter &pp): pp(pp) {DEBUG_ONLY(next = pp.topRegion; pp.topRegion = this;);}
private:
Region(const Region&); // No copy constructor
void operator=(const Region&); // No assignment operator
protected:
#ifdef DEBUG
~Region() {pp.topRegion = next;}
~Region() {pp.topRegion = next;}
#endif
};
// Use an Indent object to temporarily indent a PrettyPrinter by the
// offset given to the Indent's constructor. The PrettyPrinter's margin
// is set back to its original value when the Indent object is destroyed.
// Using an Indent object is exception-safe; no matter how control
// leaves an Indent scope, the indent is undone.
// Scopes of Indent and Block objects must be properly nested.
class Indent: public Region {
Item &endItem; // The Item returned by beginIndent
public:
Indent(PrettyPrinter &pp, int32 offset) :
Region(pp), endItem(pp.beginIndent(offset)) {}
~Indent() {pp.endIndent(endItem);}
};
// Use a Block object to temporarily enter a PrettyPrinter block. If an
// offset is provided, line breaks inside the block are indented by that
// offset relative to the existing indent; otherwise, line breaks inside
// the block are indented to the current output position. The block
// lasts until the Block object is destroyed.
// Scopes of Indent and Block objects must be properly nested.
class Block: public Region {
Item &endItem; // The Item returned by beginBlock
public:
explicit Block(PrettyPrinter &pp) :
Region(pp), endItem(pp.beginBlock(Item::blockBegin, 0)) {}
Block(PrettyPrinter &pp, int32 offset) :
Region(pp), endItem(pp.beginBlock(Item::indentBlockBegin,
offset)) {}
~Block() {pp.endBlock(endItem);}
};
};
};
void escapeString(Formatter &f, const char16 *begin, const char16 *end,
char16 quote);
void quoteString(Formatter &f, const String &s, char16 quote);
// Use an Indent object to temporarily indent a PrettyPrinter by the
// offset given to the Indent's constructor. The PrettyPrinter's margin
// is set back to its original value when the Indent object is destroyed.
// Using an Indent object is exception-safe; no matter how control
// leaves an Indent scope, the indent is undone.
// Scopes of Indent and Block objects must be properly nested.
class Indent: public Region {
Item &endItem; // The Item returned by beginIndent
public:
Indent(PrettyPrinter &pp, int32 offset): Region(pp), endItem(pp.beginIndent(offset)) {}
~Indent() {pp.endIndent(endItem);}
};
// Use a Block object to temporarily enter a PrettyPrinter block. If an
// offset is provided, line breaks inside the block are indented by that
// offset relative to the existing indent; otherwise, line breaks inside
// the block are indented to the current output position. The block
// lasts until the Block object is destroyed.
// Scopes of Indent and Block objects must be properly nested.
class Block: public Region {
Item &endItem; // The Item returned by beginBlock
public:
explicit Block(PrettyPrinter &pp): Region(pp), endItem(pp.beginBlock(Item::blockBegin, 0)) {}
Block(PrettyPrinter &pp, int32 offset): Region(pp), endItem(pp.beginBlock(Item::indentBlockBegin, offset)) {}
~Block() {pp.endBlock(endItem);}
};
};
void escapeString(Formatter &f, const char16 *begin, const char16 *end, char16 quote);
void quoteString(Formatter &f, const String &s, char16 quote);
}
#endif /* formatter_h___ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -17,7 +17,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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
@ -40,56 +40,39 @@
#include "token.h"
#include "world.h"
namespace JavaScript
namespace JavaScript
{
class Lexer {
enum {tokenLookahead = 2}; // Number of tokens that can be
// simultaneously live
enum {tokenLookahead = 2}; // Number of tokens that can be simultaneously live
#ifdef DEBUG
enum {tokenGuard = 10}; // Number of invalid tokens added to
// circular token buffer to catch
// references to old tokens
enum {tokenGuard = 10}; // Number of invalid tokens added to circular token buffer to catch references to old tokens
#else
enum {tokenGuard = 0}; // Number of invalid tokens added to
// circular token buffer to catch
// references to old tokens
enum {tokenGuard = 0}; // Number of invalid tokens added to circular token buffer to catch references to old tokens
#endif
// Token lookahead buffer size
enum {tokenBufferSize = tokenLookahead + tokenGuard};
Token tokens[tokenBufferSize]; // Circular buffer of recently read or
// lookahead tokens
Token *nextToken; // Address of next Token in the
// circular buffer to be returned by
// get()
int nTokensFwd; // Net number of Tokens on which
// unget() has been called; these
// Tokens are ahead of nextToken
Token tokens[tokenBufferSize]; // Circular buffer of recently read or lookahead tokens
Token *nextToken; // Address of next Token in the circular buffer to be returned by get()
int nTokensFwd; // Net number of Tokens on which unget() has been called; these Tokens are ahead of nextToken
#ifdef DEBUG
int nTokensBack; // Number of Tokens on which unget()
// can be called; these Tokens are
// beind nextToken
bool savedPreferRegExp[tokenBufferSize]; // Circular buffer of saved
// values of preferRegExp to
// get() calls
int nTokensBack; // Number of Tokens on which unget() can be called; these Tokens are beind nextToken
bool savedPreferRegExp[tokenBufferSize]; // Circular buffer of saved values of preferRegExp to get() calls
#endif
bool lexingUnit; // True if lexing a unit identifier
// immediately following a number
bool lexingUnit; // True if lexing a unit identifier immediately following a number
public:
World &world;
Reader reader;
Lexer(World &world, const String &source, const String &sourceLocation,
uint32 initialLineNum = 1);
Lexer(World &world, const String &source, const String &sourceLocation, uint32 initialLineNum = 1);
const Token &get(bool preferRegExp);
const Token *eat(bool preferRegExp, Token::Kind kind);
const Token &peek(bool preferRegExp);
void redesignate(bool preferRegExp);
void unget();
uint32 getPos() const;
private:
void syntaxError(const char *message, uint backUp = 1);
char16 getChar();
@ -97,7 +80,7 @@ namespace JavaScript
char16 peekChar();
char16 internalPeekChar(char16 ch);
bool testChar(char16 ch);
char16 lexEscape(bool unicodeOnly);
bool lexIdentifier(String &s, bool allowLeadingDigit);
bool lexNumeral();
@ -106,20 +89,16 @@ namespace JavaScript
void lexToken(bool preferRegExp);
};
#ifndef DEBUG
inline void Lexer::redesignate(bool) {} // See description for the DEBUG
// version inside parser.cpp
inline void Lexer::redesignate(bool) {} // See description for the DEBUG version inside lexer.cpp
#endif
// Return the position of the first character of the next token,
// which must have been peeked.
inline uint32
Lexer::getPos() const
// Return the position of the first character of the next token, which must have been peeked.
inline uint32 Lexer::getPos() const
{
ASSERT(nTokensFwd);
return nextToken->getPos();
}
}
#endif /* lexer_h___ */

Просмотреть файл

@ -60,10 +60,6 @@ namespace JavaScript {
Identifier(const Token &t) {
return new(getArena()) IdentifierExprNode(t);
}
static IdentifierList *
ListedIdentifier(String &name) {
return new(getArena()) IdentifierList(*new StringAtom(name));
}
#if 0
static QualifiedIdentifierNode
QualifiedIdentifier(Node qualifier, IdentifierNode identifier ) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,84 +1,82 @@
/* -*- 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.
*/
*
* 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 <algorithm>
#include "reader.h"
namespace JavaScript
{
namespace JS = JavaScript;
// Create a Reader reading characters from the source string.
// sourceLocation describes the origin of the source and may be used for
// error messages. initialLineNum is the line number of the first line of the
// source string.
Reader::Reader(const String &source, const String &sourceLocation,
uint32 initialLineNum):
source(source + uni::null), sourceLocation(sourceLocation),
initialLineNum(initialLineNum)
{
begin = p = this->source.data();
end = begin + this->source.size() - 1;
JS::Reader::Reader(const String &source, const String &sourceLocation, uint32 initialLineNum):
source(source + uni::null), sourceLocation(sourceLocation), initialLineNum(initialLineNum)
{
begin = p = this->source.data();
end = begin + this->source.size() - 1;
#ifdef DEBUG
recordString = 0;
recordString = 0;
#endif
beginLine();
}
beginLine();
}
// Mark the beginning of a line. Call this after reading every line break to
// fill out the line start table.
void
Reader::beginLine()
{
ASSERT(p <= end && (!linePositions.size() || p > linePositions.back()));
linePositions.push_back(p);
}
void JS::Reader::beginLine()
{
ASSERT(p <= end && (!linePositions.size() || p > linePositions.back()));
linePositions.push_back(p);
}
// Return the number of the line containing the given character position.
// The line starts should have been recorded by calling beginLine.
uint32
Reader::posToLineNum(uint32 pos) const
{
ASSERT(pos <= getPos());
std::vector<const char16 *>::const_iterator i =
std::upper_bound(linePositions.begin(), linePositions.end(),
begin + pos);
ASSERT(i != linePositions.begin());
return static_cast<uint32>(i-1 - linePositions.begin()) +
initialLineNum;
}
uint32 JS::Reader::posToLineNum(uint32 pos) const
{
ASSERT(pos <= getPos());
std::vector<const char16 *>::const_iterator i =
std::upper_bound(linePositions.begin(), linePositions.end(), begin + pos);
ASSERT(i != linePositions.begin());
return static_cast<uint32>(i-1 - linePositions.begin()) +
initialLineNum;
}
// Return the character position as well as pointers to the beginning and end
// (not including the line terminator) of the nth line. If lineNum is out of
// range, return 0 and two nulls. The line starts should have been recorded by
@ -86,131 +84,126 @@ namespace JavaScript
// manually finds the line ending by searching for a line break; otherwise,
// getLine assumes that the line ends one character before the beginning
// of the next line.
uint32
Reader::getLine(uint32 lineNum, const char16 *&lineBegin,
const char16 *&lineEnd) const
{
lineBegin = 0;
lineEnd = 0;
if (lineNum < initialLineNum)
return 0;
lineNum -= initialLineNum;
if (lineNum >= linePositions.size())
return 0;
lineBegin = linePositions[lineNum];
const char16 *e;
++lineNum;
if (lineNum < linePositions.size())
e = linePositions[lineNum] - 1;
else {
e = lineBegin;
const char16 *end = Reader::end;
while (e != end && !isLineBreak(*e))
++e;
}
lineEnd = e;
return static_cast<uint32>(lineBegin - begin);
uint32 JS::Reader::getLine(uint32 lineNum, const char16 *&lineBegin, const char16 *&lineEnd) const
{
lineBegin = 0;
lineEnd = 0;
if (lineNum < initialLineNum)
return 0;
lineNum -= initialLineNum;
if (lineNum >= linePositions.size())
return 0;
lineBegin = linePositions[lineNum];
const char16 *e;
++lineNum;
if (lineNum < linePositions.size())
e = linePositions[lineNum] - 1;
else {
e = lineBegin;
const char16 *end = Reader::end;
while (e != end && !isLineBreak(*e))
++e;
}
lineEnd = e;
return static_cast<uint32>(lineBegin - begin);
}
// Begin accumulating characters into the recordString, whose initial value is
// ignored and cleared. Each character passed to recordChar() is added to the
// end of the recordString. Recording ends when endRecord() or beginLine()
// is called. Recording is significantly optimized when the characters passed
// to readChar() are the same characters as read by get(). In this case the
// record String does not get allocated until endRecord() is called or a
// recorded String does not get allocated until endRecord() is called or a
// discrepancy appears between get() and recordChar().
void
Reader::beginRecording(String &recordString)
{
Reader::recordString = &recordString;
recordBase = p;
recordPos = p;
}
void JS::Reader::beginRecording(String &recordString)
{
Reader::recordString = &recordString;
recordBase = p;
recordPos = p;
}
// Append ch to the recordString.
void
Reader::recordChar(char16 ch)
{
ASSERT(recordString);
if (recordPos) {
if (recordPos != end && *recordPos == ch) {
recordPos++;
return;
} else {
recordString->assign(recordBase, recordPos);
recordPos = 0;
}
void JS::Reader::recordChar(char16 ch)
{
ASSERT(recordString);
if (recordPos) {
if (recordPos != end && *recordPos == ch) {
recordPos++;
return;
} else {
recordString->assign(recordBase, recordPos);
recordPos = 0;
}
*recordString += ch;
}
*recordString += ch;
}
// Finish recording characters into the recordString that was last passed to
// beginRecording(). Return that recordString.
String &
Reader::endRecording()
{
String *rs = recordString;
ASSERT(rs);
if (recordPos)
rs->assign(recordBase, recordPos);
recordString = 0;
return *rs;
}
JS::String &JS::Reader::endRecording()
{
String *rs = recordString;
ASSERT(rs);
if (recordPos)
rs->assign(recordBase, recordPos);
recordString = 0;
return *rs;
}
// Report an error at the given character position in the source code.
void
Reader::error(Exception::Kind kind, const String &message, uint32 pos)
{
uint32 lineNum = posToLineNum(pos);
const char16 *lineBegin;
const char16 *lineEnd;
uint32 linePos = getLine(lineNum, lineBegin, lineEnd);
ASSERT(lineBegin && lineEnd && linePos <= pos);
throw Exception(kind, message, sourceLocation, lineNum, pos - linePos,
pos, lineBegin, lineEnd);
}
void JS::Reader::error(Exception::Kind kind, const String &message, uint32 pos)
{
uint32 lineNum = posToLineNum(pos);
const char16 *lineBegin;
const char16 *lineEnd;
uint32 linePos = getLine(lineNum, lineBegin, lineEnd);
ASSERT(lineBegin && lineEnd && linePos <= pos);
throw Exception(kind, message, sourceLocation, lineNum, pos - linePos, pos, lineBegin, lineEnd);
}
// Read a line from the input file, including the trailing line break character.
// Return the total number of characters read, which is str's length.
// Translate <CR> and <CR><LF> sequences to <LF> characters; a <CR><LF> sequence
// only counts as one character.
size_t
LineReader::readLine(string &str)
{
int ch;
bool oldCRWasLast = crWasLast;
crWasLast = false;
size_t JS::LineReader::readLine(string &str)
{
int ch;
bool oldCRWasLast = crWasLast;
crWasLast = false;
str.resize(0);
while ((ch = getc(in)) != EOF) {
if (ch == '\n') {
if (!str.size() && oldCRWasLast)
continue;
str += '\n';
break;
}
if (ch == '\r') {
crWasLast = true;
str += '\n';
break;
}
str += static_cast<char>(ch);
str.resize(0);
while ((ch = getc(in)) != EOF) {
if (ch == '\n') {
if (!str.size() && oldCRWasLast)
continue;
str += '\n';
break;
}
return str.size();
if (ch == '\r') {
crWasLast = true;
str += '\n';
break;
}
str += static_cast<char>(ch);
}
size_t
LineReader::readLine(String &wstr)
{
string str;
size_t n = readLine(str);
wstr.resize(n);
std::transform(str.begin(), str.end(), wstr.begin(), widen);
return n;
}
} /* namespace JavaScript */
return str.size();
}
// Same as readLine of a string except that widens the resulting characters to Unicode.
size_t JS::LineReader::readLine(String &wstr)
{
string str;
size_t n = readLine(str);
wstr.resize(n);
std::transform(str.begin(), str.end(), wstr.begin(), widen);
return n;
}

Просмотреть файл

@ -17,7 +17,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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
@ -46,31 +46,25 @@ namespace JavaScript {
// Calling get() yields all of the characters in sequence.
// One character may be read
// past the end of the source; that character appears as a null.
class Reader {
const char16 *begin; // Beginning of source text
const char16 *p; // Position in source text
const char16 *end; // End of source text; *end is a null character
const char16 *begin; // Beginning of source text
const char16 *p; // Position in source text
const char16 *end; // End of source text; *end is a null character
public:
const String source; // Source text
const String sourceLocation; // Description of location from which
// the source text came
const String source; // Source text
const String sourceLocation; // Description of location from which the source text came
private:
const uint32 initialLineNum; // One-based number of current line
std::vector<const char16 *> linePositions; // Array of line starts
// recorded by beginLine()
const uint32 initialLineNum; // One-based number of current line
std::vector<const char16 *> linePositions; // Array of line starts recorded by beginLine()
String *recordString; // String, if any, into which recordChar()
// records characters; not owned by the Reader
const char16 *recordBase; // Position of last beginRecording() call
const char16 *recordPos; // Position of last recordChar() call;
// nil if a discrepancy occurred
public:
Reader(const String &source, const String &sourceLocation,
uint32 initialLineNum = 1);
String *recordString; // String, if any, into which recordChar() records characters; not owned by the Reader
const char16 *recordBase; // Position of last beginRecording() call
const char16 *recordPos; // Position of last recordChar() call; nil if a discrepancy occurred
public:
Reader(const String &source, const String &sourceLocation, uint32 initialLineNum = 1);
private:
Reader(const Reader&); // No copy constructor
void operator=(const Reader&);// No assignment operator
Reader(const Reader&); // No copy constructor
void operator=(const Reader&); // No assignment operator
public:
char16 get() {ASSERT(p <= end);return *p++;}
@ -78,13 +72,13 @@ namespace JavaScript {
void unget(uint32 n = 1) {ASSERT(p >= begin + n); p -= n;}
uint32 getPos() const {return static_cast<uint32>(p - begin);}
void setPos(uint32 pos) {ASSERT(pos <= getPos()); p = begin + pos;}
bool eof() const {ASSERT(p <= end); return p == end;}
bool peekEof(char16 ch) const {
// Faster version. ch is the result of a peek
ASSERT(p <= end && *p == ch);
return !ch && p == end;
}
}
bool pastEof() const {return p == end+1;}
bool getEof(char16 ch) const {
// Faster version. ch is the result of a get
@ -92,22 +86,22 @@ namespace JavaScript {
}
void beginLine();
uint32 posToLineNum(uint32 pos) const;
uint32 getLine(uint32 lineNum, const char16 *&lineBegin,
const char16 *&lineEnd) const;
uint32 getLine(uint32 lineNum, const char16 *&lineBegin, const char16 *&lineEnd) const;
void beginRecording(String &recordString);
void recordChar(char16 ch);
String &endRecording();
void error(Exception::Kind kind, const String &message, uint32 pos);
};
class LineReader {
FILE *in; // File from which currently reading
bool crWasLast; // True if a CR character was the last one read
FILE *in; // File from which currently reading
bool crWasLast; // True if a CR character was the last one read
public:
explicit LineReader(FILE *in): in(in), crWasLast(false) {}
size_t readLine(string &str);
size_t readLine(String &wstr);
};

Просмотреть файл

@ -1,362 +1,360 @@
/* -*- 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.
*/
*
* 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 "token.h"
#include "formatter.h"
#include "world.h"
namespace JavaScript
{
const char *const Token::kindNames[kindsEnd] = {
namespace JS = JavaScript;
// Special
"end of input", // end
"number", // number
"string", // string
"unit", // unit
"regular expression", // regExp
// Punctuators
"(", // openParenthesis
")", // closeParenthesis
"[", // openBracket
"]", // closeBracket
"{", // openBrace
"}", // closeBrace
",", // comma
";", // semicolon
".", // dot
"..", // doubleDot
"...", // tripleDot
"->", // arrow
":", // colon
"::", // doubleColon
"#", // pound
"@", // at
"++", // increment
"--", // decrement
"~", // complement
"!", // logicalNot
"*", // times
"/", // divide
"%", // modulo
"+", // plus
"-", // minus
"<<", // leftShift
">>", // rightShift
">>>", // logicalRightShift
"&&", // logicalAnd
"^^", // logicalXor
"||", // logicalOr
"&", // bitwiseAnd
"^", // bitwiseXor
"|", // bitwiseOr
"=", // assignment
"*=", // timesEquals
"/=", // divideEquals
"%=", // moduloEquals
"+=", // plusEquals
"-=", // minusEquals
"<<=", // leftShiftEquals
">>=", // rightShiftEquals
">>>=", // logicalRightShiftEquals
"&&=", // logicalAndEquals
"^^=", // logicalXorEquals
"||=", // logicalOrEquals
"&=", // bitwiseAndEquals
"^=", // bitwiseXorEquals
"|=", // bitwiseOrEquals
"==", // equal
"!=", // notEqual
"<", // lessThan
"<=", // lessThanOrEqual
">", // greaterThan
">=", // greaterThanOrEqual
"===", // identical
"!==", // notIdentical
"?", // question
const char *const JS::Token::kindNames[kindsEnd] = {
// Reserved words
"abstract", // Abstract
"break", // Break
"case", // Case
"catch", // Catch
"class", // Class
"const", // Const
"continue", // Continue
"debugger", // Debugger
"default", // Default
"delete", // Delete
"do", // Do
"else", // Else
"enum", // Enum
"export", // Export
"extends", // Extends
"false", // False
"final", // Final
"finally", // Finally
"for", // For
"function", // Function
"goto", // Goto
"if", // If
"implements", // Implements
"import", // Import
"in", // In
"instanceof", // Instanceof
"interface", // Interface
"namespace", // Namespace
"native", // Native
"new", // New
"null", // Null
"package", // Package
"private", // Private
"protected", // Protected
"public", // Public
"return", // Return
"static", // Static
"super", // Super
"switch", // Switch
"synchronized", // Synchronized
"this", // This
"throw", // Throw
"throws", // Throws
"transient", // Transient
"true", // True
"try", // Try
"typeof", // Typeof
"use", // Use
"var", // Var
"void", // Void
"volatile", // Volatile
"while", // While
"with", // With
// Special
"end of input", // end
"number", // number
"string", // string
"unit", // unit
"regular expression", // regExp
// Non-reserved words
"eval", // Eval
"exclude", // Exclude
"get", // Get
"include", // Include
"set" // Set
};
// Punctuators
"(", // openParenthesis
")", // closeParenthesis
"[", // openBracket
"]", // closeBracket
"{", // openBrace
"}", // closeBrace
",", // comma
";", // semicolon
".", // dot
"..", // doubleDot
"...", // tripleDot
"->", // arrow
":", // colon
"::", // doubleColon
"#", // pound
"@", // at
"++", // increment
"--", // decrement
"~", // complement
"!", // logicalNot
"*", // times
"/", // divide
"%", // modulo
"+", // plus
"-", // minus
"<<", // leftShift
">>", // rightShift
">>>", // logicalRightShift
"&&", // logicalAnd
"^^", // logicalXor
"||", // logicalOr
"&", // bitwiseAnd
"^", // bitwiseXor
"|", // bitwiseOr
"=", // assignment
"*=", // timesEquals
"/=", // divideEquals
"%=", // moduloEquals
"+=", // plusEquals
"-=", // minusEquals
"<<=", // leftShiftEquals
">>=", // rightShiftEquals
">>>=", // logicalRightShiftEquals
"&&=", // logicalAndEquals
"^^=", // logicalXorEquals
"||=", // logicalOrEquals
"&=", // bitwiseAndEquals
"^=", // bitwiseXorEquals
"|=", // bitwiseOrEquals
"==", // equal
"!=", // notEqual
"<", // lessThan
"<=", // lessThanOrEqual
">", // greaterThan
">=", // greaterThanOrEqual
"===", // identical
"!==", // notIdentical
"?", // question
const uchar followRet = 1<<Token::canFollowReturn;
const uchar isAttr = 1<<Token::isAttribute |
1<<Token::canFollowAttribute;
const uchar followAttr = 1<<Token::canFollowAttribute;
const uchar followGet = 1<<Token::canFollowGet;
// Reserved words
"abstract", // Abstract
"as", // As
"break", // Break
"case", // Case
"catch", // Catch
"class", // Class
"const", // Const
"continue", // Continue
"debugger", // Debugger
"default", // Default
"delete", // Delete
"do", // Do
"else", // Else
"enum", // Enum
"export", // Export
"extends", // Extends
"false", // False
"final", // Final
"finally", // Finally
"for", // For
"function", // Function
"goto", // Goto
"if", // If
"implements", // Implements
"import", // Import
"in", // In
"instanceof", // Instanceof
"interface", // Interface
"namespace", // Namespace
"native", // Native
"new", // New
"null", // Null
"package", // Package
"private", // Private
"protected", // Protected
"public", // Public
"return", // Return
"static", // Static
"super", // Super
"switch", // Switch
"synchronized", // Synchronized
"this", // This
"throw", // Throw
"throws", // Throws
"transient", // Transient
"true", // True
"try", // Try
"typeof", // Typeof
"use", // Use
"var", // Var
"void", // Void
"volatile", // Volatile
"while", // While
"with", // With
const uchar Token::kindFlags[kindsEnd] = {
// Special
followRet, // end
0, // number
0, // string
0, // unit
0, // regExp
// Punctuators
0, // openParenthesis
0, // closeParenthesis
0, // openBracket
0, // closeBracket
followAttr, // openBrace
followRet, // closeBrace
0, // comma
followRet, // semicolon
0, // dot
0, // doubleDot
0, // tripleDot
0, // arrow
0, // colon
0, // doubleColon
0, // pound
0, // at
0, // increment
0, // decrement
0, // complement
0, // logicalNot
0, // times
0, // divide
0, // modulo
0, // plus
0, // minus
0, // leftShift
0, // rightShift
0, // logicalRightShift
0, // logicalAnd
0, // logicalXor
0, // logicalOr
0, // bitwiseAnd
0, // bitwiseXor
0, // bitwiseOr
0, // assignment
0, // timesEquals
0, // divideEquals
0, // moduloEquals
0, // plusEquals
0, // minusEquals
0, // leftShiftEquals
0, // rightShiftEquals
0, // logicalRightShiftEquals
0, // logicalAndEquals
0, // logicalXorEquals
0, // logicalOrEquals
0, // bitwiseAndEquals
0, // bitwiseXorEquals
0, // bitwiseOrEquals
0, // equal
0, // notEqual
0, // lessThan
0, // lessThanOrEqual
0, // greaterThan
0, // greaterThanOrEqual
0, // identical
0, // notIdentical
0, // question
// Reserved words
followAttr, // Abstract
0, // Break
0, // Case
0, // Catch
followAttr, // Class
followAttr, // Const
0, // Continue
0, // Debugger
0, // Default
0, // Delete
0, // Do
followRet, // Else
0, // Enum
followAttr, // Export
0, // Extends
0, // False
isAttr, // Final
0, // Finally
0, // For
followAttr, // Function
0, // Goto
0, // If
0, // Implements
0, // Import
0, // In
0, // Instanceof
followAttr, // Interface
followAttr, // Namespace
followAttr, // Native
0, // New
0, // Null
isAttr, // Package
isAttr, // Private
followAttr, // Protected
isAttr, // Public
0, // Return
isAttr, // Static
0, // Super
0, // Switch
followAttr, // Synchronized
0, // This
0, // Throw
0, // Throws
followAttr, // Transient
0, // True
0, // Try
0, // Typeof
0, // Use
followAttr, // Var
0, // Void
isAttr, // Volatile
followRet, // While
0, // With
// Non-reserved words
isAttr|followGet, // Eval
isAttr|followGet, // Exclude
isAttr|followGet, // Get
isAttr|followGet, // Include
isAttr|followGet, // Set
isAttr|followGet // identifier
// Non-reserved words
"eval", // Eval
"exclude", // Exclude
"get", // Get
"include", // Include
"set" // Set
};
static const uchar followRet = 1<<JS::Token::canFollowReturn;
static const uchar isAttr = 1<<JS::Token::isAttribute | 1<<JS::Token::canFollowAttribute;
static const uchar followAttr = 1<<JS::Token::canFollowAttribute;
static const uchar followGet = 1<<JS::Token::canFollowGet;
const uchar JS::Token::kindFlags[kindsEnd] = {
// Special
followRet, // end
0, // number
0, // string
0, // unit
0, // regExp
// Punctuators
0, // openParenthesis
0, // closeParenthesis
0, // openBracket
0, // closeBracket
followAttr, // openBrace
followRet, // closeBrace
0, // comma
followRet, // semicolon
0, // dot
0, // doubleDot
0, // tripleDot
0, // arrow
0, // colon
0, // doubleColon
0, // pound
0, // at
0, // increment
0, // decrement
0, // complement
0, // logicalNot
0, // times
0, // divide
0, // modulo
0, // plus
0, // minus
0, // leftShift
0, // rightShift
0, // logicalRightShift
0, // logicalAnd
0, // logicalXor
0, // logicalOr
0, // bitwiseAnd
0, // bitwiseXor
0, // bitwiseOr
0, // assignment
0, // timesEquals
0, // divideEquals
0, // moduloEquals
0, // plusEquals
0, // minusEquals
0, // leftShiftEquals
0, // rightShiftEquals
0, // logicalRightShiftEquals
0, // logicalAndEquals
0, // logicalXorEquals
0, // logicalOrEquals
0, // bitwiseAndEquals
0, // bitwiseXorEquals
0, // bitwiseOrEquals
0, // equal
0, // notEqual
0, // lessThan
0, // lessThanOrEqual
0, // greaterThan
0, // greaterThanOrEqual
0, // identical
0, // notIdentical
0, // question
// Reserved words
isAttr, // Abstract
0, // As
0, // Break
0, // Case
0, // Catch
followAttr, // Class
followAttr, // Const
0, // Continue
0, // Debugger
0, // Default
0, // Delete
0, // Do
followRet, // Else
0, // Enum
followAttr, // Export
0, // Extends
isAttr, // False
isAttr, // Final
0, // Finally
0, // For
followAttr, // Function
0, // Goto
0, // If
0, // Implements
0, // Import
0, // In
0, // Instanceof
followAttr, // Interface
followAttr, // Namespace
followAttr, // Native
0, // New
0, // Null
isAttr, // Package
isAttr, // Private
followAttr, // Protected
isAttr, // Public
0, // Return
isAttr, // Static
0, // Super
0, // Switch
followAttr, // Synchronized
0, // This
0, // Throw
0, // Throws
followAttr, // Transient
isAttr, // True
0, // Try
0, // Typeof
0, // Use
followAttr, // Var
0, // Void
isAttr, // Volatile
followRet, // While
0, // With
// Non-reserved words
isAttr|followGet, // Eval
isAttr|followGet, // Exclude
isAttr|followGet, // Get
isAttr|followGet, // Include
isAttr|followGet, // Set
isAttr|followGet // identifier
};
// Initialize the keywords in the given world.
void
Token::initKeywords(World &world)
{
const char *const*keywordName = kindNames + keywordsBegin;
for (Kind kind = keywordsBegin; kind != keywordsEnd;
kind = Kind(kind+1))
world.identifiers[widenCString(*keywordName++)].tokenKind = kind;
}
void JS::Token::initKeywords(World &world)
{
const char *const*keywordName = kindNames + keywordsBegin;
for (Kind kind = keywordsBegin; kind != keywordsEnd;
kind = Kind(kind+1))
world.identifiers[widenCString(*keywordName++)].tokenKind = kind;
}
// Print a description of the token to f.
void
Token::print(Formatter &f, bool debug) const
{
switch (getKind()) {
case end:
f << "[end]";
break;
case number:
if (debug)
f << "[number " << /* getValue() << */ ']';
f << getChars();
break;
case unit:
if (debug)
f << "[unit]";
/* no break */
case string:
quoteString(f, getChars(), '"');
break;
case regExp:
f << '/' << getIdentifier() << '/' << getChars();
break;
case identifier:
if (debug)
f << "[identifier]";
f << getIdentifier();
break;
default:
f << getKind();
}
}
void JS::Token::print(Formatter &f, bool debug) const
{
switch (getKind()) {
case end:
f << "[end]";
break;
case number:
if (debug)
f << "[number " << /* getValue() << */ ']';
f << getChars();
break;
case unit:
if (debug)
f << "[unit]";
/* no break */
case string:
quoteString(f, getChars(), '"');
break;
case regExp:
f << '/' << getIdentifier() << '/' << getChars();
break;
case identifier:
if (debug)
f << "[identifier]";
f << getIdentifier();
break;
default:
f << getKind();
}
}

Просмотреть файл

@ -17,7 +17,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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
@ -39,177 +39,163 @@
#include "strings.h"
#include "formatter.h"
namespace JavaScript
namespace JavaScript
{
class StringAtom;
class World;
class Token {
public:
enum Kind {
// Keep synchronized with kindNames, kindFlags, and
// tokenBinaryOperatorInfos tables
// Keep synchronized with kindNames, kindFlags, and tokenBinaryOperatorInfos tables
// Special
end, // End of token stream
number, // Number
string, // String
unit, // Unit after number
regExp, // Regular expression
end, // End of token stream
number, // Number
string, // String
unit, // Unit after number
regExp, // Regular expression
// Punctuators
openParenthesis, // (
closeParenthesis, // )
openBracket, // [
closeBracket, // ]
openBrace, // {
closeBrace, // }
comma, // ,
semicolon, // ;
dot, // .
doubleDot, // ..
tripleDot, // ...
arrow, // ->
colon, // :
doubleColon, // ::
pound, // #
at, // @
increment, // ++
decrement, // --
complement, // ~
logicalNot, // !
times, // *
divide, // /
modulo, // %
plus, // +
minus, // -
leftShift, // <<
rightShift, // >>
logicalRightShift, // >>>
logicalAnd, // &&
logicalXor, // ^^
logicalOr, // ||
bitwiseAnd, // &
// These must be at constant offsets from logicalAnd ... logicalOr
bitwiseXor, // ^
bitwiseOr, // |
assignment, // =
openParenthesis, // (
closeParenthesis, // )
openBracket, // [
closeBracket, // ]
openBrace, // {
closeBrace, // }
comma, // ,
semicolon, // ;
dot, // .
doubleDot, // ..
tripleDot, // ...
arrow, // ->
colon, // :
doubleColon, // ::
pound, // #
at, // @
// These must be at constant offsets from times ... bitwiseOr
timesEquals, // *=
divideEquals, // /=
moduloEquals, // %=
plusEquals, // +=
minusEquals, // -=
leftShiftEquals, // <<=
rightShiftEquals, // >>=
logicalRightShiftEquals, // >>>=
logicalAndEquals, // &&=
logicalXorEquals, // ^^=
logicalOrEquals, // ||=
bitwiseAndEquals, // &=
bitwiseXorEquals, // ^=
bitwiseOrEquals, // |=
equal, // ==
notEqual, // !=
lessThan, // <
lessThanOrEqual, // <=
greaterThan, // >
// >, >= must be at constant offsets from <, <=
greaterThanOrEqual, // >=
identical, // ===
notIdentical, // !==
question, // ?
increment, // ++
decrement, // --
complement, // ~
logicalNot, // !
times, // *
divide, // /
modulo, // %
plus, // +
minus, // -
leftShift, // <<
rightShift, // >>
logicalRightShift, // >>>
logicalAnd, // &&
logicalXor, // ^^
logicalOr, // ||
bitwiseAnd, // & These must be at constant offsets from logicalAnd ... logicalOr
bitwiseXor, // ^
bitwiseOr, // |
assignment, // =
timesEquals, // *= These must be at constant offsets from times ... bitwiseOr
divideEquals, // /=
moduloEquals, // %=
plusEquals, // +=
minusEquals, // -=
leftShiftEquals, // <<=
rightShiftEquals, // >>=
logicalRightShiftEquals, // >>>=
logicalAndEquals, // &&=
logicalXorEquals, // ^^=
logicalOrEquals, // ||=
bitwiseAndEquals, // &=
bitwiseXorEquals, // ^=
bitwiseOrEquals, // |=
equal, // ==
notEqual, // !=
lessThan, // <
lessThanOrEqual, // <=
greaterThan, // > >, >= must be at constant offsets from <, <=
greaterThanOrEqual, // >=
identical, // ===
notIdentical, // !==
question, // ?
// Reserved words
Abstract, // abstract
Break, // break
Case, // case
Catch, // catch
Class, // class
Const, // const
Continue, // continue
Debugger, // debugger
Default, // default
Delete, // delete
Do, // do
Else, // else
Enum, // enum
Export, // export
Extends, // extends
False, // false
Final, // final
Finally, // finally
For, // for
Function, // function
Goto, // goto
If, // if
Implements, // implements
Import, // import
In, // in
Instanceof, // instanceof
Interface, // interface
Namespace, // namespace
Native, // native
New, // new
Null, // null
Package, // package
Private, // private
Protected, // protected
Public, // public
Return, // return
Static, // static
Super, // super
Switch, // switch
Synchronized, // synchronized
This, // this
Throw, // throw
Throws, // throws
Transient, // transient
True, // true
Try, // try
Typeof, // typeof
Use, // use
Var, // var
Void, // void
Volatile, // volatile
While, // while
With, // with
Abstract, // abstract
As, // as
Break, // break
Case, // case
Catch, // catch
Class, // class
Const, // const
Continue, // continue
Debugger, // debugger
Default, // default
Delete, // delete
Do, // do
Else, // else
Enum, // enum
Export, // export
Extends, // extends
False, // false
Final, // final
Finally, // finally
For, // for
Function, // function
Goto, // goto
If, // if
Implements, // implements
Import, // import
In, // in
Instanceof, // instanceof
Interface, // interface
Namespace, // namespace
Native, // native
New, // new
Null, // null
Package, // package
Private, // private
Protected, // protected
Public, // public
Return, // return
Static, // static
Super, // super
Switch, // switch
Synchronized, // synchronized
This, // this
Throw, // throw
Throws, // throws
Transient, // transient
True, // true
Try, // try
Typeof, // typeof
Use, // use
Var, // var
Void, // void
Volatile, // volatile
While, // while
With, // with
// Non-reserved words
Eval, // eval
Exclude, // exclude
Get, // get
Include, // include
Set, // set
identifier, // Non-keyword identifier
// (may be same as a keyword if it
// contains an escape code)
kindsEnd, // End of token kinds
keywordsBegin = Abstract, // Beginning of range of special
// identifier tokens
keywordsEnd = identifier, // End of range of special identifier
// tokens
nonreservedBegin = Eval, // Beginning of range of non-reserved
// words
Eval, // eval
Exclude, // exclude
Get, // get
Include, // include
Set, // set
identifier, // Non-keyword identifier (may be same as a keyword if it contains an escape code)
kindsEnd, // End of token kinds
keywordsBegin = Abstract, // Beginning of range of special identifier tokens
keywordsEnd = identifier, // End of range of special identifier tokens
nonreservedBegin = Eval, // Beginning of range of non-reserved words
nonreservedEnd = identifier, // End of range of non-reserved words
kindsWithCharsBegin = number, // Beginning of range of tokens for
// which the chars field (below) is
// valid
kindsWithCharsEnd = regExp+1 // End of range of tokens for which
// the chars field (below) is valid
kindsWithCharsBegin = number, // Beginning of range of tokens for which the chars field (below) is valid
kindsWithCharsEnd = regExp+1 // End of range of tokens for which the chars field (below) is valid
};
#define CASE_TOKEN_ATTRIBUTE_IDENTIFIER \
Token::Eval: \
case Token::Exclude: \
@ -227,13 +213,10 @@ namespace JavaScript
case Token::identifier
enum Flag {
isAttribute, // True if this token is an attribute
canFollowAttribute, // True if this token is an attribute or can
// follow an attribute
canFollowReturn, // True if this token can follow a return
// without an expression
canFollowGet // True if this token can follow a get or
// set in a FunctionName
isAttribute, // True if this token is an attribute
canFollowAttribute, // True if this token is an attribute or can follow an attribute
canFollowReturn, // True if this token can follow a return without an expression
canFollowGet // True if this token can follow a get or set in a FunctionName
};
private:
@ -241,65 +224,38 @@ namespace JavaScript
static const uchar kindFlags[kindsEnd];
#ifdef DEBUG
bool valid; // True if this token has been initialized
bool valid; // True if this token has been initialized
#endif
Kind kind; // The token's kind
bool lineBreak; // True if line break precedes this token
uint32 pos; // Source position of this token
const StringAtom *id; // The token's characters; non-nil for
// identifiers, keywords, and regular
// expressions only
String chars; // The token's characters; valid for strings, units,
// numbers, and regular expression flags only
float64 value; // The token's value (numbers only)
Kind kind; // The token's kind
bool lineBreak; // True if line break precedes this token
uint32 pos; // Source position of this token
const StringAtom *id; // The token's characters; non-nil for identifiers, keywords, and regular expressions only
String chars; // The token's characters; valid for strings, units, numbers, and regular expression flags only
float64 value; // The token's value (numbers only)
#ifdef DEBUG
Token(): valid(false) {}
#endif
public:
static void initKeywords(World &world);
static bool isSpecialKind(Kind kind) {
return kind <= regExp || kind == identifier;
}
static const char *kindName(Kind kind) {
ASSERT(uint(kind) < kindsEnd);
return kindNames[kind];
}
static bool isSpecialKind(Kind kind) {return kind <= regExp || kind == identifier;}
static const char *kindName(Kind kind) {ASSERT(uint(kind) < kindsEnd); return kindNames[kind];}
Kind getKind() const {ASSERT(valid); return kind;}
bool hasKind(Kind k) const {ASSERT(valid); return kind == k;}
bool hasIdentifierKind() const {
ASSERT(nonreservedEnd == identifier && kindsEnd == identifier+1);
return kind >= nonreservedBegin;
}
bool getFlag(Flag f) const {
ASSERT(valid);
return (kindFlags[kind] & 1<<f) != 0;
}
bool hasIdentifierKind() const {ASSERT(nonreservedEnd == identifier && kindsEnd == identifier+1); return kind >= nonreservedBegin;}
bool getFlag(Flag f) const {ASSERT(valid); return (kindFlags[kind] & 1<<f) != 0;}
bool getLineBreak() const {ASSERT(valid); return lineBreak;}
uint32 getPos() const {ASSERT(valid); return pos;}
const StringAtom &getIdentifier() const {
ASSERT(valid && id);
return *id;
}
const String &getChars() const {
ASSERT(valid && kind >= kindsWithCharsBegin &&
kind < kindsWithCharsEnd);
return chars;
}
float64 getValue() const {
ASSERT(valid && kind == number);
return value;
}
friend Formatter &operator<<(Formatter &f, Kind k) {
f << kindName(k);
return f;
}
const StringAtom &getIdentifier() const {ASSERT(valid && id); return *id;}
const String &getChars() const {ASSERT(valid && kind >= kindsWithCharsBegin && kind < kindsWithCharsEnd); return chars;}
float64 getValue() const {ASSERT(valid && kind == number); return value;}
friend Formatter &operator<<(Formatter &f, Kind k) {f << kindName(k); return f;}
void print(Formatter &f, bool debug = false) const;
friend class Lexer;
};
}
#endif /* token_h___ */

Просмотреть файл

@ -1,35 +1,35 @@
/* -*- 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.
*/
*
* 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 "utilities.h"
#ifdef DEBUG
@ -44,9 +44,9 @@
# endif
#endif
namespace JavaScript
{
namespace JS = JavaScript;
#ifdef DEBUG
#ifdef XP_MAC
// PStrFromCStr converts the source C string to a destination
@ -54,112 +54,103 @@ namespace JavaScript
// be truncated to fit into an Str255 if necessary.
// If the C String pointer is NULL, the pascal string's length is
// set to zero.
static void
PStrFromCStr(const char* src, Str255 &dst)
{
int length = 0;
if (src)
{
char *p = reinterpret_cast<char *>(&dst[1]);
int spaceLeft = 255;
char ch;
while ((ch = *src++) != 0) {
*p++ = ch;
if (--spaceLeft == 0)
break;
}
length = 255 - spaceLeft;
}
dst[0] = (uchar)length;
}
static void
jsdebugstr(const char *debuggerMsg)
{
Str255 pStr;
PStrFromCStr(debuggerMsg, pStr);
DebugStr(pStr);
}
static void
dprintf(const char *format, ...)
{
std::va_list ap;
char buffer[4096];
va_start(ap, format);
std::vsprintf(buffer, format, ap);
va_end(ap);
jsdebugstr(buffer);
}
#endif /* XP_MAC */
void
Assert(const char *s, const char *file, int line)
{
static void PStrFromCStr(const char* src, Str255 &dst)
{
int length = 0;
if (src)
{
char *p = reinterpret_cast<char *>(&dst[1]);
int spaceLeft = 255;
char ch;
while ((ch = *src++) != 0) {
*p++ = ch;
if (--spaceLeft == 0)
break;
}
length = 255 - spaceLeft;
}
dst[0] = (uchar)length;
}
static void jsdebugstr(const char *debuggerMsg)
{
Str255 pStr;
PStrFromCStr(debuggerMsg, pStr);
DebugStr(pStr);
}
static void dprintf(const char *format, ...)
{
std::va_list ap;
char buffer[4096];
va_start(ap, format);
std::vsprintf(buffer, format, ap);
va_end(ap);
jsdebugstr(buffer);
}
#endif /* XP_MAC */
void JS::Assert(const char *s, const char *file, int line)
{
#if defined(XP_UNIX) || defined(XP_OS2)
fprintf(std::stderr, "Assertion failure: %s, at %s:%d\n", s, file, line);
fprintf(std::stderr, "Assertion failure: %s, at %s:%d\n", s, file, line);
#endif
#ifdef XP_MAC
dprintf("Assertion failure: %s, at %s:%d\n", s, file, line);
dprintf("Assertion failure: %s, at %s:%d\n", s, file, line);
#endif
#ifdef WIN32
DebugBreak();
DebugBreak();
#endif
#ifndef XP_MAC
abort();
abort();
#endif
}
}
#endif /* DEBUG */
// Return lg2 of the least power of 2 greater than or equal to n.
// Return 0 if n is 0 or 1.
uint
ceilingLog2(uint32 n)
{
uint log2 = 0;
if (n & (n-1))
log2++;
if (n >> 16)
log2 += 16, n >>= 16;
if (n >> 8)
log2 += 8, n >>= 8;
if (n >> 4)
log2 += 4, n >>= 4;
if (n >> 2)
log2 += 2, n >>= 2;
if (n >> 1)
log2++;
return log2;
}
uint JS::ceilingLog2(uint32 n)
{
uint log2 = 0;
if (n & (n-1))
log2++;
if (n >> 16)
log2 += 16, n >>= 16;
if (n >> 8)
log2 += 8, n >>= 8;
if (n >> 4)
log2 += 4, n >>= 4;
if (n >> 2)
log2 += 2, n >>= 2;
if (n >> 1)
log2++;
return log2;
}
// Return lg2 of the greatest power of 2 less than or equal to n.
// This really just finds the highest set bit in the word.
// Return 0 if n is 0 or 1.
uint
floorLog2(uint32 n)
{
uint log2 = 0;
if (n >> 16)
log2 += 16, n >>= 16;
if (n >> 8)
log2 += 8, n >>= 8;
if (n >> 4)
log2 += 4, n >>= 4;
if (n >> 2)
log2 += 2, n >>= 2;
if (n >> 1)
log2++;
return log2;
}
uint JS::floorLog2(uint32 n)
{
uint log2 = 0;
if (n >> 16)
log2 += 16, n >>= 16;
if (n >> 8)
log2 += 8, n >>= 8;
if (n >> 4)
log2 += 4, n >>= 4;
if (n >> 2)
log2 += 2, n >>= 2;
if (n >> 1)
log2++;
return log2;
}

Просмотреть файл

@ -35,7 +35,7 @@
#define utilities_h___
#ifdef MSC_VER
// diasble long identifier warnings
// disable long identifier warnings
# pragma warning(disable: 4786)
#endif
@ -62,17 +62,15 @@ namespace JavaScript
# define DEBUG_ONLY(_stmt)
#endif
//
// Random Crap
// Mathematics
//
//
template<class N> N min(N v1, N v2) {return v1 <= v2 ? v1 : v2;}
template<class N> N max(N v1, N v2) {return v1 >= v2 ? v1 : v2;}
uint ceilingLog2(uint32 n);
uint floorLog2(uint32 n);
}
#endif /* utilities_h___ */

Просмотреть файл

@ -39,7 +39,7 @@
#include "hash.h"
namespace JavaScript {
//
// String atom management
//
@ -48,24 +48,19 @@ namespace JavaScript {
// StringAtoms A and B have the same character sequences if and only if A and
// B are the same StringAtom.
class StringAtom : public String {
class StringAtom: public String {
public:
// Token::Kind if this is a keyword; Token::identifier if not
Token::Kind tokenKind;
explicit StringAtom(const String &s) :
String(s), tokenKind(Token::identifier) {}
explicit StringAtom(const String &s): String(s), tokenKind(Token::identifier) {}
private:
StringAtom(const StringAtom&); // No copy constructor
void operator=(const StringAtom&); // No assignment operator
};
inline bool operator==(const StringAtom &s1, const StringAtom &s2) {
return &s1 == &s2;
}
inline bool operator!=(const StringAtom &s1, const StringAtom &s2) {
return &s1 != &s2;
}
inline bool operator==(const StringAtom &s1, const StringAtom &s2) {return &s1 == &s2;}
inline bool operator!=(const StringAtom &s1, const StringAtom &s2) {return &s1 != &s2;}
class StringAtomTable {
typedef HashTable<StringAtom, const String&> HT;
@ -73,10 +68,7 @@ namespace JavaScript {
public:
StringAtom &operator[](const String &s);
StringAtom &operator[](const char *s) {
return operator[](widenCString(s));
}
StringAtom &operator[](const char *s) {return operator[](widenCString(s));}
};
class World {