/// <summary> /// Search for ReplaceableParsers with the given name and attempt to transform the contents /// using the given transformation. The contents of the ReplaceableParser will be replaced /// with the transformed result if it is new and valid. /// </summary> /// <typeparam name="TInput"></typeparam> /// <typeparam name="TOutput"></typeparam> /// <param name="root"></param> /// <param name="predicate"></param> /// <param name="transform"></param> /// <returns></returns> public static MultiReplaceResult ReplaceMulti <TInput, TOutput>(IParser root, Func <IReplaceableParserUntyped, bool> predicate, Func <IMultiParser <TInput, TOutput>, IMultiParser <TInput, TOutput> > transform) { if (root == null || predicate == null || transform == null) { return(MultiReplaceResult.Failure()); } var visitor = new FindParserVisitor(); var state = new State(p => p is IReplaceableParserUntyped replaceable && predicate(replaceable), true); visitor.Visit(root, state); var results = new List <SingleReplaceResult>(); foreach (var found in state.Found.Cast <IReplaceableParserUntyped>()) { if (found.ReplaceableChild is not IMultiParser <TInput, TOutput> parser) { continue; } var replacement = transform(parser); if (replacement == null || ReferenceEquals(replacement, parser)) { continue; } var result = found.SetParser(replacement); results.Add(result); } return(new MultiReplaceResult(results)); }
public void Replace_Transform_Fail_ReplacementNull() { var needle = Fail <char>().Replaceable().Named("needle"); var haystack = (Any(), Any(), Any(), needle).First(); var result = FindParserVisitor.Replace <char, char>(haystack, _ => false, null); result.Success.Should().BeFalse(); }
public void Replace_Transform_Fail_PredicateNull() { var needle = Fail <char>().Replaceable().Named("needle"); var haystack = (Any(), Any(), Any(), needle).First(); var result = FindParserVisitor.Replace <char, char>(haystack, (Func <IReplaceableParserUntyped, bool>)null, _ => needle); result.Success.Should().BeFalse(); }
public void Named_Test() { var needle = Fail <char>().Named("needle"); var haystack = (Any(), Any(), Any(), needle).First(); var result = FindParserVisitor.Named(haystack, "needle"); result.Success.Should().BeTrue(); result.Value.Should().BeSameAs(needle); }
public void OfType_Test() { var needle = Fail <char>().Named("needle"); var haystack = (Any(), Any(), Any(), needle).First(); var result = FindParserVisitor.OfType <FailParser <char, char> >(haystack); result.Count.Should().Be(1); result[0].Should().BeSameAs(needle); }
/// <summary> /// Search for all parsers of the given type. Returns all results. /// </summary> /// <typeparam name="TParser"></typeparam> /// <param name="root"></param> /// <returns></returns> public static IReadOnlyList <TParser> OfType <TParser>(IParser root) where TParser : IParser { Assert.ArgumentNotNull(root, nameof(root)); var visitor = new FindParserVisitor(); var state = new State(p => p is TParser, false); visitor.Visit(root, state); return(state.Found.Cast <TParser>().ToList()); }
public static IOption <IParser> FindSingle(IParser root, Func <IParser, bool> predicate) { Assert.ArgumentNotNull(root, nameof(root)); Assert.ArgumentNotNull(predicate, nameof(predicate)); var visitor = new FindParserVisitor(); var state = new State(predicate, true); visitor.Visit(root, state); if (state.Found.Count > 0) { return(new SuccessOption <IParser>(state.Found.First())); } return(FailureOption <IParser> .Instance); }
public void ReplaceMulti_ByName() { var fail = FailMulti <char>(); var needle = FailMulti <char>().Replaceable().Named("needle"); var success = ProduceMulti(() => new[] { 'X' }); var haystack = needle; var parseResult = haystack.Parse("X"); parseResult.Success.Should().BeFalse(); var result = FindParserVisitor.ReplaceMulti <char, char>(haystack, "needle", x => success); result.Success.Should().BeTrue(); parseResult = haystack.Parse("X"); parseResult.Success.Should().BeTrue(); parseResult.Results[0].Value.Should().Be('X'); }
public void Replace_Single_ByName() { var fail = Fail <char>(); var needle = Fail <char>().Replaceable().Named("needle"); var success = Any(); var haystack = (fail, fail, fail, needle).First(); var parseResult = haystack.Parse("X"); parseResult.Success.Should().BeFalse(); var result = FindParserVisitor.Replace(haystack, "needle", success); result.Success.Should().BeTrue(); parseResult = haystack.Parse("X"); parseResult.Success.Should().BeTrue(); parseResult.Value.Should().Be('X'); }
/// <summary> /// Search for ReplaceableParsers matching a predicate and attempt to replace their contents with the /// replacement parser if it is found. The replacement parser must be non-null and of the correct /// type. Replaces all matching instances. /// </summary> /// <param name="root"></param> /// <param name="predicate"></param> /// <param name="replacement"></param> /// <returns></returns> public static MultiReplaceResult Replace(IParser root, Func <IReplaceableParserUntyped, bool> predicate, IParser replacement) { if (root == null || predicate == null || replacement == null) { return(MultiReplaceResult.Failure()); } var visitor = new FindParserVisitor(); var state = new State(p => p is IReplaceableParserUntyped replaceable && predicate(replaceable), true); visitor.Visit(root, state); var results = new List <SingleReplaceResult>(); foreach (var found in state.Found.Cast <IReplaceableParserUntyped>()) { var result = found.SetParser(replacement); results.Add(result); } return(new MultiReplaceResult(results)); }
/// <summary> /// Given a parser graph, find a ReplaceableParser matching a predicate and attempt to /// transform the contents using the given transformation. The contents of the /// ReplaceableParser will be replaced with the transformed result if it is new and valid. /// </summary> /// <typeparam name="TInput"></typeparam> /// <typeparam name="TOutput"></typeparam> /// <param name="root"></param> /// <param name="name"></param> /// <param name="transform"></param> /// <returns></returns> public static MultiReplaceResult Replace <TInput, TOutput>(this IParser root, string name, Func <IMultiParser <TInput, TOutput>, IMultiParser <TInput, TOutput> > transform) => FindParserVisitor.ReplaceMulti(root, name, transform);
/// <summary> /// Given a parser tree, find a ReplaceableParser with the given name and replace the child /// parser with the given replacement parser. /// </summary> /// <param name="root"></param> /// <param name="name"></param> /// <param name="replacement"></param> /// <returns></returns> public static MultiReplaceResult Replace(this IParser root, string name, IParser replacement) => FindParserVisitor.Replace(root, name, replacement);
/// <summary> /// Given a parser tree, find a ReplaceableParsers matching a predicate and attempt to transform /// the contents using the given transformation. The contents of the ReplaceableParser will be /// replaced with the transformed result if it is new and valid. /// </summary> /// <typeparam name="TInput"></typeparam> /// <typeparam name="TOutput"></typeparam> /// <param name="root"></param> /// <param name="predicate"></param> /// <param name="transform"></param> /// <returns></returns> public static MultiReplaceResult Replace <TInput, TOutput>(this IParser root, Func <IParser, bool> predicate, Func <IParser <TInput, TOutput>, IParser <TInput, TOutput> > transform) => FindParserVisitor.Replace(root, predicate, transform);
/// <summary> /// Given a parser tree, replace all children of ReplaceableParsers matching the given /// predicate with the provided replacement parser. Returns information about which /// instances were replaced. /// </summary> /// <param name="root"></param> /// <param name="predicate"></param> /// <param name="replacement"></param> /// <returns></returns> public static MultiReplaceResult Replace(this IParser root, Func <IParser, bool> predicate, IParser replacement) => FindParserVisitor.Replace(root, predicate, replacement);
/// <summary> /// Recurse the tree searching for a parser with the given name. Returns a result with the /// parser if found, a failure flag otherwise. /// </summary> /// <param name="root"></param> /// <param name="name"></param> /// <returns></returns> public static IOption <IParser> FindNamed(this IParser root, string name) => FindParserVisitor.Named(root, name);
/// <summary> /// Recurse the tree searching for a parser with the given id value. Returns a result with the /// parser if found, a failure otherwise. /// </summary> /// <param name="root"></param> /// <param name="id"></param> /// <returns></returns> public static IOption <IParser> Find(this IParser root, int id) => FindParserVisitor.ById(root, id);