1 module rules;
2 
3 import std.uni;
4 import std.format : format;
5 import std.array : back, front;
6 import std.string : indexOf;
7 import std.typecons : Flag;
8 
9 alias StoreRulePart = Flag!"StoreRulePart";
10 
11 class RulePart {
12 	StoreRulePart storeThis;
13 	string name;
14 	string storeName;
15 
16 	this(string name) {
17 		this.name = name;
18 
19 		auto hashIdx = this.name.indexOf('#');
20 		if(hashIdx != -1) {
21 			this.storeThis = StoreRulePart.yes;
22 			this.storeName = this.name[hashIdx + 1 .. $];
23 			this.name = this.name[0 .. hashIdx];
24 		}
25 	}
26 
27 	bool terminal() pure const @safe {
28 		return this.name.front.isLower();
29 	}
30 
31 	bool nonterminal() pure const @safe {
32 		return this.name.front.isUpper();
33 	}
34 
35 	override string toString() pure const @safe {
36 		if(this.storeThis == StoreRulePart.yes) {
37 			return format("%s#%s", this.name, this.storeName);
38 		} else {
39 			return this.name;
40 		}
41 	}
42 }
43 
44 class SubRule {
45 	RulePart[] elements;
46 
47 	string name;
48 
49 	this(string name) {
50 		this.name = name;
51 	}
52 
53 	override string toString() pure const @safe {
54 		string rslt = this.name ~ " : ";
55 		foreach(it; this.elements) {
56 			rslt ~= it.toString() ~ " ";
57 		}
58 
59 		return rslt;
60 	}
61 }
62 
63 class Rule {
64 	SubRule[] subRules;
65 	string name;
66 	bool isExtern;
67 
68 	this(string name) {
69 		this.name = name;
70 	}
71 
72 	this(string name, bool e) {
73 		this.name = name;
74 		this.isExtern = e;
75 	}
76 
77 	override string toString() pure const @safe {
78 		string rslt = this.name ~ " : \n";
79 		foreach(it; this.subRules) {
80 			rslt ~= "\t" ~ it.toString() ~ "\n";
81 		}
82 
83 		return rslt;
84 	}
85 }
86