Ejemplo n.º 1
0
 public ThompsonsConstruction()
 {
     _nfa         = new Automaton();
     _start_state = new State(_nfa);
     _nfa.AddStartState(_start_state);
 }
Ejemplo n.º 2
0
 public State FindHashSetState(Automaton dfa, SmartSet <State> states)
 {
     _hash_sets.TryGetValue(states, out State result);
     return(result);
 }
Ejemplo n.º 3
0
        /* Apply powerset construction to the NFA to convert to a DFA.
         * Note, the result of this method isn't strictly a DFA because
         * edges in the automaton can be text or code, which function just like
         * epsilon transitions--no input is consumed for the edge.
         */
        public Automaton Optimize(Automaton nfa)
        {
            var dfa = new Automaton();

            // For every state s, compute collection of states along epsilon edges
            // to get an initial computation of dfa states.
            foreach (var s in nfa.Vertices)
            {
                var c = ClosureTaker.GetClosure(new List <State> {
                    s
                }, nfa);
                _closure[s] = c;
            }

            // For every state set, compute sums and fix up state sets.
            foreach (var p in _closure)
            {
                var key = p.Key;
                var set = p.Value;
                foreach (var s in set)
                {
                    _closure[s].UnionWith(set);
                }
            }

            // For every state in nfa using Tarjan walk,
            // sum sets with common transitions.
            var ordered_list = new TarjanNoBackEdges <State, Edge>(nfa).ToList();

            ordered_list.Reverse();
            var changed = true;

            while (changed)
            {
                changed = false;
                foreach (var s in ordered_list)
                {
                    var closure     = _closure[s];
                    var transitions = ClosureTaker.GatherTransitions(closure);
                    foreach (var transition_set in transitions)
                    {
                        var key       = transition_set.Key;
                        var value     = transition_set.Value;
                        var state_set = new SmartSet <State>();
                        // All states in value must have common set in dfa.
                        foreach (var e in value)
                        {
                            var c  = e.To;
                            var cl = _closure[c];
                            state_set.UnionWith(cl);
                        }

                        foreach (var c in state_set)
                        {
                            if (!_closure[c].Equals(state_set))
                            {
                                _closure[c] = state_set;
                                changed     = true;
                            }
                        }
                    }
                }
            }

            var initialState = CreateInitialState(nfa, dfa);

            foreach (var p in _closure)
            {
                var state_set     = p.Value;
                var new_dfa_state = FindHashSetState(dfa, state_set);
                if (new_dfa_state == null)
                {
                    var state = AddHashSetState(dfa, state_set);
                    {
                        var mark = false;
                        foreach (var s in state_set)
                        {
                            if (nfa.FinalStates.Contains(s))
                            {
                                mark = true;
                            }
                        }
                        if (mark && !dfa.FinalStates.Contains(state))
                        {
                            dfa.AddFinalState(state);
                        }
                    }
                }
            }

            //System.Console.Error.WriteLine(dfa.ToString());

            foreach (var p in _closure)
            {
                var k         = p.Key;
                var state_set = p.Value;
                var dfa_state = FindHashSetState(dfa, state_set);
                //     System.Console.Error.WriteLine("State " + dfa_state.Id + ":"
                //                                    + state_set.Aggregate(
                //                                        "", // start with empty string to handle empty list case.
                //                                       (current, next) => current + ", " + next));
            }

            //System.Console.Error.WriteLine(dfa.ToString());
            foreach (var from_dfa_state in dfa.Vertices)
            {
                var nfa_state_set = FindHashSet(from_dfa_state);
                var transitions   = ClosureTaker.GatherTransitions(nfa_state_set);
                foreach (var transition_set in transitions)
                {
                    // Note, transitions is a collection of edges for a given string.
                    // For the NFA, an edge has one Ast for the edge because it came from one pattern.
                    // But, for the DFA, there could be multiple edges for the same string,
                    // each from a different pattern! Compute the set of Asts for
                    // all edges.
                    var key       = transition_set.Key;
                    var value     = transition_set.Value;
                    var state_set = new HashSet <State>();
                    foreach (var e in value)
                    {
                        state_set.Add(e.To);
                    }
                    // Find in all previous states.
                    var new_state_set = _hash_sets.Where(hs => state_set.IsSubsetOf(hs.Key)).FirstOrDefault().Key;
                    if (new_state_set == null)
                    {
                        new_state_set = _closure[state_set.First()];
                    }
                    var to_dfa_state = FindHashSetState(dfa, new_state_set);
                    var mods         = value.First().EdgeModifiers;
                    var asts         = new List <IParseTree>();
                    foreach (var v in value)
                    {
                        foreach (var v2 in v.AstList)
                        {
                            asts.Add(v2);
                        }
                    }
                    var he = new Edge(dfa, from_dfa_state, to_dfa_state, asts, mods);
                }
            }

            // Add in "any" fragment in order to match tree nodes that aren't in pattern.
            //{
            //    State s3 = new State(dfa); s3.Commit();
            //    var e1 = new Edge(dfa, s3, s3, null, Edge.EmptyAst, (int)Edge.EdgeModifiers.Any); e1.Commit();
            //    var f = new Fragment(s3);
            //}

            return(dfa);
        }
Ejemplo n.º 4
0
        public void Match()
        {
            foreach (var pass in _passes)
            {
                _current_type = pass.Owner.Type;
                if (Piggy._debug_information)
                {
                    Console.Error.WriteLine(pass.Owner.TemplateName + " " + pass.Name);
                }
                var thompsons_construction = new ThompsonsConstruction();
                var nfa = thompsons_construction.NFA;
                foreach (var pattern in pass.Patterns)
                {
                    thompsons_construction.post2nfa(pattern);
                }
                if (Piggy._debug_information)
                {
                    Console.Error.WriteLine(nfa);
                }
                var       nfa_optimizer = new NfaOptimizer();
                Automaton optimized_nfa = null;
                if (false)
                {
                    optimized_nfa = nfa_optimizer.Optimize(nfa);
                }
                else
                {
                    optimized_nfa = nfa;
                }
                if (Piggy._debug_information)
                {
                    Console.Error.WriteLine(optimized_nfa);
                }

                // Perform naive matching for each node.
                foreach (var input in _ast.Preorder())
                {
                    if (!(input as AstParserParser.NodeContext != null ||
                          input as AstParserParser.AttrContext != null))
                    {
                        continue;
                    }

                    var has_previous_match = _matches.Contains(input);
                    var do_matching        = !has_previous_match;
                    if (has_previous_match)
                    {
                        continue;
                    }

                    var currentStateList = new List <State>();
                    var currentPathList  = new List <Path>();
                    var nextPathList     = new List <Path>();
                    var nextStateList    = new List <State>();
                    var nfa_match        = new NfaMatch(_piggy._code_blocks, _instance, optimized_nfa);
                    var start            = optimized_nfa.StartStates.FirstOrDefault().Id;
                    var st = optimized_nfa.Vertices.Where(s => s.Id == start).FirstOrDefault();
                    nfa_match.AddStateAndClosure(currentStateList, st);
                    if (Piggy._debug_information)
                    {
                        System.Console.Error.WriteLine("Looking at " + input.GetText().Truncate(40));
                    }
                    var matched = nfa_match.FindMatches(currentPathList, currentStateList, ref nextPathList,
                                                        ref nextStateList, input);
                    if (matched)
                    {
                        // If this node matched, then mark entire subtree as matched.
                        var stack = new Stack <IParseTree>();
                        stack.Push(input);
                        while (stack.Count > 0)
                        {
                            var v = stack.Pop();
                            _matches.Add(v);
                            for (var i = v.ChildCount - 1; i >= 0; --i)
                            {
                                var c = v.GetChild(i);
                                stack.Push(c);
                            }
                        }

                        _top_level_matches.Add(input);
                        foreach (var p in nextPathList)
                        {
                            _matches_path_start.MyAdd(input, p);
                        }
                    }
                }
            }
        }