mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-24 08:07:30 +09:00
No issue - Refactor parsing of unicode escapes to be more general
This commit is contained in:
parent
952f2273b6
commit
05a8a5271c
2 changed files with 69 additions and 64 deletions
|
|
@ -90,6 +90,26 @@ RegExpBuilder::AddCharacter(char16_t c)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// forward declare atom helpers from below
|
||||||
|
static inline RegExpTree* SurrogatePairAtom(LifoAlloc* alloc, char16_t lead, char16_t trail, bool ignore_case);
|
||||||
|
static inline RegExpTree* LeadSurrogateAtom(LifoAlloc* alloc, char16_t value);
|
||||||
|
static inline RegExpTree* TrailSurrogateAtom(LifoAlloc* alloc, char16_t value);
|
||||||
|
|
||||||
|
void
|
||||||
|
RegExpBuilder::AddUnicodeCharacter(widechar c, bool ignore_case) {
|
||||||
|
if (c > unicode::UTF16Max) {
|
||||||
|
char16_t lead, trail;
|
||||||
|
unicode::UTF16Encode(c, &lead, &trail);
|
||||||
|
AddAtom(SurrogatePairAtom(alloc, lead, trail, ignore_case));
|
||||||
|
} else if (unicode::IsLeadSurrogate(c)) {
|
||||||
|
AddAtom(LeadSurrogateAtom(alloc, c));
|
||||||
|
} else if (unicode::IsTrailSurrogate(c)) {
|
||||||
|
AddAtom(TrailSurrogateAtom(alloc, c));
|
||||||
|
} else {
|
||||||
|
AddCharacter(static_cast<char16_t>(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RegExpBuilder::AddEmpty()
|
RegExpBuilder::AddEmpty()
|
||||||
{
|
{
|
||||||
|
|
@ -362,6 +382,39 @@ RegExpParser<CharT>::ParseBracedHexEscape(widechar* value)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CharT>
|
||||||
|
bool
|
||||||
|
RegExpParser<CharT>::ParseUnicodeEscape(widechar* value)
|
||||||
|
{
|
||||||
|
// Parse a RegExpUnicodeEscapeSequence
|
||||||
|
// Both \uxxxx and \u{xxxxx} are allowed. \u has already been consumed.
|
||||||
|
const CharT* start = position();
|
||||||
|
if (current() == '{' && unicode_) {
|
||||||
|
bool result = ParseBracedHexEscape(value);
|
||||||
|
if (!result) {
|
||||||
|
Reset(start);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// \u but no {, or \u{...} escapes not allowed.
|
||||||
|
bool result = ParseHexEscape(4, value);
|
||||||
|
if (result && unicode_ && unicode::IsLeadSurrogate(static_cast<char16_t>(*value)) && current() == '\\') {
|
||||||
|
// Attempt to read trail surrogate.
|
||||||
|
const CharT* start = position();
|
||||||
|
if (Next() == 'u') {
|
||||||
|
Advance(2);
|
||||||
|
widechar trail;
|
||||||
|
if (ParseHexEscape(4, &trail) &&
|
||||||
|
unicode::IsTrailSurrogate(static_cast<char16_t>(trail))) {
|
||||||
|
*value = unicode::UTF16Decode(static_cast<char16_t>(*value), static_cast<char16_t>(trail));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reset(start);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
bool
|
bool
|
||||||
RegExpParser<CharT>::ParseTrailSurrogate(widechar* value)
|
RegExpParser<CharT>::ParseTrailSurrogate(widechar* value)
|
||||||
|
|
@ -560,30 +613,13 @@ RegExpParser<CharT>::ParseClassCharacterEscape(widechar* code)
|
||||||
case 'u': {
|
case 'u': {
|
||||||
Advance();
|
Advance();
|
||||||
widechar value;
|
widechar value;
|
||||||
if (unicode_) {
|
if (ParseUnicodeEscape(&value)) {
|
||||||
if (current() == '{') {
|
*code = value;
|
||||||
if (!ParseBracedHexEscape(&value))
|
return true;
|
||||||
return false;
|
|
||||||
*code = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (ParseHexEscape(4, &value)) {
|
|
||||||
if (unicode::IsLeadSurrogate(value)) {
|
|
||||||
widechar trail;
|
|
||||||
if (ParseTrailSurrogate(&trail)) {
|
|
||||||
*code = unicode::UTF16Decode(value, trail);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*code = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ReportError(JSMSG_INVALID_UNICODE_ESCAPE);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (ParseHexEscape(4, &value)) {
|
if (unicode_) {
|
||||||
*code = value;
|
ReportError(JSMSG_INVALID_UNICODE_ESCAPE);
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
// If \u is not followed by a four-digit or braced hexadecimal, treat it
|
// If \u is not followed by a four-digit or braced hexadecimal, treat it
|
||||||
// as an identity escape.
|
// as an identity escape.
|
||||||
|
|
@ -1789,45 +1825,12 @@ RegExpParser<CharT>::ParseDisjunction()
|
||||||
case 'u': {
|
case 'u': {
|
||||||
Advance(2);
|
Advance(2);
|
||||||
widechar value;
|
widechar value;
|
||||||
if (unicode_) {
|
if (ParseUnicodeEscape(&value)) {
|
||||||
if (current() == '{') {
|
builder->AddUnicodeCharacter(value, ignore_case_);
|
||||||
if (!ParseBracedHexEscape(&value))
|
} else if (!unicode_) {
|
||||||
return nullptr;
|
builder->AddCharacter('u');
|
||||||
if (unicode::IsLeadSurrogate(value)) {
|
|
||||||
builder->AddAtom(LeadSurrogateAtom(alloc, value));
|
|
||||||
} else if (unicode::IsTrailSurrogate(value)) {
|
|
||||||
builder->AddAtom(TrailSurrogateAtom(alloc, value));
|
|
||||||
} else if (value >= unicode::NonBMPMin) {
|
|
||||||
char16_t lead, trail;
|
|
||||||
unicode::UTF16Encode(value, &lead, &trail);
|
|
||||||
builder->AddAtom(SurrogatePairAtom(alloc, lead, trail,
|
|
||||||
ignore_case_));
|
|
||||||
} else {
|
|
||||||
builder->AddCharacter(value);
|
|
||||||
}
|
|
||||||
} else if (ParseHexEscape(4, &value)) {
|
|
||||||
if (unicode::IsLeadSurrogate(value)) {
|
|
||||||
widechar trail;
|
|
||||||
if (ParseTrailSurrogate(&trail)) {
|
|
||||||
builder->AddAtom(SurrogatePairAtom(alloc, value, trail,
|
|
||||||
ignore_case_));
|
|
||||||
} else {
|
|
||||||
builder->AddAtom(LeadSurrogateAtom(alloc, value));
|
|
||||||
}
|
|
||||||
} else if (unicode::IsTrailSurrogate(value)) {
|
|
||||||
builder->AddAtom(TrailSurrogateAtom(alloc, value));
|
|
||||||
} else {
|
|
||||||
builder->AddCharacter(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ReportError(JSMSG_INVALID_UNICODE_ESCAPE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ParseHexEscape(4, &value)) {
|
|
||||||
builder->AddCharacter(value);
|
|
||||||
} else {
|
} else {
|
||||||
builder->AddCharacter('u');
|
return ReportError(JSMSG_INVALID_UNICODE_ESCAPE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,12 +133,16 @@ class BufferedVector
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Characters parsed by RegExpParser can be either char16_t or kEndMarker.
|
||||||
|
typedef uint32_t widechar;
|
||||||
|
|
||||||
// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
|
// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
|
||||||
class RegExpBuilder
|
class RegExpBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit RegExpBuilder(LifoAlloc* alloc);
|
explicit RegExpBuilder(LifoAlloc* alloc);
|
||||||
void AddCharacter(char16_t character);
|
void AddCharacter(char16_t character);
|
||||||
|
void AddUnicodeCharacter(widechar c, bool ignore_case);
|
||||||
// "Adds" an empty expression. Does nothing except consume a
|
// "Adds" an empty expression. Does nothing except consume a
|
||||||
// following quantifier
|
// following quantifier
|
||||||
void AddEmpty();
|
void AddEmpty();
|
||||||
|
|
@ -168,9 +172,6 @@ class RegExpBuilder
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Characters parsed by RegExpParser can be either char16_t or kEndMarker.
|
|
||||||
typedef uint32_t widechar;
|
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
class RegExpParser
|
class RegExpParser
|
||||||
{
|
{
|
||||||
|
|
@ -198,6 +199,7 @@ class RegExpParser
|
||||||
bool ParseHexEscape(int length, widechar* value);
|
bool ParseHexEscape(int length, widechar* value);
|
||||||
|
|
||||||
bool ParseBracedHexEscape(widechar* value);
|
bool ParseBracedHexEscape(widechar* value);
|
||||||
|
bool ParseUnicodeEscape(widechar* value);
|
||||||
bool ParseTrailSurrogate(widechar* value);
|
bool ParseTrailSurrogate(widechar* value);
|
||||||
bool ParseRawSurrogatePair(char16_t* lead, char16_t* trail);
|
bool ParseRawSurrogatePair(char16_t* lead, char16_t* trail);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue