void ReadNumber(SourceUnit unit, ScanResult <LoreToken> result) { const string HexChars = "abcdefABCDEF"; var accum = new StringBuilder(); var isfloat = false; var nofloatstart = false; var nofloatend = false; var ishex = false; var chr = unit.Peek(); if (chr == '.') { nofloatstart = true; accum.Append("0"); } else if (chr == '0' && unit.See(2) && unit.Peek(1) == 'x') { ishex = true; unit.Skip(2); } if (!unit.See(0)) { Throw("Unexpected end of file."); } while (unit.See(0) && (chr = unit.Peek()) > 0) { if (chr == '.') { if (!unit.See(1) || !char.IsDigit(unit.Peek(1))) { nofloatend = true; if (nofloatstart) { Throw("Floating-point literal must have a digit before or after the decimal point."); } } if (isfloat) { break; // Throw ("There can only be one decimal point in a floating-point literal."); } isfloat = true; accum.Append(unit.Read()); if (nofloatend) { accum.Append('0'); break; } continue; } if (ishex) { if (char.IsDigit(chr) || HexChars.Contains(chr)) { accum.Append(unit.Read()); continue; } break; } if (char.IsDigit(chr)) { accum.Append(unit.Read()); continue; } break; } var str = accum.ToString(); ulong hexvalue = 0; if (ishex) { if (!ulong.TryParse(str, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo, out hexvalue)) { try { ulong.Parse(str, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo); } catch (Exception e) { Throw($"Unable to parse base-16 integer literal: {e.Message}."); } } } else if (isfloat) { try { float.Parse(str, NumberStyles.Float, NumberFormatInfo.InvariantInfo); } catch (Exception e) { Throw($"Unable to parse floating-point literal: {e.Message}."); } } else { try { ulong.Parse(str, NumberStyles.Integer, NumberFormatInfo.InvariantInfo); } catch (Exception e) { Throw($"Unable to parse integer literal: {e.Message}."); } } result.Token = isfloat ? LoreToken.FloatLiteral : LoreToken.IntLiteral; result.Value = ishex ? hexvalue.ToString() : str; }
private void ColorNone(string line, ColoredCharacter[] result, ref int index) { while (index < line.Length) { if (OutputIfNext(line, result, ref index, "//", CommentColor)) { for (var i = index; i < line.Length; i++, index++) { result[i] = new ColoredCharacter(line[i], CommentColor); } return; } if (OutputIfNext(line, result, ref index, "/*", CommentColor)) { _state = TokenState.MultiComment; _multiCommentDepth = 1; return; } var ch = line[index]; if (OutputIfNext(line, result, ref index, "\"", StringColor) || OutputIfNext(line, result, ref index, "\'", StringColor)) { _state = TokenState.String; _stringTerminator = ch; return; } if (Operators.TryGetValue(ch, out var operators)) { var idx = index; var op = operators.FirstOrDefault(s => IsNext(line, idx, s)); if (op != null) { Output(result, ref index, op, OperatorColor); continue; } } if (char.IsLetter(ch) || ch == '_' || ch == '`') { var start = index; var isBacktick = ch == '`'; if (isBacktick) { index++; // opening backtick } while (index < line.Length && (char.IsLetterOrDigit(line[index]) || line[index] == '_')) { index++; } if (isBacktick && index < line.Length && line[index] == '`') { index++; // closing backtick } var word = line.Substring(start, index - start); index = start; if (isBacktick) { Output(result, ref index, word, OperatorColor); continue; } if (Keywords.Contains(word)) { Output(result, ref index, word, KeywordColor); continue; } Output(result, ref index, word, IdentifierColor); continue; } if (char.IsDigit(ch)) { var format = NumberFormat.Decimal; var hasDecimal = false; var hasExp = false; var justTake = false; if (ch == '0' && index + 1 < line.Length) { var nextChar = line[index + 1]; if (nextChar == 'x' || nextChar == 'X') { format = NumberFormat.Hexadecimal; } if (nextChar == 'b' || nextChar == 'B') { format = NumberFormat.Binary; } if (format != NumberFormat.Decimal) { if (index + 2 < line.Length && line[index + 2] == '_') { result[index++] = new ColoredCharacter('0', NumberColor); continue; } result[index + 0] = new ColoredCharacter('0', NumberColor); result[index + 1] = new ColoredCharacter(nextChar, NumberColor); index += 2; } } bool IsDigit(char c) => char.IsDigit(c) || (format == NumberFormat.Hexadecimal && HexChars.Contains(c)); while (index < line.Length) { var c = line[index]; if (justTake) { justTake = false; result[index++] = new ColoredCharacter(c, NumberColor); continue; } if (c == '_' && (index + 1 < line.Length && IsDigit(line[index + 1]))) { result[index++] = new ColoredCharacter(c, NumberColor); continue; } if (format == NumberFormat.Decimal) { if (c == '.' && !hasDecimal && !hasExp) { hasDecimal = true; if (index + 1 >= line.Length || !IsDigit(line[index + 1])) { break; } result[index++] = new ColoredCharacter(c, NumberColor); continue; } if ((c == 'e' || c == 'E') && !hasExp) { if (index + 1 < line.Length) { var next = line[index + 1]; if (next == '+' || next == '-') { justTake = true; } } hasExp = true; result[index++] = new ColoredCharacter(c, NumberColor); continue; } } if (!IsDigit(c)) { break; } result[index++] = new ColoredCharacter(c, NumberColor); } continue; } result[index] = new ColoredCharacter(line[index], OtherColor); index++; } }