static public bool TryParse(List <string> tokens, out FractionSection format) { List <string> numeratorParts = null; List <string> denominatorParts = null; for (var i = 0; i < tokens.Count; i++) { var part = tokens[i]; if (part == "/") { numeratorParts = tokens.GetRange(0, i); i++; denominatorParts = tokens.GetRange(i, tokens.Count - i); break; } } if (numeratorParts == null) { format = null; return(false); } GetNumerator(numeratorParts, out var integerPart, out var numeratorPart); if (!TryGetDenominator(denominatorParts, out var denominatorPrefix, out var denominatorPart, out var denominatorConstant, out var denominatorSuffix, out var fractionSuffix)) { format = null; return(false); } format = new FractionSection() { IntegerPart = integerPart, Numerator = numeratorPart, DenominatorPrefix = denominatorPrefix, Denominator = denominatorPart, DenominatorConstant = denominatorConstant, DenominatorSuffix = denominatorSuffix, FractionSuffix = fractionSuffix }; return(true); }
private static Section ParseSection(Tokenizer reader, int index, out bool syntaxError) { bool hasDateParts = false; bool hasDurationParts = false; bool hasGeneralPart = false; bool hasTextPart = false; bool hasPlaceholders = false; Condition condition = null; Color color = null; string token; List <string> tokens = new List <string>(); syntaxError = false; while ((token = ReadToken(reader, out syntaxError)) != null) { if (token == ";") { break; } hasPlaceholders |= Token.IsPlaceholder(token); if (Token.IsDatePart(token)) { hasDateParts |= true; hasDurationParts |= Token.IsDurationPart(token); tokens.Add(token); } else if (Token.IsGeneral(token)) { hasGeneralPart |= true; tokens.Add(token); } else if (token == "@") { hasTextPart |= true; tokens.Add(token); } else if (token.StartsWith("[")) { // Does not add to tokens. Absolute/elapsed time tokens // also start with '[', but handled as date part above var expression = token.Substring(1, token.Length - 2); if (TryParseCondition(expression, out var parseCondition)) { condition = parseCondition; } else if (TryParseColor(expression, out var parseColor)) { color = parseColor; } else if (TryParseCurrencySymbol(expression, out var parseCurrencySymbol)) { tokens.Add("\"" + parseCurrencySymbol + "\""); } } else { tokens.Add(token); } } if (syntaxError || tokens.Count == 0) { return(null); } if ( (hasDateParts && (hasGeneralPart || hasTextPart)) || (hasGeneralPart && (hasDateParts || hasTextPart)) || (hasTextPart && (hasGeneralPart || hasDateParts))) { // Cannot mix date, general and/or text parts syntaxError = true; return(null); } SectionType type; FractionSection fraction = null; ExponentialSection exponential = null; DecimalSection number = null; List <string> generalTextDateDuration = null; if (hasDateParts) { if (hasDurationParts) { type = SectionType.Duration; } else { type = SectionType.Date; } ParseMilliseconds(tokens, out generalTextDateDuration); } else if (hasGeneralPart) { type = SectionType.General; generalTextDateDuration = tokens; } else if (hasTextPart || !hasPlaceholders) { type = SectionType.Text; generalTextDateDuration = tokens; } else if (FractionSection.TryParse(tokens, out fraction)) { type = SectionType.Fraction; } else if (ExponentialSection.TryParse(tokens, out exponential)) { type = SectionType.Exponential; } else if (DecimalSection.TryParse(tokens, out number)) { type = SectionType.Number; } else { // Unable to parse format string syntaxError = true; return(null); } return(new Section() { Type = type, SectionIndex = index, Color = color, Condition = condition, Fraction = fraction, Exponential = exponential, Number = number, GeneralTextDateDurationParts = generalTextDateDuration }); }