protected override bool OnExecute(PatternState state) { state.BeginCollection(); PatternElement value = Value; bool success = value.Execute(state); List <object> items = state.EndCollection(); if (!success) { return(false); } if (state.Command != PatternCommand.End) { throw new Exception( "Successful pattern match with unexpected command"); } MatchIterator iterator = new MatchIterator(items); object result = state.EndDestination(iterator); state.AddToCollection(result); state.ClearCommand(); return(true); }
public void Visit(PatternElement root) { HashSet <PatternElement> ancestors = new HashSet <PatternElement>(); HashSet <PatternElement> visited = new HashSet <PatternElement>(); Visit(root, ancestors, visited); }
private TraceItem StartTrace(TraceKind kind, PatternElement source) { TraceItem traceElement = new TraceItem { Kind = kind, PatternElement = source, State = TraceState.InProgress }; Items.Add(traceElement); if (!Tally.TryGetValue(source, out TallyEntry entry)) { entry = new TallyEntry { LastPosition = 0, Count = 0 }; Tally.Add(source, entry); } if (entry.LastPosition != State.Enumerator.Index) { entry.Count = 0; entry.LastPosition = State.Enumerator.Index; } entry.Count++; if (entry.Count > CycleThreshold) { throw new Exception("Possible cycle detected!"); } return(traceElement); }
public static PatternElement Allow(PatternElement element) { return(new OptionalElement(element)); }
protected override bool OnCanExecute(PatternState state) { PatternElement value = Value; return(value.CanExecute(state)); }
public TraceItem OnExecute(PatternElement source) { return(StartTrace(TraceKind.Execute, source)); }
private void Visit( PatternElement current, HashSet <PatternElement> ancestors, HashSet <PatternElement> visited) { if (visited.Contains(current)) { return; } if (ancestors.Contains(current)) { string typeName = current.GetType().Name; current.SpecifySourceText($"{{Cycle: {typeName}}}"); return; } ancestors.Add(current); string result = ""; switch (current) { case Pattern pattern: Visit(pattern.Value, ancestors, visited); result = $"Pattern(\"{pattern.Name}\")"; break; case CommandElement command: string commandName = Enum .GetName(typeof(PatternCommand), command.Value); result = $"Command({commandName})"; break; case EmptyElement _: result = "Empty"; break; case EndElement end: string opName = "End"; if (end.Destination == null) { result = $"{opName}(null)"; break; } string enclosingName = end.Destination .Method .DeclaringType .Name; string fnName = end.Destination .Method .Name; result = $"{opName}({enclosingName}.{fnName})"; break; case OptionalElement option: Visit(option, ancestors, visited); result = $"Allow({option.Value})"; break; case Options options: foreach (PatternElement element in options.Elements) { Visit(element, ancestors, visited); } string elements = string.Join(" | ", options.Elements.Select(x => x.ToString())); result = $"({elements})"; break; case Sequence sequence: foreach (PatternElement element in sequence.Elements) { Visit(element, ancestors, visited); } elements = string.Join(" & ", sequence.Elements.Select(x => x.ToString())); result = elements; break; case TokenElement token: string typeName = Enum .GetName(typeof(TokenType), token.Type); result = $"Token({typeName}, {token.Content})"; break; case TokenTypeElement tokenType: typeName = Enum .GetName(typeof(TokenType), tokenType.Type); result = $"Token({typeName})"; break; default: throw new Exception("Unrecognized element type"); } ancestors.Remove(current); visited.Add(current); current.SpecifySourceText(result); }