1 module pegged.cutter;
2 
3 import pegged.grammar;
4 
5 @safe:
6 
7 void optimize(TParseTree)(ref TParseTree p, string[] force = null, string[] keep = null)
8 {
9 	import std.algorithm : canFind, endsWith, startsWith;
10 	import std..string : indexOf;
11 
12 	if (p.children.length == 0)
13 		return;
14 	bool processed = true;
15 	while (processed)
16 	{
17 		processed = false;
18 		ParseTree[] new_children;
19 		foreach (ref child; p.children)
20 		{
21 			if (force !is null && force.canFind(child.name))
22 			{
23 			}
24 			else if (keep !is null && keep.canFind(child.name))
25 			{
26 				new_children ~= child;
27 				continue;
28 			}
29 			else if (child.children.length != 1)
30 			{
31 				new_children ~= child;
32 				continue;
33 			}
34 			foreach (ref grand_child; child.children)
35 			{
36 				new_children ~= grand_child;
37 			}
38 			processed = true;
39 		}
40 		p.children = new_children;
41 	}
42 	foreach (ref child; p.children)
43 	{
44 		optimize!TParseTree(child, force, keep);
45 	}
46 }
47 
48 void cutNodes(TParseTree)(ref TParseTree p, string[] names1 = null, string[] names2 = null)
49 {
50 	import std.algorithm : canFind, endsWith, startsWith;
51 	import std..string : indexOf;
52 
53 	if (p.name.endsWith(`_`))
54 	{
55 		p.matches.length = 0;
56 		p.name = p.name[0 .. $ - 1];
57 	}
58 	else if (names2 !is null && names2.canFind(p.name))
59 	{
60 		p.matches.length = 0;
61 	}
62 	if (p.children.length == 0)
63 		return;
64 	bool processed = true;
65 	while (processed)
66 	{
67 		processed = false;
68 		ParseTree[] new_children;
69 		foreach (ref child; p.children)
70 		{
71 			if (child.name == "any")
72 			{
73 			}
74 			else if (child.name.canFind('!'))
75 			{
76 			}
77 			else if (names1 !is null && names1.canFind(child.name))
78 			{
79 			}
80 			else if (child.name.indexOf("._") == -1)
81 			{
82 				new_children ~= child;
83 				continue;
84 			}
85 			foreach (ref grand_child; child.children)
86 			{
87 				new_children ~= grand_child;
88 			}
89 			processed = true;
90 		}
91 		p.children = new_children;
92 	}
93 	foreach (ref child; p.children)
94 	{
95 		cutNodes!TParseTree(child, names1, names2);
96 	}
97 }