private bool IsIdentifierStartCharHelper(char c, bool expandedUnicode)
{
bool isEscapeChar = false;
int escapeLength = 0;
UnicodeCategory ccat = 0;
if (c == '\\')
{
isEscapeChar = true;
char cc = this.GetChar(this.endPos + 1);
switch (cc)
{
case '-':
c = '-';
goto isIdentifierChar;
case 'u':
escapeLength = 4;
break;
case 'U':
escapeLength = 8;
break;
default:
return false;
}
int escVal = 0;
for (int i = 0; i < escapeLength; i++)
{
char ch = this.GetChar(this.endPos + 2 + i);
escVal <<= 4;
if (Scanner.IsHexDigit(ch))
escVal |= Scanner.GetHexValue(ch);
else
{
escVal >>= 4;
break;
}
}
if (escVal > 0xFFFF) return false; //REVIEW: can a 32-bit Unicode char ever be legal? If so, how does one categorize it?
c = (char)escVal;
}
if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '$')
goto isIdentifierChar;
if (c < 128)
return false;
ccat = Char.GetUnicodeCategory(c);
switch (ccat)
{
case UnicodeCategory.UppercaseLetter:
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.TitlecaseLetter:
case UnicodeCategory.ModifierLetter:
case UnicodeCategory.OtherLetter:
case UnicodeCategory.LetterNumber:
goto isIdentifierChar;
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.DecimalDigitNumber:
case UnicodeCategory.ConnectorPunctuation:
if (expandedUnicode) goto isIdentifierChar;
return false;
case UnicodeCategory.Format:
if (expandedUnicode)
{
if (!isEscapeChar)
{
isEscapeChar = true;
escapeLength = -1;
}
goto isIdentifierChar;
}
return false;
default:
return false;
}
isIdentifierChar:
if (isEscapeChar)
{
int startPos = this.idLastPosOnBuilder;
if (startPos == 0) startPos = this.startPos;
if (this.endPos > startPos)
this.identifier.Append(this.Substring(startPos, this.endPos - startPos));
if (ccat != UnicodeCategory.Format)
this.identifier.Append(c);
this.endPos += escapeLength + 1;
this.idLastPosOnBuilder = this.endPos + 1;
}
return true;
}