Skip to content

Commit c3158d7

Browse files
author
Viktor Chernev
committed
Grammar testing
1 parent 67e41d4 commit c3158d7

File tree

228 files changed

+44043
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

228 files changed

+44043
-1
lines changed

@DescribeCompilerAPI/Compiler/DescribeCompiler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public IDescribeOptimizer Optimizer
3333
/// </summary>
3434
/// <param name="grammarName">The enumerated name of the grammar to be loaded</param>
3535
/// <returns>true if successful, otherwise false</returns>
36-
bool ChangeGrammar(GrammarName grammarName)
36+
public bool ChangeGrammar(GrammarName grammarName)
3737
{
3838
try
3939
{

@DescribeCompilerAPI/Compiler/Optimizers/DefaultOptimizer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace DescribeCompiler
99
{
10+
//http://www.goldparser.org/doc/grammars/predefined-sets.htm
1011
public class DefaultOptimizer : IDescribeOptimizer
1112
{
1213
//Misc
Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
using GoldParser.Grammar;
2+
using GoldParser.ParseTree;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace DescribeCompiler.Compiler.Optimizers
10+
{
11+
//http://www.goldparser.org/doc/grammars/predefined-sets.htm
12+
public class OptimizerForDescribe06 : IDescribeOptimizer
13+
{
14+
//Misc
15+
private static Random random = new Random();
16+
private static string getRandomString(int length = 8)
17+
{
18+
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
19+
return new string(Enumerable.Repeat(chars, length)
20+
.Select(s => s[random.Next(s.Length)]).ToArray());
21+
}
22+
23+
24+
//Name
25+
private string GetRuleName(Reduction r)
26+
{
27+
string ruleName = r.Production.Head.Name;
28+
return ruleName;
29+
}
30+
31+
32+
33+
//Text
34+
//<text-chunk>
35+
//::= Text | EscapeHyphen | EscapeLeftArrow | EscapeRightArrow | EscapeSeparator
36+
//| EscapeTerminator | EscapeStar | EscapeFSlash | EscapeBSlash
37+
private string DoTextChunk(Reduction r)
38+
{
39+
GrammarSymbol sym = r.Production.Handle[0];
40+
string text = "";
41+
switch (sym.Name)
42+
{
43+
case "Text":
44+
default:
45+
text = r[0].Data.ToString();
46+
break;
47+
case "EscapeHyphen":
48+
case "EscapeLeftArrow":
49+
case "EscapeRightArrow":
50+
case "EscapeSeparator":
51+
case "EscapeTerminator":
52+
case "EscapeStar":
53+
case "EscapeFSlash":
54+
text = r[0].Data.ToString().Replace("\\", "");
55+
break;
56+
case "EscapeBSlash":
57+
text = r[0].Data.ToString().Replace("\\\\", "\\");
58+
break;
59+
}
60+
string s = r[0].Data.ToString();
61+
return text;
62+
}
63+
64+
//<text-chunk-list>
65+
//::= <text-chunk> <text-chunk>
66+
//| <text-chunk> <text-chunk-list>
67+
private string DoTextChunkList(Reduction r)
68+
{
69+
string s1 = DoTextChunk(r[0].Data as Reduction);
70+
71+
string ruleName = GetRuleName(r[1].Data as Reduction);
72+
if (ruleName == "text-chunk")
73+
{
74+
string s2 = DoTextChunk(r[1].Data as Reduction);
75+
string s = s1 + s2;
76+
return s;
77+
}
78+
else
79+
{
80+
string s2 = DoTextChunkList(r[1].Data as Reduction);
81+
string s = s1 + s2;
82+
return s;
83+
}
84+
}
85+
86+
//<text>
87+
//::= <text-chunk>
88+
//| <text-chunk-list>
89+
private string DoText(Reduction r)
90+
{
91+
string ruleName = GetRuleName(r[0].Data as Reduction);
92+
if (ruleName == "text-chunk")
93+
{
94+
string s = DoTextChunk(r[0].Data as Reduction);
95+
return s;
96+
}
97+
else if (ruleName == "text-chunk-list")
98+
{
99+
string s = DoTextChunkList(r[0].Data as Reduction);
100+
return s;
101+
}
102+
else return null;
103+
}
104+
105+
106+
//ITEMS
107+
//<item>
108+
//:= <text> <tag> Link Decorator
109+
//| <text> <tag> <links> <decorators>
110+
//not in that order though
111+
private string DoItem(DescribeUnfold u, Reduction r)
112+
{
113+
string text = null;
114+
for (int i = 0; i < r.Count(); i++)
115+
{
116+
string ruleName = r[i].Symbol.Name;
117+
switch (ruleName)
118+
{
119+
case "text":
120+
text = DoText(r[i].Data as Reduction);
121+
text = text.Trim();
122+
break;
123+
}
124+
}
125+
126+
//text can't be null
127+
if (text == null) return null;
128+
129+
//tag
130+
string tag = getRandomString();
131+
if (!u.Translations.Keys.Contains(tag))
132+
{
133+
u.Translations.Add(tag, text);
134+
}
135+
else
136+
{
137+
//redefinition
138+
u.Translations[tag] = text;
139+
}
140+
141+
//idFile
142+
if (u.ItemIdFile.ContainsKey(tag) == false)
143+
{
144+
u.ItemIdFile.Add(tag, new List<string>() { u.CurFile });
145+
}
146+
else
147+
{
148+
u.ItemIdFile[tag].Add(u.CurFile);
149+
}
150+
151+
return tag;
152+
}
153+
154+
//<item-or-expression>
155+
//::= <item>
156+
//| <expression>
157+
private string DoItemOrExpression(DescribeUnfold u, Reduction r)
158+
{
159+
string ruleName = GetRuleName(r[0].Data as Reduction);
160+
if (ruleName == "item")
161+
{
162+
string key = DoItem(u, r[0].Data as Reduction);
163+
return key;
164+
}
165+
else if (ruleName == "expression")
166+
{
167+
string key = DoExpression(u, r[0].Data as Reduction);
168+
return key;
169+
}
170+
else return null;
171+
}
172+
173+
//<item-or-expression-list>
174+
//::= <item> Separator <item>
175+
//| <item> Separator <expression>
176+
//| <item> Separator <item-or-expression-list>
177+
//| <expression> <item>
178+
//| <expression> <expression>
179+
//| <expression> <item-or-expression-list>
180+
private string[] DoItemOrExpressionList(DescribeUnfold u, Reduction r)
181+
{
182+
//this method is about a list of "ItemOrExpression"
183+
string ruleName1 = GetRuleName(r[0].Data as Reduction);
184+
185+
string key1 = "";
186+
if (ruleName1 == "item") key1 = DoItem(u, r[0].Data as Reduction);
187+
else if (ruleName1 == "expression") key1 = DoExpression(u, r[0].Data as Reduction);
188+
else return null;
189+
190+
Reduction reduction = null;
191+
if (ruleName1 == "item") reduction = r[2].Data as Reduction;
192+
else if (ruleName1 == "expression") reduction = r[1].Data as Reduction;
193+
List<string> list = new List<string>() { key1 };
194+
195+
string ruleName2 = GetRuleName(reduction);
196+
if (ruleName2 == "item")
197+
{
198+
string key = DoItem(u, reduction);
199+
list.Add(key);
200+
}
201+
else if (ruleName2 == "expression")
202+
{
203+
string key = DoExpression(u, reduction);
204+
list.Add(key);
205+
}
206+
else if (ruleName2 == "item-or-expression-list")
207+
{
208+
string[] keys = DoItemOrExpressionList(u, reduction);
209+
for (int i = 0; i < keys.Length; i++) list.Add(keys[i]);
210+
}
211+
212+
return list.ToArray();
213+
}
214+
215+
216+
217+
218+
219+
// EXPRESSIONS
220+
221+
//<expression>
222+
//::= <item> <producer> Terminator
223+
//| <item> <producer> <item-or-expression> Terminator
224+
//| <item> <producer> <item-or-expression-list> Terminator
225+
//| <item> <producer> <item-or-expression>
226+
//| <item> <producer> <item-or-expression-list>
227+
private string DoExpression(DescribeUnfold u, Reduction r)
228+
{
229+
string head = DoItem(u, r[0].Data as Reduction);
230+
231+
//empty production treated as item
232+
if (r[2] is Token && r[2].Data.ToString() == ";")
233+
{
234+
return head;
235+
}
236+
237+
//otherwise continue as normal production
238+
string ruleName = GetRuleName(r[2].Data as Reduction);
239+
if (ruleName == "Terminator")
240+
{
241+
u.Productions.Add(head, new List<string>());
242+
}
243+
else if (ruleName == "item-or-expression")
244+
{
245+
string right = DoItemOrExpression(u, r[2].Data as Reduction);
246+
//check for id collision
247+
//item with same id is redefinition,
248+
//but 2 productions heads with same id is collision
249+
if (u.Productions.ContainsKey(head))
250+
{
251+
string item = u.Translations[head] + " <" + head + ">";
252+
string prodfile = u.ProdIdFile[head];
253+
string message = "Collision! Item \"" + item +
254+
"\" - there is production head with the same id in file: \"" +
255+
prodfile + "\"";
256+
throw new Exception(message);
257+
}
258+
u.Productions.Add(head, new List<string>() { right });
259+
}
260+
else if (ruleName == "item-or-expression-list")
261+
{
262+
string[] rights = DoItemOrExpressionList(u, r[2].Data as Reduction);
263+
//check for id collision
264+
//item with same id is redefinition,
265+
//but 2 productions heads with same id is collision
266+
if (u.Productions.ContainsKey(head))
267+
{
268+
string item = u.Translations[head] + " <" + head + ">";
269+
string prodfile = u.ProdIdFile[head];
270+
string message = "Collision! Item \"" + item +
271+
"\" - there is production head with the same id in file: \"" +
272+
prodfile + "\"";
273+
throw new Exception(message);
274+
}
275+
u.Productions.Add(head, rights.ToList());
276+
}
277+
278+
//idFile
279+
u.ProdIdFile.Add(head, u.CurFile);
280+
281+
//return
282+
return head;
283+
}
284+
285+
//<expression-list>
286+
//::= <expression> <expression>
287+
//| <expression> <expression-list>
288+
private string[] DoExpressionList(DescribeUnfold u, Reduction r, bool isPrimery = false)
289+
{
290+
//this method is about a list of "Expression"
291+
string key1 = DoExpression(u, r[0].Data as Reduction);
292+
293+
//isPrimery meant that it is expressionList directly in the scripture
294+
//element - where we might find valid nammespace directive
295+
bool removeKey = false;
296+
if (isPrimery)
297+
{
298+
//setup the Namespace field in the unfold
299+
//production literal is "directives" or "DIRECTIVES".
300+
//if we have only one production then we won't be doing this check
301+
//for now and just parse it, be it a directive
302+
string literal = u.Translations[key1];
303+
if (literal == "directives" || literal == "DIRECTIVES")
304+
{
305+
List<string> directives = u.Productions[key1];
306+
foreach (string directive in directives)
307+
{
308+
string keyword = u.Translations[directive];
309+
if (keyword == "namespace") u.CurNamespace = directive;
310+
u.Translations.Remove(directive);
311+
}
312+
313+
u.Translations.Remove(key1);
314+
u.Productions.Remove(key1);
315+
u.PrimaryProductions.Remove(key1);
316+
removeKey = true;
317+
}
318+
}
319+
320+
321+
string ruleName2 = GetRuleName(r[1].Data as Reduction);
322+
if (ruleName2 == "expression")
323+
{
324+
string key2 = DoExpression(u, r[1].Data as Reduction);
325+
if (removeKey) return new string[] { key2 };
326+
else return new string[] { key1, key2 };
327+
}
328+
else if (ruleName2 == "expression-list")
329+
{
330+
string[] keys = DoExpressionList(u, r[1].Data as Reduction);
331+
List<string> li = new List<string>();
332+
if (removeKey == false) li.Add(key1);
333+
for (int i = 0; i < keys.Length; i++) li.Add(keys[i]);
334+
return li.ToArray();
335+
}
336+
337+
return null;
338+
}
339+
340+
//<scripture>
341+
//::= <expression>
342+
//| <expression-list>
343+
344+
/// <summary>
345+
/// Translate Gold engine parse tree (root Reduction r) to Unfold structure.
346+
/// </summary>
347+
/// <param name="u">Unfold to be populated</param>
348+
/// <param name="r">Root reduction aka the parse tree</param>
349+
/// <returns>True if successful</returns>
350+
public bool DoScripture(DescribeUnfold u, Reduction r)
351+
{
352+
//reset namespace for the file
353+
u.CurNamespace = "";
354+
355+
//if we have no productions whatsoever
356+
//then this must be the primary file
357+
bool isPrimary = u.Productions.Count == 0;
358+
359+
//Unfold the scripture
360+
string ruleName = GetRuleName(r[0].Data as Reduction);
361+
if (ruleName == "expression")
362+
{
363+
string key2 = DoExpression(u, r[0].Data as Reduction);
364+
if (isPrimary) u.PrimaryProductions.Add(key2);
365+
return true;
366+
}
367+
else if (ruleName == "expression-list")
368+
{
369+
string[] keys = DoExpressionList(u, r[0].Data as Reduction, true);
370+
if (isPrimary)
371+
{
372+
for (int i = 0; i < keys.Length; i++)
373+
{
374+
u.PrimaryProductions.Add(keys[i]);
375+
}
376+
}
377+
return true;
378+
}
379+
return false;
380+
}
381+
}
382+
}

0 commit comments

Comments
 (0)