public static Optional <MatchResult <NamedTypeDetails> > NamedType(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var name = Optional <IdentifierDetails> .Missing; var genericTypeParameters = Optional <ImmutableList <GenericTypeParameterDetails> > .Missing; var readerAfterValue = reader .StartMatching() .Then(Identifier, value => name = value) .ThenOptionally(Whitespace) .If(Match('<')).Then(GenericTypeParameters, value => genericTypeParameters = value); if (!readerAfterValue.IsDefined) { return(null); } if (genericTypeParameters.IsDefined && !genericTypeParameters.Value.Any()) { throw new ArgumentException($"Invalid named type content starting at {reader.Index} - has generic type param opening bracket but zero type params present"); } return(MatchResult.New( new NamedTypeDetails( name.Value, genericTypeParameters.GetValueOrDefault(ImmutableList <GenericTypeParameterDetails> .Empty) ), readerAfterValue.Value )); }
private static bool PositionIsOverWhitespace(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } return((reader.Current != null) && char.IsWhiteSpace(reader.Current.Value)); }
public static Optional <IReadStringContent> StartMatching(this IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } return(Optional.For(reader)); }
private static SourceRangeDetails GetSourceRangeFromReaders(IReadStringContent readerStart, IReadStringContent readerAfter) { if (readerAfter == null) { throw new ArgumentNullException(nameof(readerAfter)); } return(new SourceRangeDetails(readerStart.Index, readerAfter.Index - readerStart.Index)); }
public CharacterAndNextReader(char character, IReadStringContent nextReader) { if (nextReader == null) { throw new ArgumentNullException(nameof(nextReader)); } Character = character; NextReader = nextReader; }
public static Optional <MatchResult <InterfaceDetails> > Interface(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var identifiedInterface = false; var interfaceName = Optional <IdentifierDetails> .Missing; var genericTypeParameters = Optional <ImmutableList <GenericTypeParameterDetails> > .Missing; var baseTypes = Optional <ImmutableList <NamedTypeDetails> > .Missing; var properties = ImmutableList <PropertyDetails> .Empty; var readerAfterValue = reader .StartMatching() .Then(Match("interface")) .Then(Whitespace) .IfDefined(() => identifiedInterface = true) .ThenOptionally(Whitespace) .Then(Identifier, value => interfaceName = value) .ThenOptionally(Whitespace) .If(Match('<')).Then(GenericTypeParameters, value => genericTypeParameters = value) .ThenOptionally(Whitespace) .ThenOptionally(InheritanceChain, value => baseTypes = value) .ThenOptionally(Whitespace) .Then(Match('{')) .ThenOptionally(Whitespace) .ThenOptionally(InterfaceProperties, value => properties = value) .ThenOptionally(Whitespace) .Then(Match('}')); if (!readerAfterValue.IsDefined) { if (identifiedInterface) { throw new ArgumentException($"Invalid interface content starting at {reader.Index}"); } return(null); } if (genericTypeParameters.IsDefined && !genericTypeParameters.Value.Any()) { throw new ArgumentException($"Invalid interface content starting at {reader.Index} - has generic type param opening bracket but zero type params present"); } return(MatchResult.New( new InterfaceDetails( interfaceName.Value, genericTypeParameters.GetValueOrDefault(ImmutableList <GenericTypeParameterDetails> .Empty), baseTypes.GetValueOrDefault(ImmutableList <NamedTypeDetails> .Empty), properties, new SourceRangeDetails(reader.Index, readerAfterValue.Value.Index - reader.Index) ), readerAfterValue.Value )); }
public MatchResult(T result, IReadStringContent reader) { if (result == null) { throw new ArgumentNullException(nameof(result)); } if (reader == null) { throw new ArgumentNullException(nameof(reader)); } Result = result; Reader = reader; }
public ParsedContent(ImmutableList <IType> types, IReadStringContent reader) { if (types == null) { throw new ArgumentNullException(nameof(types)); } if (types.Any(t => t == null)) { throw new ArgumentException("Null reference encountered in set", nameof(types)); } Types = types; Reader = reader; }
public static string ReadRemainingContent(this IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var content = new StringBuilder(); while (reader.Current != null) { content.Append(reader.Current); reader = reader.GetNext(); } return(content.ToString()); }
private static Optional <MatchResult <NamedTypeDetails> > BaseType(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var result = InheritanceChain(reader, supportMultipleBaseTypes: false); if (!result.IsDefined) { return(null); } return(MatchResult.New(result.Value.Result.Single(), result.Value.Reader)); }
public static Optional <MatchResult <IdentifierDetails> > Identifier(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var result = reader.MatchAnythingUntil(IdentifierDetails.DisallowedCharacters); if (!result.IsDefined) { return(null); } return(MatchResult.New( new IdentifierDetails(result.Value.Result, GetSourceRangeFromReaders(reader, result.Value.Reader)), result.Value.Reader )); }
private static IEnumerable <CharacterAndNextReader> Read(this IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } while (true) { var currentCharacter = reader.Current; if (currentCharacter == null) { yield break; } var nextReader = reader.GetNext(); yield return(new CharacterAndNextReader(currentCharacter.Value, nextReader)); reader = nextReader; } }
/// <summary> /// At least one terminator character must be specified, otherwise all of the remaining content would be returned /// </summary> public static Optional <MatchResult <string> > MatchAnythingUntil(this IReadStringContent reader, ImmutableList <char> acceptableTerminators) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (acceptableTerminators == null) { throw new ArgumentNullException(nameof(acceptableTerminators)); } if (!acceptableTerminators.Any()) { throw new ArgumentException("at least one terminator character must be specified", nameof(acceptableTerminators)); } var matchedCharacters = reader .Read() .TakeWhile(c => !acceptableTerminators.Contains(c.Character)); // Ensure some content was actually read (if not then return a no-data result) if (!matchedCharacters.Any()) { return(null); } // Ensure that the content was correctly terminated (the content may have been exhausted, which is not the same as identifying content that // was explicitly terminated by one of a particular set of characters - if no terminator was met then it a no-data result must be returned) var readerAfterMatch = matchedCharacters.Last().NextReader; if (readerAfterMatch.Current == null) { return(null); } return(MatchResult.New( string.Join("", matchedCharacters.Select(c => c.Character)), readerAfterMatch )); }
private static Optional <MatchResult <ImmutableList <NamedTypeDetails> > > InheritanceChain(IReadStringContent reader) => InheritanceChain(reader, supportMultipleBaseTypes: true);
private static Optional <MatchResult <ImmutableList <NamedTypeDetails> > > InheritanceChain(IReadStringContent reader, bool supportMultipleBaseTypes) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var readerAtTypeList = reader.StartMatching().Then(Match("extends")); if (!readerAtTypeList.IsDefined) { return(null); } var baseTypes = ImmutableList <NamedTypeDetails> .Empty; while (true) { if (baseTypes.Any()) { var readerAfterTypeParameterSeparator = readerAtTypeList.ThenOptionally(Whitespace).Then(Match(',')); if (readerAfterTypeParameterSeparator.IsDefined) { readerAtTypeList = readerAfterTypeParameterSeparator; } } var name = Optional <NamedTypeDetails> .Missing; var readerAfterValue = readerAtTypeList .ThenOptionally(Whitespace) .Then(NamedType, value => name = value); if (!readerAfterValue.IsDefined) { break; } baseTypes = baseTypes.Add(name.Value); readerAtTypeList = readerAfterValue; if (!supportMultipleBaseTypes) { break; } } return(MatchResult.New(baseTypes, readerAtTypeList.Value)); }
public static Optional <MatchResult <ImmutableList <GenericTypeParameterDetails> > > GenericTypeParameters(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var readerAtTypeParameterDefinition = reader.StartMatching().Then(Match('<')); if (!readerAtTypeParameterDefinition.IsDefined) { return(null); } var genericTypeParameters = ImmutableList <GenericTypeParameterDetails> .Empty; while (true) { var readerAfterImminentClosingBrace = readerAtTypeParameterDefinition.ThenOptionally(Whitespace).Then(Match('>')); if (readerAfterImminentClosingBrace.IsDefined) { reader = readerAfterImminentClosingBrace.Value; break; } if (genericTypeParameters.Any()) { var readerAfterTypeParameterSeparator = readerAtTypeParameterDefinition.ThenOptionally(Whitespace).Then(Match(',')); if (readerAfterTypeParameterSeparator.IsDefined) { readerAtTypeParameterDefinition = readerAfterTypeParameterSeparator; } } var name = Optional <NamedTypeDetails> .Missing; var typeConstraint = Optional <NamedTypeDetails> .Missing; var readerAfterValue = readerAtTypeParameterDefinition .ThenOptionally(Whitespace) .Then(NamedType, value => name = value) .ThenOptionally(Whitespace) .If(Match("extends")).Then(BaseType, value => typeConstraint = value); if (!readerAfterValue.IsDefined) { break; } genericTypeParameters = genericTypeParameters.Add(new GenericTypeParameterDetails( name.Value, typeConstraint )); readerAtTypeParameterDefinition = readerAfterValue; } return(MatchResult.New(genericTypeParameters, reader)); }
public static Optional <MatchResult <TypeDescriptionDetails> > TypeDescription(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var result = reader.MatchAnythingUntil(UntilWhiteSpaceOrPunctuation); if (!result.IsDefined) { return(null); } return(MatchResult.New( new TypeDescriptionDetails(result.Value.Result, GetSourceRangeFromReaders(reader, result.Value.Reader)), result.Value.Reader )); }
private static Optional <MatchResult <ImmutableList <PropertyDetails> > > InterfaceProperties(IReadStringContent reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var contents = ImmutableList <PropertyDetails> .Empty; while (true) { var identifier = Optional <IdentifierDetails> .Missing; var typeDescription = Optional <TypeDescriptionDetails> .Missing; var readerAfterValue = reader .StartMatching() .ThenOptionally(Whitespace) .Then(Identifier, value => identifier = value) .ThenOptionally(Whitespace) .Then(Match(':')) .ThenOptionally(Whitespace) .Then(TypeDescription, value => typeDescription = value) .ThenOptionally(Whitespace) .Then(Match(';')); if (!readerAfterValue.IsDefined) { break; } contents = contents.Add(new PropertyDetails(identifier.Value, typeDescription.Value)); reader = readerAfterValue.Value; } if (!contents.Any()) { return(null); } return(MatchResult.New(contents, reader)); }