mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 07:48:38 +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
|
||||
}
|
||||
|
||||
// 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
|
||||
RegExpBuilder::AddEmpty()
|
||||
{
|
||||
|
|
@ -362,6 +382,39 @@ RegExpParser<CharT>::ParseBracedHexEscape(widechar* value)
|
|||
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>
|
||||
bool
|
||||
RegExpParser<CharT>::ParseTrailSurrogate(widechar* value)
|
||||
|
|
@ -560,30 +613,13 @@ RegExpParser<CharT>::ParseClassCharacterEscape(widechar* code)
|
|||
case 'u': {
|
||||
Advance();
|
||||
widechar value;
|
||||
if (unicode_) {
|
||||
if (current() == '{') {
|
||||
if (!ParseBracedHexEscape(&value))
|
||||
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 (ParseUnicodeEscape(&value)) {
|
||||
*code = value;
|
||||
return true;
|
||||
}
|
||||
if (ParseHexEscape(4, &value)) {
|
||||
*code = value;
|
||||
return true;
|
||||
if (unicode_) {
|
||||
ReportError(JSMSG_INVALID_UNICODE_ESCAPE);
|
||||
return false;
|
||||
}
|
||||
// If \u is not followed by a four-digit or braced hexadecimal, treat it
|
||||
// as an identity escape.
|
||||
|
|
@ -1789,45 +1825,12 @@ RegExpParser<CharT>::ParseDisjunction()
|
|||
case 'u': {
|
||||
Advance(2);
|
||||
widechar value;
|
||||
if (unicode_) {
|
||||
if (current() == '{') {
|
||||
if (!ParseBracedHexEscape(&value))
|
||||
return nullptr;
|
||||
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);
|
||||
if (ParseUnicodeEscape(&value)) {
|
||||
builder->AddUnicodeCharacter(value, ignore_case_);
|
||||
} else if (!unicode_) {
|
||||
builder->AddCharacter('u');
|
||||
} else {
|
||||
builder->AddCharacter('u');
|
||||
return ReportError(JSMSG_INVALID_UNICODE_ESCAPE);
|
||||
}
|
||||
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.
|
||||
class RegExpBuilder
|
||||
{
|
||||
public:
|
||||
explicit RegExpBuilder(LifoAlloc* alloc);
|
||||
void AddCharacter(char16_t character);
|
||||
void AddUnicodeCharacter(widechar c, bool ignore_case);
|
||||
// "Adds" an empty expression. Does nothing except consume a
|
||||
// following quantifier
|
||||
void AddEmpty();
|
||||
|
|
@ -168,9 +172,6 @@ class RegExpBuilder
|
|||
#endif
|
||||
};
|
||||
|
||||
// Characters parsed by RegExpParser can be either char16_t or kEndMarker.
|
||||
typedef uint32_t widechar;
|
||||
|
||||
template <typename CharT>
|
||||
class RegExpParser
|
||||
{
|
||||
|
|
@ -198,6 +199,7 @@ class RegExpParser
|
|||
bool ParseHexEscape(int length, widechar* value);
|
||||
|
||||
bool ParseBracedHexEscape(widechar* value);
|
||||
bool ParseUnicodeEscape(widechar* value);
|
||||
bool ParseTrailSurrogate(widechar* value);
|
||||
bool ParseRawSurrogatePair(char16_t* lead, char16_t* trail);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue