public IEnumerable <Match2> GetMatches(string inputText) { ArrayConsList <char> consList = new ArrayConsList <char>(inputText); int index = 0, afterLastMatchIndex = 0; while (index <= inputText.Length) { Result <char, Match2> result = Parse(consList, afterLastMatchIndex); if (result.Tree.Success) { yield return(result.Tree); if (result.Tree.Length > 0) { consList = (ArrayConsList <char>)result.Rest; index += result.Tree.Length; afterLastMatchIndex = index; continue; } } if (!consList.IsEmpty) { consList = (ArrayConsList <char>)consList.Tail; } index++; } }
public IEnumerable<Match2> GetMatches(string inputText) { ArrayConsList<char> consList = new ArrayConsList<char>(inputText); int index = 0, afterLastMatchIndex = 0; while (index <= inputText.Length) { Result<char, Match2> result = Parse(consList, afterLastMatchIndex); if (result.Tree.Success) { yield return result.Tree; if (result.Tree.Length > 0) { consList = (ArrayConsList<char>)result.Rest; index += result.Tree.Length; afterLastMatchIndex = index; continue; } } if (!consList.IsEmpty) consList = (ArrayConsList<char>)consList.Tail; index++; } }
public static void CharParserTest <TTree>(Parser <char, TTree> parser, int times, int maxItemCount, string inputText) { IConsList <char> consList = new ArrayConsList <char>(inputText); DateTime start = DateTime.Now; IConsList <char> rest = null; for (int i = 0; i < times; i++) { Result <char, TTree> result = parser(consList); while (result != null) { rest = result.Rest; result = parser(result.Rest); } } if (rest != null && !rest.IsEmpty) { Console.WriteLine("The remaining list is NOT empty.\n"); } TimeSpan time = DateTime.Now - start; TimeSpan timePerCycle = new TimeSpan(0, 0, 0, 0, (int)(time.TotalMilliseconds / times)); Console.WriteLine(time); Console.WriteLine(); //Console.WriteLine("{0} per cycle", timePerCycle); //Console.WriteLine(); }
protected override Result<char, Match2> Parse(ArrayConsList<char> consList, int afterLastMatchIndex) { Result<char, string> result = Parser(consList); if (result != null) return new Result<char, Match2>( new Match2(consList.ArrayIndex, result.Tree.Length, result.Tree), result.Rest); else return new Result<char, Match2>(Match2.Empty, consList); }
protected override Result <char, Match2> Parse(ArrayConsList <char> consList, int afterLastMatchIndex) { Result <char, string> result = Parser(consList); if (result != null) { return(new Result <char, Match2>( new Match2(consList.ArrayIndex, result.Tree.Length, result.Tree), result.Rest)); } else { return(new Result <char, Match2>(Match2.Empty, consList)); } }
private bool doesAnchorMatch(AnchorType anchorType, ArrayConsList <char> currentPos, int afterLastMatchIndex) { switch (anchorType) { case AnchorType.StartOfString: return(currentPos.IsStartOfArray); case AnchorType.StartOfLine: return(currentPos.IsStartOfArray || currentPos.Prev == '\n'); case AnchorType.EndOfString: return(currentPos.IsEmpty); case AnchorType.EndOfLine: return(currentPos.IsEmpty || currentPos.Head == '\n'); case AnchorType.EndOfStringOrBeforeEndingNewline: return(currentPos.DropWhile(c => c == '\n').IsEmpty); case AnchorType.ContiguousMatch: return(currentPos.ArrayIndex == afterLastMatchIndex); case AnchorType.WordBoundary: return(isWordBoundary(currentPos)); case AnchorType.NonWordBoundary: return(!isWordBoundary(currentPos)); default: throw new ApplicationException( string.Format("BacktrackingMatcher: illegal anchor type ({0}).", anchorType.ToString())); } }
protected override Result <char, Match2> Parse(ArrayConsList <char> consList, int afterLastMatchIndex) { BacktrackPoint lastBacktrackPoint = null; StackFrame callStack = new GroupStackFrame(null, Pattern); var partialResult = new Result <char, int>(0, consList); while (callStack != null) { if (callStack is QuantifierStackFrame) { QuantifierStackFrame quantStackFrame = (QuantifierStackFrame)callStack; if (quantStackFrame.IsPositionChanged(partialResult.Tree)) { lastBacktrackPoint = new BacktrackPoint(lastBacktrackPoint, quantStackFrame.SecondAlternative(partialResult.Tree), partialResult); callStack = quantStackFrame.FirstAlternative(partialResult.Tree); } else { callStack = quantStackFrame.Parent; } } else { BasePattern currentPattern = callStack.RemainingChildren.Head; if (currentPattern.MinCharLength > partialResult.Rest.Length) { partialResult = null; } else { callStack = ((GroupStackFrame)callStack).MoveToNextChild(); switch (currentPattern.Type) { case PatternType.Group: callStack = new GroupStackFrame(callStack, ((GroupPattern)currentPattern).Patterns); break; case PatternType.Quantifier: var quant = (QuantifierPattern)currentPattern; quant.AssertCanonicalForm(); if (quant.MinOccurrences == quant.MaxOccurrences) { callStack = new GroupStackFrame(callStack, new RepeaterConsList <BasePattern>(quant.ChildPattern, quant.MinOccurrences)); } else { callStack = new QuantifierStackFrame(callStack, quant); } break; case PatternType.Alternation: var alternatives = ((AlternationPattern)currentPattern).Alternatives; foreach (var alt in alternatives.Skip(1).Reverse()) { lastBacktrackPoint = new BacktrackPoint(lastBacktrackPoint, new GroupStackFrame(callStack, alt), partialResult); } callStack = new GroupStackFrame(callStack, alternatives.First()); break; case PatternType.Anchor: if (!doesAnchorMatch(((AnchorPattern)currentPattern).AnchorType, (ArrayConsList <char>)partialResult.Rest, afterLastMatchIndex)) { partialResult = null; } break; case PatternType.Char: partialResult = parseChar(partialResult, ((CharPattern)currentPattern).IsMatch); break; default: throw new ApplicationException( string.Format("BacktrackingMatcher: unrecognized pattern type ({0}).", currentPattern.GetType().Name)); } } if (partialResult == null) { if (lastBacktrackPoint != null) { callStack = lastBacktrackPoint.CallStack; partialResult = lastBacktrackPoint.PartialResult; lastBacktrackPoint = lastBacktrackPoint.Previous; } else { return(new Result <char, Match2>(Match2.Empty, consList)); } } } callStack = unwindEmptyFrames(callStack); } return(new Result <char, Match2>( new Match2(consList.ArrayIndex, partialResult.Tree, consList.AsEnumerable().Take(partialResult.Tree).AsString()), partialResult.Rest)); }
private bool isWordBoundary(ArrayConsList <char> currentPos) { return((!currentPos.IsStartOfArray && CharGroupPattern.WordChar.IsMatch(currentPos.Prev)) ^ (!currentPos.IsEmpty && CharGroupPattern.WordChar.IsMatch(currentPos.Head))); }
protected abstract Result<char, Match2> Parse(ArrayConsList<char> consList, int afterLastMatchIndex);
protected override Result<char, Match2> Parse(ArrayConsList<char> consList, int afterLastMatchIndex) { BacktrackPoint lastBacktrackPoint = null; StackFrame callStack = new GroupStackFrame(null, Pattern); var partialResult = new Result<char, int>(0, consList); while (callStack != null) { if (callStack is QuantifierStackFrame) { QuantifierStackFrame quantStackFrame = (QuantifierStackFrame)callStack; if (quantStackFrame.IsPositionChanged(partialResult.Tree)) { lastBacktrackPoint = new BacktrackPoint(lastBacktrackPoint, quantStackFrame.SecondAlternative(partialResult.Tree), partialResult); callStack = quantStackFrame.FirstAlternative(partialResult.Tree); } else callStack = quantStackFrame.Parent; } else { BasePattern currentPattern = callStack.RemainingChildren.Head; if (currentPattern.MinCharLength > partialResult.Rest.Length) partialResult = null; else { callStack = ((GroupStackFrame)callStack).MoveToNextChild(); switch (currentPattern.Type) { case PatternType.Group: callStack = new GroupStackFrame(callStack, ((GroupPattern)currentPattern).Patterns); break; case PatternType.Quantifier: var quant = (QuantifierPattern)currentPattern; quant.AssertCanonicalForm(); if (quant.MinOccurrences == quant.MaxOccurrences) callStack = new GroupStackFrame(callStack, new RepeaterConsList<BasePattern>(quant.ChildPattern, quant.MinOccurrences)); else callStack = new QuantifierStackFrame(callStack, quant); break; case PatternType.Alternation: var alternatives = ((AlternationPattern)currentPattern).Alternatives; foreach (var alt in alternatives.Skip(1).Reverse()) lastBacktrackPoint = new BacktrackPoint(lastBacktrackPoint, new GroupStackFrame(callStack, alt), partialResult); callStack = new GroupStackFrame(callStack, alternatives.First()); break; case PatternType.Anchor: if (!doesAnchorMatch(((AnchorPattern)currentPattern).AnchorType, (ArrayConsList<char>)partialResult.Rest, afterLastMatchIndex)) partialResult = null; break; case PatternType.Char: partialResult = parseChar(partialResult, ((CharPattern)currentPattern).IsMatch); break; default: throw new ApplicationException( string.Format("BacktrackingMatcher: unrecognized pattern type ({0}).", currentPattern.GetType().Name)); } } if (partialResult == null) { if (lastBacktrackPoint != null) { callStack = lastBacktrackPoint.CallStack; partialResult = lastBacktrackPoint.PartialResult; lastBacktrackPoint = lastBacktrackPoint.Previous; } else return new Result<char, Match2>(Match2.Empty, consList); } } callStack = unwindEmptyFrames(callStack); } return new Result<char, Match2>( new Match2(consList.ArrayIndex, partialResult.Tree, consList.AsEnumerable().Take(partialResult.Tree).AsString()), partialResult.Rest); }
private bool isWordBoundary(ArrayConsList<char> currentPos) { return (!currentPos.IsStartOfArray && CharGroupPattern.WordChar.IsMatch(currentPos.Prev)) ^ (!currentPos.IsEmpty && CharGroupPattern.WordChar.IsMatch(currentPos.Head)); }
private bool doesAnchorMatch(AnchorType anchorType, ArrayConsList<char> currentPos, int afterLastMatchIndex) { switch (anchorType) { case AnchorType.StartOfString: return currentPos.IsStartOfArray; case AnchorType.StartOfLine: return currentPos.IsStartOfArray || currentPos.Prev == '\n'; case AnchorType.EndOfString: return currentPos.IsEmpty; case AnchorType.EndOfLine: return currentPos.IsEmpty || currentPos.Head == '\n'; case AnchorType.EndOfStringOrBeforeEndingNewline: return currentPos.DropWhile(c => c == '\n').IsEmpty; case AnchorType.ContiguousMatch: return currentPos.ArrayIndex == afterLastMatchIndex; case AnchorType.WordBoundary: return isWordBoundary(currentPos); case AnchorType.NonWordBoundary: return !isWordBoundary(currentPos); default: throw new ApplicationException( string.Format("BacktrackingMatcher: illegal anchor type ({0}).", anchorType.ToString())); } }
protected abstract Result <char, Match2> Parse(ArrayConsList <char> consList, int afterLastMatchIndex);
protected override Result <char, Match2> Parse(ArrayConsList <char> consList, int afterLastMatchIndex) { return(new Result <char, Match2>(Match2.Empty, consList)); }
protected override Result<char, Match2> Parse(ArrayConsList<char> consList, int afterLastMatchIndex) { return new Result<char, Match2>(Match2.Empty, consList); }