/// <summary> /// Attempt to consume the <see cref="Pattern"/> from the <paramref name="source"/>. /// </summary> /// <param name="source">The <see cref="String"/> to consume.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</returns> /// <exception cref="PatternUndefinedException">The pattern was attempted to be used before actually being defined.</exception> public Result Consume(String source, ITrace?trace) { Guard.NotNull(source, nameof(source)); Source src = new Source(source); return(Consume(ref src, trace)); }
/// <summary> /// Call the Neglect parser of this <see cref="Patterns.Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { Int32 originalPosition = source.Position; Pattern.Neglect(ref source, ref result, trace); CapStore.Value = source.Substring(originalPosition, source.Position - originalPosition).ToString(); }
/// <summary> /// Call the Consume parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Consume(ref Source source, ref Result result, ITrace?trace) { From.Consume(ref source, ref result, trace); if (!result) { result.Error = Error.ConsumeFailed; return; } To.Consume(ref source, ref result, trace); while (!result) { if (source.EOF) { break; } source.Position++; result.Length++; if (To.CheckHeader(ref source)) { To.Consume(ref source, ref result, trace); } } if (!result) { result.Error = Error.EndOfSource; } }
/// <summary> /// Call the Neglect parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { if (source.EOF) { result.Error = Error.EndOfSource; trace?.Collect(result.Error, source.Position); } else { for (Int32 i = 0; i < Count; i++) { if (source.EOF) { result.Error = Error.NeglectFailed; trace?.Collect(result.Error, source.Position); break; } Char Char; if (!Check(Char = source.Peek())) { trace?.Collect(Char, source.Position); source.Position++; result.Length++; result.Error = Error.None; } else { result.Error = Error.NeglectFailed; trace?.Collect(result.Error, source.Position); break; } } } }
/// <summary> /// Call the Neglect parser of this <see cref="Node"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { if (source.EOF) { result.Error = Error.EndOfSource; trace?.Collect(result.Error, source.Position); return; } switch (source.Peek()) { case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085': case '\u2028': case '\u2029': result.Error = Error.NeglectFailed; trace?.Collect(result.Error, source.Position); break; default: trace?.Collect(source.Peek(), source.Position); source.Position++; result.Length++; break; } }
/// <summary> /// Call the Consume parser of this <see cref="Node"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</ /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Consume(ref Source source, ref Result result, ITrace?trace) { if (!source.EOF) { result.Error = Error.ConsumeFailed; } }
/// <summary> /// Call the Neglect parser of this <see cref="Node"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>. /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { if (source.EOF) { result.Error = Error.NeglectFailed; } }
/// <inheritdoc/> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { if (Head is null) { throw new PatternUndefinedException(); } Head.Neglect(ref source, ref result, trace); }
/// <summary> /// Call the Neglect parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { Left.Neglect(ref source, ref result, trace); if (!result) { return; } Right.Neglect(ref source, ref result, trace); }
/// <summary> /// Call the Neglect parser of this <see cref="Patterns.Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { for (Int32 i = 0; i < Count; i++) { Pattern.Neglect(ref source, ref result, trace); if (!result) { return; } } }
/// <summary> /// Attempt to consume the <see cref="Pattern"/> from the <paramref name="source"/>, adjusting the position in the <paramref name="source"/> as appropriate. /// </summary> /// <param name="source">The <see cref="Source"/> to consume</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</returns> /// <exception cref="PatternUndefinedException">The pattern was attempted to be used before actually being defined.</exception> public Result Consume(ref Source source, ITrace?trace) { Result result = new Result(ref source); Int32 OriginalPosition = source.Position; Consume(ref source, ref result, trace); if (!result) { source.Position = OriginalPosition; } return(result); }
/// <summary> /// Call the Neglect parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { Int32 OriginalPosition = source.Position; Int32 OriginalLength = result.Length; Right.Neglect(ref source, ref result, trace); if (result) { source.Position = OriginalPosition; result.Length = OriginalLength; Left.Neglect(ref source, ref result); } }
/// <summary> /// Call the Consume parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</ /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Consume(ref Source source, ref Result result, ITrace?trace) { //The constructors should catch this situation first, but it should still be checked here in case someone forgot if (!HeadRequired && !BodyRequired && !TailRequired) { throw new PatternConstructionException("At least one component must be required"); } //To make this easier to reason about, the implementation has been split, and this function actually just calls the requested one //This actually causes a small amount of optimization, beleive it or not. In a unified approach, two of these checks would have to occur inside of the body loop, and multiple times within the same iteration, which means they are repeated several times instead of just once here. This also prevents possible branch misprediction problems. Boolean FoundBody; if (HeadRequired) { ConsumeRequiredHead(ref source, ref result, out FoundBody); } else { ConsumeOptionalHead(ref source, ref result, out FoundBody); } if (!result) { return; } if (BodyRequired) { ConsumeRequiredBody(ref source, ref result, ref FoundBody); } else { ConsumeOptionalBody(ref source, ref result, ref FoundBody); } if (!result) { return; } if (TailRequired) { ConsumeRequiredTail(ref source, ref result, in FoundBody); } else { ConsumeOptionalTail(ref source, ref result, in FoundBody); } //Because these are generalized, they don't validate length, so we do that now if ((HeadRequired && BodyRequired && TailRequired && result.Length < 3) || //If all three are required, the length must be at least 3 (!(HeadRequired ^ BodyRequired ^ TailRequired) && result.Length < 2) || //If two are required, the length must be at least 2 (HeadRequired ^ BodyRequired ^ TailRequired && result.Length < 1)) //If only one is required, the length must be at least 1 { result.Error = Error.ConsumeFailed; } }
/// <summary> /// Call the Consume parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Consume(ref Source source, ref Result result, ITrace?trace) { Left.Consume(ref source, ref result); if (!result) { Error Error = result.Error; //Store the error result.Error = Error.None; Right.Consume(ref source, ref result, trace); if (!result) { result.Error = Error; //Resassign the first error, since both failed, but we want to be clear of that } } }
/// <summary> /// Call the Consume parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Consume(ref Source source, ref Result result, ITrace?trace) { //If we reached the end of the source we have an error if (source.EOF) { result.Error = Error.EndOfSource; return; } //Now do the appropriate parse switch (Bias) { case Bias.Tail: ConsumeTailBiased(ref source, ref result); break; default: ConsumeHeadBiased(ref source, ref result); break; } }
/// <summary> /// Call the Neglect parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) { if (source.EOF) { result.Error = Error.EndOfSource; trace?.Collect(result.Error, source.Position); } else { if (!Left(source.Peek()) && !Right(source.Peek())) { trace?.Collect(result.Error, source.Position); source.Position++; result.Length++; result.Error = Error.None; } else { result.Error = Error.NeglectFailed; trace?.Collect(result.Error, source.Position); } } }
/// <summary> /// Attempt to consume the <paramref name="pattern"/> from the <paramref name="source"/>, adjusting the position in the <paramref name="source"/> as appropriate. /// </summary> /// <param name="pattern">The <see cref="Char"/> to match.</param> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the consumed string.</returns> public static Result Consume(this Char pattern, ref Source source, ITrace?trace) => pattern.Consume(ref source, Case.Sensitive, trace);
/// <summary> /// Attempt to consume the <paramref name="pattern"/> from the <paramref name="source"/>. /// </summary> /// <param name="pattern">The <see cref="Char"/> to match.</param> /// <param name="source">The <see cref="String"/> to consume.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the consumed string.</returns> public static Result Consume(this Char pattern, String source, ITrace?trace) { Guard.NotNull(source, nameof(source)); return(pattern.Consume(source, Case.Sensitive, trace)); }
/// <summary> /// Attempt to consume the <paramref name="pattern"/> from the <paramref name="source"/>. /// </summary> /// <param name="pattern">The <see cref="Char"/> to match.</param> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="comparisonType">Whether the comparison is sensitive to casing.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the consumed string.</returns> public static Result Consume(this Char pattern, String source, Case comparisonType, ITrace?trace) { Guard.NotNull(source, nameof(source)); Source src = new Source(source); return(pattern.Consume(ref src, comparisonType, trace)); }
/// <summary> /// Attempt to consume the <paramref name="pattern"/> from the <paramref name="source"/>, adjusting the position in the <paramref name="source"/> as appropriate. /// </summary> /// <param name="pattern">The <see cref="Char"/> to match.</param> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="comparisonType">Whether the comparison is sensitive to casing.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the consumed string.</returns> public static Result Consume(this Char pattern, ref Source source, Case comparisonType, ITrace?trace) { Result result = new Result(ref source); pattern.Consume(ref source, ref result, comparisonType, trace); return(result); }
/// <summary> /// Attempt to neglect the <paramref name="pattern" />, adjusting the <paramref name="source"/> and <paramref name="result"/> as appropriate. /// </summary> /// <param name="pattern">The <see cref="Char"/> pattern.</param> /// <param name="source">The <see cref="Source"/> to neglect from.</param> /// <param name="result">The <see cref="Result"/> to store the result into.</param> /// <param name="comparisonType">Whether the comparison is sensitive to casing.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal static void Neglect(this Char pattern, ref Source source, ref Result result, Case comparisonType, ITrace?trace) { if (source.Length == 0) { result.Error = Error.EndOfSource; trace?.Collect(result.Error, source.Position); } else { Char Peek = source.Peek(); if (!pattern.Equals(Peek, comparisonType)) { trace?.Collect(Peek, source.Position); source.Position++; result.Length++; result.Error = Error.None; } else { result.Error = Error.NeglectFailed; trace?.Collect(result.Error, source.Position); } } }
/// <summary> /// Attempt to consume the <paramref name="pattern"/> from the <paramref name="source"/>, adjusting the position in the <paramref name="source"/> as appropriate /// </summary> /// <param name="pattern">The <see cref="String"/> to match</param> /// <param name="source">The <see cref="Source"/> to consume</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the consumed string</returns> public static Result Consume(this String pattern, ref Source source, ITrace?trace) { Guard.NotNull(pattern, nameof(pattern)); return(pattern.Consume(ref source, Case.Sensitive, trace)); }
internal static void Consume(this String pattern, ref Source source, ref Result result, Case comparisonType, ITrace?trace) { Guard.NotNull(pattern, nameof(pattern)); if (pattern.Length > source.Length) { result.Error = Error.EndOfSource; trace?.Collect(result.Error, source.Position); } else { ReadOnlySpan <Char> Peek = source.Peek(pattern.Length); if (pattern.Equals(Peek, comparisonType)) { trace?.Collect(Peek, source.Position); source.Position += Peek.Length; result.Length += Peek.Length; result.Error = Error.None; } else { result.Error = Error.ConsumeFailed; trace?.Collect(result.Error, source.Position); } } }
internal static void Neglect(this ReadOnlySpan <Char> pattern, ref Source source, ref Result result, Case comparisonType, ITrace?trace) { if (pattern.Length > source.Length) { result.Error = Error.EndOfSource; trace?.Collect(result.Error, source.Position); } else { ReadOnlySpan <Char> Peek = source.Peek(pattern.Length); if (!pattern.Equals(Peek, comparisonType)) { trace?.Collect(Peek, source.Length); source.Position += Peek.Length; result.Length += Peek.Length; result.Error = Error.None; } else { result.Error = Error.NeglectFailed; trace?.Collect(result.Error, source.Position); } } }
/// <summary> /// Attempt to consume the <paramref name="pattern"/> from the <paramref name="source"/>, adjusting the position in the <paramref name="source"/> as appropriate /// </summary> /// <param name="pattern">The <see cref="ReadOnlySpan{T}"/> of <see cref="Char"/> to match</param> /// <param name="source">The <see cref="Source"/> to consume</param> /// <param name="comparisonType">Whether the comparison is sensitive to casing.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the consumed string</returns> public static Result Consume(this ReadOnlySpan <Char> pattern, ref Source source, Case comparisonType, ITrace?trace) { Result Result = new Result(ref source); pattern.Consume(ref source, ref Result, comparisonType, trace); return(Result); }
/// <summary> /// Call the Consume parser of this <see cref="Node"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Consume(ref Source source, ref Result result, ITrace?trace) { if (source.EOF) { trace?.Collect(Error.EndOfSource, source.Position); result.Error = Error.EndOfSource; return; } switch (source.Peek()) { case '\u000A': if (source.EOF) { goto Done; } switch (source.Peek()) { case '\u000D': trace?.Collect("\u000A\u000D", source.Position); source.Position++; result.Length++; goto Done; default: // The line terminator is just 0x000A break; } trace?.Collect('\u000A', source.Position); break; case '\u000B': trace?.Collect('\u000B', source.Position); break; case '\u000C': trace?.Collect('\u000C', source.Position); break; case '\u000D': if (source.EOF) { goto Done; } switch (source.Peek()) { case '\u000A': trace?.Collect("\u000D\u000A", source.Position); source.Position++; result.Length++; goto Done; default: // The line terminator is just 0x000D break; } trace?.Collect('\u000D', source.Position); break; case '\u0085': trace?.Collect('\u0085', source.Position); break; case '\u2028': trace?.Collect('\u2028', source.Position); break; case '\u2029': trace?.Collect('\u2029', source.Position); break; default: result.Error = Error.ConsumeFailed; trace?.Collect(result.Error, source.Position); return; } Done: source.Position++; result.Length++; }
/// <summary> /// Call the Neglect parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> internal override void Neglect(ref Source source, ref Result result, ITrace?trace) => throw new NotImplementedException();
/// <summary> /// Attempt to consume the <see cref="Pattern"/> from the <paramref name="source"/>. /// </summary> /// <param name="source">The <see cref="Result"/> to consume.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <returns>A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</returns> /// <exception cref="PatternUndefinedException">The pattern was attempted to be used before actually being defined.</exception> public Result Consume(Result source, ITrace?trace) { Source src = new Source(source); return(Consume(ref src, trace)); }
/// <summary> /// Call the Neglect parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/> and <paramref name="trace"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <exception cref="PatternUndefinedException">The pattern was attempted to be used before actually being defined.</exception> internal abstract void Neglect(ref Source source, ref Result result, ITrace?trace);
/// <summary> /// Call the Consume parser of this <see cref="Pattern"/> on the <paramref name="source"/> with the <paramref name="result"/> and <paramref name="trace"/>. /// </summary> /// <param name="source">The <see cref="Source"/> to consume.</param> /// <param name="result">A <see cref="Result"/> containing whether a match occured and the captured <see cref="String"/>.</param> /// <param name="trace">The <see cref="ITrace"/> to record steps in.</param> /// <exception cref="PatternUndefinedException">The pattern was attempted to be used before actually being defined.</exception> internal abstract void Consume(ref Source source, ref Result result, ITrace?trace);