private static bool ParseNumberLiteralDoubleFloat(string text, ref string error, NumberLiteralSuffix type, out object numberLiteral) { numberLiteral = null; if (text.Contains(".") || text.Contains("e") || type == NumberLiteralSuffix.Float || type == NumberLiteralSuffix.Double) { const NumberStyles decimalStyle = NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint; // real number switch (type) { case NumberLiteralSuffix.None: // double is defualt case NumberLiteralSuffix.Double: { numberLiteral = TryParse <double>(double.TryParse, text, out error, decimalStyle); return(true); } case NumberLiteralSuffix.Float: { numberLiteral = TryParse <float>(float.TryParse, text, out error, decimalStyle); return(true); } case NumberLiteralSuffix.Decimal: { numberLiteral = TryParse <decimal>(decimal.TryParse, text, out error, decimalStyle); return(true); } default: error = $"could not parse real number of type {type}"; { return(true); } } } return(false); }
private static bool ParseNumberLiteralSuffix(ref string text, ref string error, char lastDigit, ref NumberLiteralSuffix type) { if (char.IsLetter(lastDigit)) { // number type suffix if (lastDigit == 'm') { type = NumberLiteralSuffix.Decimal; } else if (lastDigit == 'f') { type = NumberLiteralSuffix.Float; } else if (lastDigit == 'd') { type = NumberLiteralSuffix.Double; } else if (text.EndsWith("ul", StringComparison.Ordinal) || text.EndsWith("lu", StringComparison.Ordinal)) { type = NumberLiteralSuffix.UnsignedLong; } else if (lastDigit == 'u') { type = NumberLiteralSuffix.Unsigned; } else if (lastDigit == 'l') { type = NumberLiteralSuffix.Long; } else { error = "number literal type suffix not known"; return(true); } if (type == NumberLiteralSuffix.UnsignedLong) { text = text.Remove(text.Length - 2); // remove 2 last chars } else { text = text.Remove(text.Length - 1); // remove last char } } return(false); }
private static object ParseNumberLiteral(string text, out string error) { text = text.ToLower(); error = null; NumberLiteralSuffix type = NumberLiteralSuffix.None; var lastDigit = text[text.Length - 1]; if (ParseNumberLiteralSuffix(ref text, ref error, lastDigit, ref type)) { return(null); } object numberLiteral; if (ParseNumberLiteralDoubleFloat(text, ref error, type, out numberLiteral)) { return(numberLiteral); } const NumberStyles integerStyle = NumberStyles.AllowLeadingSign; // try parse integral constant object result = null; if (type == NumberLiteralSuffix.None) { result = TryParse <int>(int.TryParse, text, integerStyle) ?? TryParse <uint>(uint.TryParse, text, integerStyle) ?? TryParse <long>(long.TryParse, text, integerStyle) ?? TryParse <ulong>(ulong.TryParse, text, integerStyle); } else if (type == NumberLiteralSuffix.Unsigned) { result = TryParse <uint>(uint.TryParse, text, integerStyle) ?? TryParse <ulong>(ulong.TryParse, text, integerStyle); } else if (type == NumberLiteralSuffix.Long) { result = TryParse <long>(long.TryParse, text, integerStyle) ?? TryParse <ulong>(ulong.TryParse, text, integerStyle); } else if (type == NumberLiteralSuffix.UnsignedLong) { result = TryParse <ulong>(ulong.TryParse, text, integerStyle); } if (result != null) { return(result); } // handle errors // if all are digits, or '0x' + hex digits => too large number if (text.All(char.IsDigit) || (text.StartsWith("0x", StringComparison.Ordinal) && text.Skip(2).All(c => char.IsDigit(c) || (c >= 'a' && c <= 'f')))) { error = $"number number {text} is too large for integral literal, try to append 'd' to real number literal"; } else { error = $"could not parse {text} as numeric literal"; } return(null); }