/// <summary> /// Lex a hex literal optionally followed by an integer suffix. Asserts the current /// character is a hex digit. /// </summary> private Token LexHexInt() { Contracts.Assert(LexCharUtils.IsHexDigit(ChCur)); ulong u = 0; bool fOverflow = false; do { if ((u & 0xF000000000000000) != 0 && !fOverflow) { ReportError(ErrId.IntOverflow); fOverflow = true; } u = (u << 4) + (ulong)LexCharUtils.GetHexVal(ChCur); } while (LexCharUtils.IsHexDigit(ChNext())); if (fOverflow) { u = ulong.MaxValue; } return(new IntLitToken(GetSpan(), u, LexIntSuffix() | IntLitKind.Hex)); }
/// <summary> /// Lex a character escape. Returns true if successful (ch is valid). /// </summary> private bool FLexEscChar(bool fUniOnly, out uint u) { Contracts.Assert(ChCur == '\\'); int ichErr = _cursor.IchCur; bool fUni; int cchHex; switch (ChNext()) { case 'u': fUni = true; cchHex = 4; goto LHex; case 'U': fUni = true; cchHex = 8; goto LHex; default: if (!fUniOnly) { switch (ChCur) { default: goto LBad; case 'x': case 'X': fUni = false; cchHex = 4; goto LHex; case '\'': u = 0x0027; break; case '"': u = 0x0022; break; case '\\': u = 0x005C; break; case '0': u = 0x0000; break; case 'a': u = 0x0007; break; case 'b': u = 0x0008; break; case 'f': u = 0x000C; break; case 'n': u = 0x000A; break; case 'r': u = 0x000D; break; case 't': u = 0x0009; break; case 'v': u = 0x000B; break; } ChNext(); return(true); } LBad: ReportError(ichErr, _cursor.IchCur, ErrId.BadEscape); u = 0; return(false); } LHex: bool fRet = true; ChNext(); u = 0; for (int ich = 0; ich < cchHex; ich++) { if (!LexCharUtils.IsHexDigit(ChCur)) { fRet = (ich > 0); if (fUni || !fRet) { ReportError(ichErr, _cursor.IchCur, ErrId.BadEscape); } break; } u = (u << 4) + (uint)LexCharUtils.GetHexVal(ChCur); ChNext(); } return(fRet); }
/// <summary> /// Called to lex a numeric literal or a Dot token. Asserts the current /// character lex type is LexCharType.NumLit. /// </summary> private Token LexNumLit() { Contracts.Assert(LexCharUtils.StartKind(ChCur) == LexStartKind.NumLit); Contracts.Assert(LexCharUtils.IsDigit(ChCur) || ChCur == '.'); // A dot not followed by a digit is just a Dot. This is a very common case (hence first). if (ChCur == '.' && !LexCharUtils.IsDigit(ChPeek(1))) { return(LexPunc()); } // Check for a hex literal. Note that 0x followed by a non-hex-digit is really a 0 followed // by an identifier. if (ChCur == '0' && (ChPeek(1) == 'x' || ChPeek(1) == 'X') && LexCharUtils.IsHexDigit(ChPeek(2))) { // Advance to first hex digit. ChNext(); ChNext(); return(LexHexInt()); } // Decimal literal (possible floating point). Contracts.Assert(LexCharUtils.IsDigit(ChCur) || ChCur == '.' && LexCharUtils.IsDigit(ChPeek(1))); bool fExp = false; bool fDot = ChCur == '.'; _sb.Length = 0; _sb.Append(ChCur); for (; ;) { if (ChNext() == '.') { if (fDot || !LexCharUtils.IsDigit(ChPeek(1))) { break; } fDot = true; } else if (!LexCharUtils.IsDigit(ChCur)) { break; } _sb.Append(ChCur); } // Check for an exponent. if (ChCur == 'e' || ChCur == 'E') { char chTmp = ChPeek(1); if (LexCharUtils.IsDigit(chTmp) || (chTmp == '+' || chTmp == '-') && LexCharUtils.IsDigit(ChPeek(2))) { fExp = true; _sb.Append(ChCur); _sb.Append(ChNext()); while (LexCharUtils.IsDigit(chTmp = ChNext())) { _sb.Append(chTmp); } } } bool fReal = fDot || fExp; char chSuf = LexRealSuffix(fReal); if (fReal || chSuf != '\0') { return(LexRealNum(chSuf)); } // Integer type. return(LexDecInt(LexIntSuffix())); }