public ThompsonsConstruction() { _nfa = new Automaton(); _start_state = new State(_nfa); _nfa.AddStartState(_start_state); }
public State FindHashSetState(Automaton dfa, SmartSet <State> states) { _hash_sets.TryGetValue(states, out State result); return(result); }
/* 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); }
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); } } } } }