From cf7f6d77dae1697de3d25d5f14d121b552244faa Mon Sep 17 00:00:00 2001 From: "waldemar%netscape.com" Date: Tue, 25 Jan 2000 22:58:34 +0000 Subject: [PATCH] Added string, character, and exception utilities --- js/js2/utilities.cpp | 109 +++++++++++++++++++++++++++++--- js/js2/utilities.h | 142 +++++++++++++++++++++++++----------------- js2/src/utilities.cpp | 109 +++++++++++++++++++++++++++++--- js2/src/utilities.h | 142 +++++++++++++++++++++++++----------------- 4 files changed, 372 insertions(+), 130 deletions(-) diff --git a/js/js2/utilities.cpp b/js/js2/utilities.cpp index b50dd1d3860..39e19e30f8e 100644 --- a/js/js2/utilities.cpp +++ b/js/js2/utilities.cpp @@ -17,8 +17,10 @@ // Copyright (C) 1998 Netscape Communications Corporation. All // Rights Reserved. +#include #include #include +#include #include "utilities.h" #ifdef WIN32 @@ -159,7 +161,52 @@ uint JS::floorLog2(uint32 n) // -// From java.lang.Character.java: +// Return a String containing the characters of the null-terminated C string cstr +// (without the trailing null). +JS::String JS::widenCString(const char *cstr) +{ + size_t len = std::strlen(cstr); + String s(len, uni::null); + std::transform(cstr, cstr+len, s.begin(), widen); + return s; +} + + +// Widen and append length characters starting at chars to the end of str. +void JS::appendChars(String &str, const char *chars, size_t length) +{ + String::size_type strLen = str.size(); + str.append(length, uni::null); + std::transform(chars, chars+length, str.begin()+strLen, widen); +} + + +// Widen and append the null-terminated string cstr to the end of str. +// Return str. +JS::String &JS::operator+=(String &str, const char *cstr) +{ + appendChars(str, cstr, std::strlen(cstr)); + return str; +} + + +// Return the concatenation of str and the null-terminated string cstr. +JS::String JS::operator+(const String &str, const char *cstr) +{ + String s = widenCString(cstr); + return str + s; +} + + +// Return the concatenation of the null-terminated string cstr and str. +JS::String JS::operator+(const char *cstr, const String &str) +{ + String s = widenCString(cstr); + return s += str; +} + + +// From java.lang.Character: // // The character properties are currently encoded into 32 bits in the // following manner: @@ -1433,26 +1480,47 @@ const uint32 JS::CharInfo::a[] = { // Return c converted to upper case. If c cannot be converted to upper case, // return c unchanged. -JS::char16 JS::toUpper(char16 c) +char16 JS::toUpper(char16 c) { - uint32 code = CharInfo::cCode(c); - if (code & 0x00100000) - c = static_cast(static_cast(c) - (static_cast(code) >> 22)); + CharInfo ci(c); + if (ci.info & 0x00100000) + c = static_cast(static_cast(c) - (static_cast(ci.info) >> 22)); return c; } // Return c converted to lower case. If c cannot be converted to lower case, // return c unchanged. -JS::char16 JS::toLower(char16 c) +char16 JS::toLower(char16 c) { - uint32 code = CharInfo::cCode(c); - if (code & 0x00200000) - c = static_cast(static_cast(c) + (static_cast(code) >> 22)); + CharInfo ci(c); + if (ci.info & 0x00200000) + c = static_cast(static_cast(c) + (static_cast(ci.info) >> 22)); return c; } +// Return true if c is an ASCII hexadecimal digit, in which case store the digit's numeric value in d. +bool JS::isASCIIHexDigit(char16 c, uint &digit) +{ + uint cv = c; + + if (cv < '0') + return false; + if (cv <= '9') { + digit = cv - '0'; + return true; + } + cv |= 0x20; + if (cv >= 'a' && cv <= 'f') { + digit = cv - 'a' + 10; + return true; + } + return false; +} + + + // // C++ I/O // @@ -1479,6 +1547,29 @@ void JS::showString(ostream &out, const String &str) } +// +// Exceptions +// + + +static const char *const kindStrings[] = { + "Syntax error" // SyntaxError +}; + +// Return a null-terminated string describing the exception's kind. +const char *JS::Exception::kindString() const +{ + return kindStrings[kind]; +} + + +// Return the full error message. +JS::String JS::Exception::fullMessage() const +{ + return kindString() + (": " + message); +} + + // // Static Initializers // diff --git a/js/js2/utilities.h b/js/js2/utilities.h index da9d7d559b1..1ac65e8b182 100644 --- a/js/js2/utilities.h +++ b/js/js2/utilities.h @@ -25,6 +25,7 @@ #include #include "systemtypes.h" +using std::size_t; using std::string; using std::istream; using std::ostream; @@ -72,25 +73,16 @@ namespace JavaScript { // Unicode UTF-16 characters and strings // - // A UTF-16 character - // Use wchar_t on platforms on which wchar_t has 16 bits; otherwise use uint16. - // Note that in C++ wchar_t is a distinct type rather than a typedef for some integral type. - // Like char, a char16 can be either signed or unsigned at the implementation's discretion. - typedef wchar_t char16; - typedef unsigned wchar_t uchar16; - // A string of UTF-16 characters. Nulls are allowed just like any other character. // The string is not null-terminated. // Use wstring if char16 is wchar_t. Otherwise use basic_string. typedef std::basic_string String; - #if 0 - using std::wint_t; - const wint_t ueof = WEOF; - #else - typedef int32 wint_t; // A type that can hold any char16 plus one special value: ueof. - const wint_t ueof = -1; - #endif + typedef uint32 char16orEOF; // A type that can hold any char16 plus one special value: ueof. + const char16orEOF char16eof = static_cast(-1); + + // If c is a char16, return it; if c is char16eof, return the character \uFFFF. + inline char16 char16orEOFToChar16(char16orEOF c) {return static_cast(c);} // Special char16s namespace uni { @@ -100,11 +92,20 @@ namespace JavaScript { const char16 ls = 0x2028; const char16 ps = 0x2029; } + const uint16 firstFormatChar = 0x200C; // Lowest Unicode Cf character inline char16 widen(char ch) {return static_cast(static_cast(ch));} + String widenCString(const char *cstr); + void appendChars(String &str, const char *chars, size_t length); + String &operator+=(String &str, const char *cstr); + String operator+(const String &str, const char *cstr); + String operator+(const char *cstr, const String &str); + class CharInfo { + uint32 info; // Word from table a. + // Unicode character attribute lookup tables static const uint8 x[]; static const uint8 y[]; @@ -152,43 +153,49 @@ namespace JavaScript { LineBreakGroup // 5 Line break character [LineBreakGroup & -2 == WhiteGroup] }; - // Character classifying and mapping macros, based on java.lang.Character - static uint32 cCode(char16 c) {return a[y[x[static_cast(c)>>6]<<6 | c&0x3F]];} - static Type cType(char16 c) {return static_cast(cCode(c) & 0x1F);} - static Group cGroup(char16 c) {return static_cast(cCode(c) >> 16 & 7);} + CharInfo() {} + CharInfo(char16 c): info(a[y[x[static_cast(c)>>6]<<6 | c&0x3F]]) {} + CharInfo(const CharInfo &ci): info(ci.info) {} + + friend Type cType(const CharInfo &ci) {return static_cast(ci.info & 0x1F);} + friend Group cGroup(const CharInfo &ci) {return static_cast(ci.info >> 16 & 7);} + + friend bool isAlpha(const CharInfo &ci) + { + return ((((1 << UppercaseLetter) | (1 << LowercaseLetter) | (1 << TitlecaseLetter) | (1 << ModifierLetter) | (1 << OtherLetter)) + >> cType(ci)) & 1) != 0; + } + + friend bool isAlphanumeric(const CharInfo &ci) + { + return ((((1 << UppercaseLetter) | (1 << LowercaseLetter) | (1 << TitlecaseLetter) | (1 << ModifierLetter) | (1 << OtherLetter) | + (1 << DecimalDigitNumber) | (1 << LetterNumber)) + >> cType(ci)) & 1) != 0; + } + + // Return true if this character can start a JavaScript identifier + friend bool isIdLeading(const CharInfo &ci) {return cGroup(ci) == IdGroup;} + // Return true if this character can continue a JavaScript identifier + friend bool isIdContinuing(const CharInfo &ci) {return cGroup(ci) & -2 == IdGroup;} + + // Return true if this character is a Unicode decimal digit (Nd) character + friend bool isDecimalDigit(const CharInfo &ci) {return cType(ci) == DecimalDigitNumber;} + // Return true if this character is a Unicode white space or line break character + friend bool isSpace(const CharInfo &ci) {return cGroup(ci) & -2 == WhiteGroup;} + // Return true if this character is a Unicode line break character (LF, CR, LS, or PS) + friend bool isLineBreak(const CharInfo &ci) {return cGroup(ci) == LineBreakGroup;} + // Return true if this character is a Unicode format control character (Cf) + friend bool isFormat(const CharInfo &ci) {return cGroup(ci) == FormatGroup;} + + friend bool isUpper(const CharInfo &ci) {return cType(ci) == UppercaseLetter;} + friend bool isLower(const CharInfo &ci) {return cType(ci) == LowercaseLetter;} + + friend char16 toUpper(char16 c); + friend char16 toLower(char16 c); }; - - inline bool isAlpha(char16 c) - { - return ((((1 << CharInfo::UppercaseLetter) | (1 << CharInfo::LowercaseLetter) | (1 << CharInfo::TitlecaseLetter) | - (1 << CharInfo::ModifierLetter) | (1 << CharInfo::OtherLetter)) - >> CharInfo::cType(c)) & 1) != 0; - } - - inline bool isAlphanumeric(char16 c) - { - return ((((1 << CharInfo::UppercaseLetter) | (1 << CharInfo::LowercaseLetter) | (1 << CharInfo::TitlecaseLetter) | - (1 << CharInfo::ModifierLetter) | (1 << CharInfo::OtherLetter) | (1 << CharInfo::DecimalDigitNumber)) - >> CharInfo::cType(c)) & 1) != 0; - } - - // Return true if c can start a JavaScript identifier - inline bool isIdLeading(char16 c) {return CharInfo::cGroup(c) == CharInfo::IdGroup;} - // Return true if c can continue a JavaScript identifier - inline bool isIdContinuing(char16 c) {return CharInfo::cGroup(c) & -2 == CharInfo::IdGroup;} - - // Return true if c is a Unicode decimal digit (Nd) character - inline bool isDecimalDigit(char16 c) {return CharInfo::cType(c) == CharInfo::DecimalDigitNumber;} - // Return true if c is a Unicode white space or line break character - inline bool isSpace(char16 c) {return CharInfo::cGroup(c) & -2 == CharInfo::WhiteGroup;} - // Return true if c is a Unicode line break character (LF, CR, LS, or PS) - inline bool isLineBreak(char16 c) {return CharInfo::cGroup(c) == CharInfo::LineBreakGroup;} - - inline bool isUpper(char16 c) {return CharInfo::cType(c) == CharInfo::UppercaseLetter;} - inline bool isLower(char16 c) {return CharInfo::cType(c) == CharInfo::LowercaseLetter;} - - char16 toUpper(char16 c); - char16 toLower(char16 c); + + inline bool isASCIIDecimalDigit(char16 c) {return c >= '0' && c <= '9';} + bool isASCIIHexDigit(char16 c, uint &digit); // @@ -197,8 +204,7 @@ namespace JavaScript { // private template - class ProtoArrayBuffer - { + class ProtoArrayBuffer { protected: T *buffer; int32 length; @@ -237,8 +243,7 @@ namespace JavaScript { // ArrayBuffer allocates the array from the heap. // Use append to append nElts elements to the end of the ArrayBuffer. template - class ArrayBuffer: public ProtoArrayBuffer - { + class ArrayBuffer: public ProtoArrayBuffer { T cache[cacheSize]; public: @@ -283,8 +288,7 @@ namespace JavaScript { // A class to remember the format of an ostream so that a function may modify it internally // without changing it for the caller. - class SaveFormat - { + class SaveFormat { ostream &o; std::ios_base::fmtflags flags; char fill; @@ -304,5 +308,31 @@ namespace JavaScript { } void showString(ostream &out, const String &str); + +// +// Exceptions +// + + // A JavaScript exception (other than out-of-memory, for which we use the standard C++ + // exception bad_alloc). + struct Exception { + enum Kind { + SyntaxError + }; + + Kind kind; // The exception's kind + String message; // The detailed message + String sourceFile; // A description of the source code that caused the error + uint32 lineNum; // One-based source line number; 0 if unknown + uint32 charPos; // Zero-based character offset within the line + String sourceLine; // The text of the source line + + Exception(Kind kind, const String &message): kind(kind), message(message), lineNum(0) {} + Exception(Kind kind, const String &message, const String &sourceFile, uint32 lineNum, uint32 charPos, const String sourceLine): + kind(kind), message(message), sourceFile(sourceFile), lineNum(lineNum), charPos(charPos), sourceLine(sourceLine) {} + + const char *kindString() const; + String fullMessage() const; + }; } #endif diff --git a/js2/src/utilities.cpp b/js2/src/utilities.cpp index b50dd1d3860..39e19e30f8e 100644 --- a/js2/src/utilities.cpp +++ b/js2/src/utilities.cpp @@ -17,8 +17,10 @@ // Copyright (C) 1998 Netscape Communications Corporation. All // Rights Reserved. +#include #include #include +#include #include "utilities.h" #ifdef WIN32 @@ -159,7 +161,52 @@ uint JS::floorLog2(uint32 n) // -// From java.lang.Character.java: +// Return a String containing the characters of the null-terminated C string cstr +// (without the trailing null). +JS::String JS::widenCString(const char *cstr) +{ + size_t len = std::strlen(cstr); + String s(len, uni::null); + std::transform(cstr, cstr+len, s.begin(), widen); + return s; +} + + +// Widen and append length characters starting at chars to the end of str. +void JS::appendChars(String &str, const char *chars, size_t length) +{ + String::size_type strLen = str.size(); + str.append(length, uni::null); + std::transform(chars, chars+length, str.begin()+strLen, widen); +} + + +// Widen and append the null-terminated string cstr to the end of str. +// Return str. +JS::String &JS::operator+=(String &str, const char *cstr) +{ + appendChars(str, cstr, std::strlen(cstr)); + return str; +} + + +// Return the concatenation of str and the null-terminated string cstr. +JS::String JS::operator+(const String &str, const char *cstr) +{ + String s = widenCString(cstr); + return str + s; +} + + +// Return the concatenation of the null-terminated string cstr and str. +JS::String JS::operator+(const char *cstr, const String &str) +{ + String s = widenCString(cstr); + return s += str; +} + + +// From java.lang.Character: // // The character properties are currently encoded into 32 bits in the // following manner: @@ -1433,26 +1480,47 @@ const uint32 JS::CharInfo::a[] = { // Return c converted to upper case. If c cannot be converted to upper case, // return c unchanged. -JS::char16 JS::toUpper(char16 c) +char16 JS::toUpper(char16 c) { - uint32 code = CharInfo::cCode(c); - if (code & 0x00100000) - c = static_cast(static_cast(c) - (static_cast(code) >> 22)); + CharInfo ci(c); + if (ci.info & 0x00100000) + c = static_cast(static_cast(c) - (static_cast(ci.info) >> 22)); return c; } // Return c converted to lower case. If c cannot be converted to lower case, // return c unchanged. -JS::char16 JS::toLower(char16 c) +char16 JS::toLower(char16 c) { - uint32 code = CharInfo::cCode(c); - if (code & 0x00200000) - c = static_cast(static_cast(c) + (static_cast(code) >> 22)); + CharInfo ci(c); + if (ci.info & 0x00200000) + c = static_cast(static_cast(c) + (static_cast(ci.info) >> 22)); return c; } +// Return true if c is an ASCII hexadecimal digit, in which case store the digit's numeric value in d. +bool JS::isASCIIHexDigit(char16 c, uint &digit) +{ + uint cv = c; + + if (cv < '0') + return false; + if (cv <= '9') { + digit = cv - '0'; + return true; + } + cv |= 0x20; + if (cv >= 'a' && cv <= 'f') { + digit = cv - 'a' + 10; + return true; + } + return false; +} + + + // // C++ I/O // @@ -1479,6 +1547,29 @@ void JS::showString(ostream &out, const String &str) } +// +// Exceptions +// + + +static const char *const kindStrings[] = { + "Syntax error" // SyntaxError +}; + +// Return a null-terminated string describing the exception's kind. +const char *JS::Exception::kindString() const +{ + return kindStrings[kind]; +} + + +// Return the full error message. +JS::String JS::Exception::fullMessage() const +{ + return kindString() + (": " + message); +} + + // // Static Initializers // diff --git a/js2/src/utilities.h b/js2/src/utilities.h index da9d7d559b1..1ac65e8b182 100644 --- a/js2/src/utilities.h +++ b/js2/src/utilities.h @@ -25,6 +25,7 @@ #include #include "systemtypes.h" +using std::size_t; using std::string; using std::istream; using std::ostream; @@ -72,25 +73,16 @@ namespace JavaScript { // Unicode UTF-16 characters and strings // - // A UTF-16 character - // Use wchar_t on platforms on which wchar_t has 16 bits; otherwise use uint16. - // Note that in C++ wchar_t is a distinct type rather than a typedef for some integral type. - // Like char, a char16 can be either signed or unsigned at the implementation's discretion. - typedef wchar_t char16; - typedef unsigned wchar_t uchar16; - // A string of UTF-16 characters. Nulls are allowed just like any other character. // The string is not null-terminated. // Use wstring if char16 is wchar_t. Otherwise use basic_string. typedef std::basic_string String; - #if 0 - using std::wint_t; - const wint_t ueof = WEOF; - #else - typedef int32 wint_t; // A type that can hold any char16 plus one special value: ueof. - const wint_t ueof = -1; - #endif + typedef uint32 char16orEOF; // A type that can hold any char16 plus one special value: ueof. + const char16orEOF char16eof = static_cast(-1); + + // If c is a char16, return it; if c is char16eof, return the character \uFFFF. + inline char16 char16orEOFToChar16(char16orEOF c) {return static_cast(c);} // Special char16s namespace uni { @@ -100,11 +92,20 @@ namespace JavaScript { const char16 ls = 0x2028; const char16 ps = 0x2029; } + const uint16 firstFormatChar = 0x200C; // Lowest Unicode Cf character inline char16 widen(char ch) {return static_cast(static_cast(ch));} + String widenCString(const char *cstr); + void appendChars(String &str, const char *chars, size_t length); + String &operator+=(String &str, const char *cstr); + String operator+(const String &str, const char *cstr); + String operator+(const char *cstr, const String &str); + class CharInfo { + uint32 info; // Word from table a. + // Unicode character attribute lookup tables static const uint8 x[]; static const uint8 y[]; @@ -152,43 +153,49 @@ namespace JavaScript { LineBreakGroup // 5 Line break character [LineBreakGroup & -2 == WhiteGroup] }; - // Character classifying and mapping macros, based on java.lang.Character - static uint32 cCode(char16 c) {return a[y[x[static_cast(c)>>6]<<6 | c&0x3F]];} - static Type cType(char16 c) {return static_cast(cCode(c) & 0x1F);} - static Group cGroup(char16 c) {return static_cast(cCode(c) >> 16 & 7);} + CharInfo() {} + CharInfo(char16 c): info(a[y[x[static_cast(c)>>6]<<6 | c&0x3F]]) {} + CharInfo(const CharInfo &ci): info(ci.info) {} + + friend Type cType(const CharInfo &ci) {return static_cast(ci.info & 0x1F);} + friend Group cGroup(const CharInfo &ci) {return static_cast(ci.info >> 16 & 7);} + + friend bool isAlpha(const CharInfo &ci) + { + return ((((1 << UppercaseLetter) | (1 << LowercaseLetter) | (1 << TitlecaseLetter) | (1 << ModifierLetter) | (1 << OtherLetter)) + >> cType(ci)) & 1) != 0; + } + + friend bool isAlphanumeric(const CharInfo &ci) + { + return ((((1 << UppercaseLetter) | (1 << LowercaseLetter) | (1 << TitlecaseLetter) | (1 << ModifierLetter) | (1 << OtherLetter) | + (1 << DecimalDigitNumber) | (1 << LetterNumber)) + >> cType(ci)) & 1) != 0; + } + + // Return true if this character can start a JavaScript identifier + friend bool isIdLeading(const CharInfo &ci) {return cGroup(ci) == IdGroup;} + // Return true if this character can continue a JavaScript identifier + friend bool isIdContinuing(const CharInfo &ci) {return cGroup(ci) & -2 == IdGroup;} + + // Return true if this character is a Unicode decimal digit (Nd) character + friend bool isDecimalDigit(const CharInfo &ci) {return cType(ci) == DecimalDigitNumber;} + // Return true if this character is a Unicode white space or line break character + friend bool isSpace(const CharInfo &ci) {return cGroup(ci) & -2 == WhiteGroup;} + // Return true if this character is a Unicode line break character (LF, CR, LS, or PS) + friend bool isLineBreak(const CharInfo &ci) {return cGroup(ci) == LineBreakGroup;} + // Return true if this character is a Unicode format control character (Cf) + friend bool isFormat(const CharInfo &ci) {return cGroup(ci) == FormatGroup;} + + friend bool isUpper(const CharInfo &ci) {return cType(ci) == UppercaseLetter;} + friend bool isLower(const CharInfo &ci) {return cType(ci) == LowercaseLetter;} + + friend char16 toUpper(char16 c); + friend char16 toLower(char16 c); }; - - inline bool isAlpha(char16 c) - { - return ((((1 << CharInfo::UppercaseLetter) | (1 << CharInfo::LowercaseLetter) | (1 << CharInfo::TitlecaseLetter) | - (1 << CharInfo::ModifierLetter) | (1 << CharInfo::OtherLetter)) - >> CharInfo::cType(c)) & 1) != 0; - } - - inline bool isAlphanumeric(char16 c) - { - return ((((1 << CharInfo::UppercaseLetter) | (1 << CharInfo::LowercaseLetter) | (1 << CharInfo::TitlecaseLetter) | - (1 << CharInfo::ModifierLetter) | (1 << CharInfo::OtherLetter) | (1 << CharInfo::DecimalDigitNumber)) - >> CharInfo::cType(c)) & 1) != 0; - } - - // Return true if c can start a JavaScript identifier - inline bool isIdLeading(char16 c) {return CharInfo::cGroup(c) == CharInfo::IdGroup;} - // Return true if c can continue a JavaScript identifier - inline bool isIdContinuing(char16 c) {return CharInfo::cGroup(c) & -2 == CharInfo::IdGroup;} - - // Return true if c is a Unicode decimal digit (Nd) character - inline bool isDecimalDigit(char16 c) {return CharInfo::cType(c) == CharInfo::DecimalDigitNumber;} - // Return true if c is a Unicode white space or line break character - inline bool isSpace(char16 c) {return CharInfo::cGroup(c) & -2 == CharInfo::WhiteGroup;} - // Return true if c is a Unicode line break character (LF, CR, LS, or PS) - inline bool isLineBreak(char16 c) {return CharInfo::cGroup(c) == CharInfo::LineBreakGroup;} - - inline bool isUpper(char16 c) {return CharInfo::cType(c) == CharInfo::UppercaseLetter;} - inline bool isLower(char16 c) {return CharInfo::cType(c) == CharInfo::LowercaseLetter;} - - char16 toUpper(char16 c); - char16 toLower(char16 c); + + inline bool isASCIIDecimalDigit(char16 c) {return c >= '0' && c <= '9';} + bool isASCIIHexDigit(char16 c, uint &digit); // @@ -197,8 +204,7 @@ namespace JavaScript { // private template - class ProtoArrayBuffer - { + class ProtoArrayBuffer { protected: T *buffer; int32 length; @@ -237,8 +243,7 @@ namespace JavaScript { // ArrayBuffer allocates the array from the heap. // Use append to append nElts elements to the end of the ArrayBuffer. template - class ArrayBuffer: public ProtoArrayBuffer - { + class ArrayBuffer: public ProtoArrayBuffer { T cache[cacheSize]; public: @@ -283,8 +288,7 @@ namespace JavaScript { // A class to remember the format of an ostream so that a function may modify it internally // without changing it for the caller. - class SaveFormat - { + class SaveFormat { ostream &o; std::ios_base::fmtflags flags; char fill; @@ -304,5 +308,31 @@ namespace JavaScript { } void showString(ostream &out, const String &str); + +// +// Exceptions +// + + // A JavaScript exception (other than out-of-memory, for which we use the standard C++ + // exception bad_alloc). + struct Exception { + enum Kind { + SyntaxError + }; + + Kind kind; // The exception's kind + String message; // The detailed message + String sourceFile; // A description of the source code that caused the error + uint32 lineNum; // One-based source line number; 0 if unknown + uint32 charPos; // Zero-based character offset within the line + String sourceLine; // The text of the source line + + Exception(Kind kind, const String &message): kind(kind), message(message), lineNum(0) {} + Exception(Kind kind, const String &message, const String &sourceFile, uint32 lineNum, uint32 charPos, const String sourceLine): + kind(kind), message(message), sourceFile(sourceFile), lineNum(lineNum), charPos(charPos), sourceLine(sourceLine) {} + + const char *kindString() const; + String fullMessage() const; + }; } #endif