public static string FormatAppearance <TKind>(TKind kind, string value) { var clipped = FormatLiteral(Friendly.Clip(value, 12)); var description = TryGetTokenAttribute(kind); if (description != null) { if (description.Category != null) { return($"{description.Category} {clipped}"); } if (description.Example != null) { return(clipped); } } return($"{FormatKind(kind!)} {clipped}"); }
/// <summary> /// Constructs a parser that will fail if the given parser succeeds, /// and will succeed if the given parser fails. In any case, it won't /// consume any input. It's like a negative look-ahead in a regular expression. /// </summary> /// <typeparam name="T">The result type of the given parser.</typeparam> /// <typeparam name="TKind">The kind of token being parsed.</typeparam> /// <param name="parser">The parser to wrap</param> /// <returns>A parser that is the negation of the given parser.</returns> public static TokenListParser <TKind, Unit> Not <TKind, T>(TokenListParser <TKind, T> parser) { if (parser == null) { throw new ArgumentNullException(nameof(parser)); } return(input => { var result = parser(input); if (result.HasValue) { // This is usually a success case for Not(), so the allocations here are a bit of a pity. var current = input.ConsumeToken(); var last = result.Remainder.ConsumeToken(); if (current.HasValue) { var span = last.HasValue ? current.Value.Span.Source.Substring(current.Value.Position.Absolute, last.Value.Position.Absolute - current.Value.Position.Absolute) : current.Value.Span.Source.Substring(current.Value.Position.Absolute); return TokenListParserResult.Empty <TKind, Unit>(input, $"unexpected successful parsing of {Presentation.FormatLiteral(Friendly.Clip(span, 12))}"); } return TokenListParserResult.Empty <TKind, Unit>(input, "unexpected successful parsing"); } return TokenListParserResult.Value(Unit.Value, input, input); }); }