Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4c2821c

Browse files
authored
Fix hopcroft DFA minimization and add plot graph function
1 parent 5d3a828 commit 4c2821c

File tree

2 files changed

+177
-32
lines changed

2 files changed

+177
-32
lines changed

‎ParserGenerator.cs‎

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*
1+
/*
22
33
Copyright (C) 2019. rollrat All Rights Reserved.
44
@@ -13,41 +13,24 @@
1313

1414
namespace ParserGenerator
1515
{
16-
public class ParserAction
17-
{
18-
public Action<ParsingTree.ParsingTreeNode> SemanticAction;
19-
public static ParserAction Create(Action<ParsingTree.ParsingTreeNode> action)
20-
=> new ParserAction { SemanticAction = action };
21-
}
22-
2316
public class ParserProduction
2417
{
2518
public int index;
2619
public string production_name;
2720
public bool isterminal;
2821
public List<ParserProduction> contents = new List<ParserProduction>();
2922
public List<List<ParserProduction>> sub_productions = new List<List<ParserProduction>>();
30-
public List<ParserAction> temp_actions = new List<ParserAction>();
31-
public List<ParserAction> actions = new List<ParserAction>();
3223

3324
public static ParserProduction operator +(ParserProduction p1, ParserProduction p2)
3425
{
3526
p1.contents.Add(p2);
3627
return p1;
3728
}
3829

39-
public static ParserProduction operator +(ParserProduction pp, ParserAction ac)
40-
{
41-
pp.temp_actions.Add(ac);
42-
return pp;
43-
}
44-
4530
public static ParserProduction operator |(ParserProduction p1, ParserProduction p2)
4631
{
4732
p2.contents.Insert(0, p2);
4833
p1.sub_productions.Add(new List<ParserProduction>(p2.contents));
49-
p1.actions.AddRange(p2.temp_actions);
50-
p2.temp_actions.Clear();
5134
p2.contents.Clear();
5235
return p1;
5336
}
@@ -1283,7 +1266,6 @@ public ShiftReduceParser CreateShiftReduceParserInstance()
12831266
var grammar = new List<List<int>>();
12841267
var grammar_group = new List<int>();
12851268
var production_mapping = new List<List<int>>();
1286-
var semantic_rules = new List<ParserAction>();
12871269
var pm_count = 0;
12881270

12891271
foreach (var pr in production_rules)
@@ -1298,7 +1280,6 @@ public ShiftReduceParser CreateShiftReduceParserInstance()
12981280
}
12991281
grammar.AddRange(ll);
13001282
production_mapping.Add(pm);
1301-
semantic_rules.AddRange(pr.actions);
13021283
}
13031284

13041285
for (int i = 0; i < number_of_states; i++)
@@ -1335,7 +1316,7 @@ public ShiftReduceParser CreateShiftReduceParserInstance()
13351316
}
13361317
}
13371318

1338-
return new ShiftReduceParser(symbol_table, jump_table, goto_table, grammar_group.ToArray(), grammar.Select(x => x.ToArray()).ToArray(),semantic_rules);
1319+
return new ShiftReduceParser(symbol_table, jump_table, goto_table, grammar_group.ToArray(), grammar.Select(x => x.ToArray()).ToArray());
13391320
}
13401321
}
13411322

@@ -1358,7 +1339,7 @@ public static ParsingTreeNode NewNode(string production, string contents)
13581339
=> new ParsingTreeNode { Parent = null, Childs = new List<ParsingTreeNode>(), Produnction = production, Contents = contents };
13591340
}
13601341

1361-
publicParsingTreeNode root;
1342+
ParsingTreeNode root;
13621343

13631344
public ParsingTree(ParsingTreeNode root)
13641345
{
@@ -1375,7 +1356,6 @@ public class ShiftReduceParser
13751356
List<string> symbol_index_name = new List<string>();
13761357
Stack<int> state_stack = new Stack<int>();
13771358
Stack<ParsingTree.ParsingTreeNode> treenode_stack = new Stack<ParsingTree.ParsingTreeNode>();
1378-
List<ParserAction> actions;
13791359

13801360
// 3 1 2 0
13811361
// Accept? Shift? Reduce? Error?
@@ -1384,14 +1364,13 @@ public class ShiftReduceParser
13841364
int[][] production;
13851365
int[] group_table;
13861366

1387-
public ShiftReduceParser(Dictionary<string, int> symbol_table, int[][] jump_table, int[][] goto_table, int[] group_table, int[][] production,List<ParserAction>actions)
1367+
public ShiftReduceParser(Dictionary<string, int> symbol_table, int[][] jump_table, int[][] goto_table, int[] group_table, int[][] production)
13881368
{
13891369
symbol_name_index = symbol_table;
13901370
this.jump_table = jump_table;
13911371
this.goto_table = goto_table;
13921372
this.production = production;
13931373
this.group_table = group_table;
1394-
this.actions = actions;
13951374
var l = symbol_table.ToList().Select(x => new Tuple<int, string>(x.Value, x.Key)).ToList();
13961375
l.Sort();
13971376
l.ForEach(x => symbol_index_name.Add(x.Item2));
@@ -1472,7 +1451,6 @@ private void reduce(int index)
14721451
reduction_parent.Contents = string.Join("", reduce_treenodes.Select(x => x.Contents));
14731452
reduction_parent.Childs = reduce_treenodes;
14741453
treenode_stack.Push(reduction_parent);
1475-
actions[reduction_parent.ProductionRuleIndex].SemanticAction(reduction_parent);
14761454
}
14771455
}
1478-
}
1456+
}

‎ScannerGenerator.cs‎

Lines changed: 172 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@ public class diagram
6262
public void MakeNFA(string pattern) { Diagram = make_nfa("(" + pattern + ")"); }
6363
public void OptimizeNFA() { while (opt_nfa(Diagram)) ; }
6464
public void NFAtoDFA() { Diagram = nfa2dfa(Diagram); }
65-
public void MinimizeDFA() { opt_dfa(Diagram); }
65+
public void MinimizeDFA() { opt_dfa_hopcroft(Diagram); }
6666
public string PrintDiagram() { return print_diagram(Diagram); }
6767

6868
public static string PrintDiagram(diagram dia) { return print_diagram(dia); }
69+
public static string PrintGraph(diagram dia) { return print_diagram_for_graphviz(dia); }
6970

7071
/// <summary>
7172
/// Try simple-regular-expression to optimized DFA
@@ -342,6 +343,86 @@ private static string print_diagram(diagram d)
342343
return builder.ToString();
343344
}
344345

346+
private static string print_diagram_for_graphviz(diagram d)
347+
{
348+
var builder = new StringBuilder();
349+
var used = new HashSet<int>();
350+
351+
var stack_used = new Stack<transition_node>();
352+
var check_used = new List<bool>(d.count_of_vertex);
353+
check_used.AddRange(Enumerable.Repeat(false, d.count_of_vertex));
354+
355+
stack_used.Push(d.start_node);
356+
used.Add(d.start_node.index);
357+
358+
while (stack_used.Count != 0)
359+
{
360+
var tn = stack_used.Pop();
361+
if (check_used[tn.index]) continue;
362+
check_used[tn.index] = true;
363+
364+
used.Add(tn.index);
365+
366+
tn.transition.ForEach(x => stack_used.Push(x.Item2));
367+
}
368+
369+
builder.Append("digraph finite_state_machine {\r\n");
370+
builder.Append(" rankdir=LR;\r\n");
371+
builder.Append(" size=\"20,30\"\r\n");
372+
373+
// print doublecircle
374+
builder.Append(" node [shape = doublecircle]; ");
375+
foreach (var dd in d.nodes)
376+
if (dd.is_acceptable && used.Contains(dd.index))
377+
builder.Append(dd.index + "; ");
378+
builder.Append("\r\n");
379+
380+
// print point
381+
builder.Append(" node [shape = point]; ss\r\n");
382+
383+
// print circle
384+
builder.Append(" node [shape = circle];\r\n");
385+
386+
var stack = new Stack<transition_node>();
387+
var check = new List<bool>(d.count_of_vertex);
388+
check.AddRange(Enumerable.Repeat(false, d.count_of_vertex));
389+
390+
stack.Push(d.start_node);
391+
builder.Append($" ss -> {d.start_node.index}");
392+
393+
while (stack.Count != 0)
394+
{
395+
var tn = stack.Pop();
396+
if (check[tn.index]) continue;
397+
check[tn.index] = true;
398+
399+
foreach (var j in tn.transition)
400+
{
401+
string v = "";
402+
if (j.Item1 == e_closure)
403+
v = "&epsilon;";
404+
else if (j.Item1 == '"')
405+
v = "\"";
406+
else if (j.Item1 == '\n')
407+
v = "\\n";
408+
else if (j.Item1 == '\r')
409+
v = "\\r";
410+
else if (j.Item1 == '\t')
411+
v = "\\t";
412+
else
413+
v = new string(j.Item1, 1);
414+
415+
builder.Append($@" {tn.index} -> {j.Item2.index} [ label = ""{v}"" ];" + "\r\n");
416+
}
417+
418+
tn.transition.ForEach(x => stack.Push(x.Item2));
419+
}
420+
421+
builder.Append("}");
422+
423+
return builder.ToString();
424+
}
425+
345426
/// <summary>
346427
/// Get inverse array of diagram nodes
347428
/// </summary>
@@ -612,8 +693,7 @@ private diagram nfa2dfa(diagram dia)
612693
break;
613694
}
614695
}
615-
616-
696+
617697
diagram.count_of_vertex = transition_node_list.Count;
618698
diagram.nodes = transition_node_list;
619699
diagram.start_node = transition_node_list[0];
@@ -661,7 +741,7 @@ private void opt_dfa(diagram dia)
661741
}
662742

663743
color_count++;
664-
744+
665745
while (true)
666746
{
667747
// Collect transition color
@@ -700,6 +780,93 @@ private void opt_dfa(diagram dia)
700780

701781
previous_group = group;
702782
}
783+
784+
var dicc = new Dictionary<int, int>();
785+
var inverse_transition = get_inverse_transtition(dia);
786+
for (int i = 0; i < color.Count; i++)
787+
if (!dicc.ContainsKey(color[i]))
788+
dicc.Add(color[i], i);
789+
else if (inverse_transition.ContainsKey(i))
790+
{
791+
foreach (var inv in inverse_transition[i])
792+
for (int j = 0; j < dia.nodes[inv].transition.Count; j++)
793+
if (dia.nodes[inv].transition[j].Item2.index == i)
794+
dia.nodes[inv].transition[j] = new Tuple<char, transition_node>(dia.nodes[inv].transition[j].Item1, dia.nodes[dicc[color[i]]]);
795+
}
796+
}
797+
798+
/// <summary>
799+
/// Minimization DFA using Hopcroft Algorithm
800+
/// </summary>
801+
/// <param name="dia"></param>
802+
/// <returns></returns>
803+
private void opt_dfa_hopcroft(diagram dia)
804+
{
805+
var visit = new HashSet<string>();
806+
var queue = new Queue<List<int>>();
807+
808+
// Enqueue Nodes
809+
var acc_nodes = new List<int>();
810+
var nacc_nodes = new List<int>();
811+
foreach (var node in dia.nodes)
812+
if (node.is_acceptable)
813+
acc_nodes.Add(node.index);
814+
else
815+
nacc_nodes.Add(node.index);
816+
817+
queue.Enqueue(acc_nodes);
818+
queue.Enqueue(nacc_nodes);
819+
820+
var color = new List<int>();
821+
var color_count = 1;
822+
color.AddRange(Enumerable.Repeat(0, dia.count_of_vertex));
823+
824+
acc_nodes.ForEach(x => color[x] = color_count);
825+
color_count = 1;
826+
827+
while (queue.Count > 0)
828+
{
829+
var front = queue.Dequeue();
830+
front.Sort();
831+
var str = string.Join(",", front);
832+
833+
if (visit.Contains(str)) continue;
834+
visit.Add(str);
835+
836+
//foreach (var node in front)
837+
// color[node] = color_count;
838+
//color_count++;
839+
840+
// Collect transition color
841+
var dic = new Dictionary<int, SortedDictionary<char, int>>();
842+
foreach (var index in front)
843+
{
844+
var node = dia.nodes[index];
845+
foreach (var ts in node.transition)
846+
{
847+
if (!dic.ContainsKey(node.index))
848+
dic.Add(node.index, new SortedDictionary<char, int>());
849+
dic[node.index].Add(ts.Item1, color[ts.Item2.index]);
850+
}
851+
}
852+
853+
var list = dic.ToList();
854+
var group = new Dictionary<string, List<int>>();
855+
for (int i = 0; i < list.Count; i++)
856+
{
857+
var ds = dic2str(list[i].Value);
858+
if (!group.ContainsKey(ds))
859+
group.Add(ds, new List<int>());
860+
group[ds].Add(list[i].Key);
861+
}
862+
863+
foreach (var gi in group)
864+
{
865+
queue.Enqueue(gi.Value);
866+
gi.Value.ForEach(x => color[x] = color_count);
867+
color_count++;
868+
}
869+
}
703870

704871
var dicc = new Dictionary<int, int>();
705872
var inverse_transition = get_inverse_transtition(dia);
@@ -1004,4 +1171,4 @@ public Tuple<string, string, int, int> Lookahead()
10041171
return result;
10051172
}
10061173
}
1007-
}
1174+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /