internal static IEnumerable <ParseNode> TraverseSegmentsDepthFirst(this ParseNode startNode) { var visited = new HashSet <ParseNode>(); var stack = new Stack <ParseNode>(); var parents = startNode.AncestorsAndSelf(); stack.Push(startNode); while (stack.Any()) { var current = stack.Pop(); if (!visited.Add(current)) { continue; } if (current.Prefix == Prefixes.S) { yield return(current); } var neighbours = current.NeighboursWithExclusion(parents).Where(p => !visited.Contains(p)); foreach (var neighbour in neighbours.Reverse()) { stack.Push(neighbour); } } }
internal static object Analyze(this List <SegmentContext> segments, Separators separators, Type type, string rulesAssemblyName) { if (segments == null) { throw new ArgumentNullException("segments"); } if (separators == null) { throw new ArgumentNullException("separators"); } if (type == null) { throw new ArgumentNullException("type"); } var messageGrammar = ParseNode.BuldTree(type, true); if (messageGrammar.Prefix != Prefixes.M) { throw new Exception(string.Format("Only messages are supported: {0}", messageGrammar.Name)); } var segmentPosition = messageGrammar.Children.First(); var instancePosition = new ParseNode(type); foreach (var segment in segments) { if (segment.IsHeader) { continue; } Logger.Log(string.Format("Segment to match: {0}", segment.LogName)); try { // Jump back to HL segment if needed if (segment.IsJump) { segmentPosition = messageGrammar.JumpToHl(instancePosition.Root(), segment.ParentId); } var currSeg = segmentPosition.TraverseSegmentsDepthFirst().FirstOrDefault(n => n.IsEqual(segment)); if (currSeg == null) { throw new Exception( string.Format( "Segment {0} was not found after segment {1} in class {2}.", segment.Value, segmentPosition.EdiName, type.Name)); } var segmentTree = currSeg.AncestorsToIntersection(segmentPosition); instancePosition = instancePosition.AncestorsAndSelf().Last(nt => nt.Name == segmentTree.First().Parent.Name); foreach (var parseTree in segmentTree) { instancePosition = instancePosition.AddChild(parseTree.Type, parseTree.Type.Name); if (parseTree.Prefix == Prefixes.S) { instancePosition.ParseSegment(segment.Value, separators); } } segmentPosition = currSeg; } catch (Exception ex) { throw new ParserException("Failed at line: " + segment.Value, ex); } Logger.Log(string.Format("Matched segment: {0}", segmentPosition.Name)); } return(instancePosition.Root().ToInstance()); }