private void SubGenerate(GeneratorScope scope, IReadOnlyList <KeyValuePair <uint, RegExEvaluationNode> > nodes, int a, int b, RegExEvaluationNode target, ushort?currentState) { if (a > b) { scope.Goto(target == null ? scope.AcceptLabel(currentState) : scope.StateLabel(target.Id)); } else { var m = (a + b) / 2; var pair = nodes[m]; scope.IfBegin(pair.Key, m - a); SubGenerate(scope.Indent(), nodes, a, m - 1, pair.Value, currentState); scope.IfEnd(m - a); SubGenerate(scope, nodes, m + 1, b, target, currentState); } }
private void GenerateCode(GeneratorScope scope, RegExEvaluationNode node) { var dfa = _dfaStates[node.Id]; var currentState = dfa.SmallestAcceptState; #if DIAGNOSTICS Console.WriteLine($"Code generation for of state {dfa.DfaId}:"); foreach (var range in node) { Console.WriteLine($" range {range.Key.Min}-{range.Key.Max} {range.Value?.Id} {range.Value?.AcceptAction}"); } #endif var points = new SortedDictionary <uint, RegExEvaluationNode>(); RegExEvaluationNode lastValue = null; uint lastSuccessor = 0; foreach (var pair in node) { if ((pair.Value == lastValue) && (lastSuccessor == pair.Key.Min)) { points.Remove(lastSuccessor); } else if (lastSuccessor < pair.Key.Min) { points.Add(pair.Key.Min, null); } lastSuccessor = pair.Key.Max + 1; points.Add(lastSuccessor, pair.Value); lastValue = pair.Value; } if (lastSuccessor == char.MaxValue + 1) { points.Remove(lastSuccessor); } else { lastValue = null; } #if DIAGNOSTICS Console.WriteLine("Points:"); foreach (var pair in points) { Console.WriteLine(" point {0} -> {1}", pair.Key, pair.Value != null ? $"{pair.Value.Id} ({pair.Value.AcceptAction})" : string.Empty); } #endif var accept = node.AcceptAction.HasValue ? $" (accepts to {node.AcceptAction.Value})" : string.Empty; scope.WriteLine("/*"); scope.WriteLine(" * DFA STATE {0}{1}", node.Id, accept); foreach (var map in node) { scope.WriteLine(" * {0} -> {1}", map.Key, map.Value.Id); } scope.WriteLine(" */"); if ((node.Id > 0) || NodeIsReferenced(node)) { scope.SetLabel(scope.StateLabel(node.Id)); } if (node.AcceptAction.HasValue && !(node.AcceptAction > currentState)) { scope.MarkPos(); if (node.Count > 0) { scope.IncrementPos(scope.AcceptLabel(node.AcceptAction), node.Id == 0); } } else { if (node.Count > 0) { scope.IncrementPos(scope.AcceptLabel(currentState), node.Id == 0); } } var pointList = points.ToList(); if ((pointList.Count == 0) && (node.Count == 0)) { scope.Goto(scope.AcceptLabel(currentState)); } else { SubGenerate(scope, pointList, 0, points.Count - 1, lastValue, currentState); } }