예제 #1
0
 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);
     }
 }
예제 #2
0
        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);
            }
        }