1 using Mercury.Exceptions;
2 using Mercury.Nucleus.Collections;
3 using System.Collections.Generic;
6 namespace Mercury.Syntax
17 protected HashSet<Symbol> nonterminals =
new HashSet<Symbol>();
18 protected HashSet<Symbol> terminals =
new HashSet<Symbol>();
19 protected HashSet<Rule> rules =
new HashSet<Rule>();
44 nonterminals.Add(root);
53 public Symbol Root {
get;
private set; }
72 switch (newSymbol.
Type)
74 case SymbolType.Terminal:
75 terminals.Add(newSymbol);
78 case SymbolType.Nonterminal:
79 nonterminals.Add(newSymbol);
97 if (rule.
RHS.Any(x => (x.Name ==
Epsilon.Name) && (!x.IsEpsilon)))
101 foreach (var s
in rule.RHS.Where(x => !x.IsEpsilon))
112 {
foreach (var rule
in rules) AddRule(rule);
return this; }
118 {
foreach (var rule
in other.rules) AddRule(rule);
return this; }
125 Nonterminals = nonterminals.ToList(),
126 Terminals = terminals.ToList(),
127 Rules = rules.ToList(),
142 private List<Rule> epsilonRules;
143 private List<Rule> terminalRules;
145 private ListMultiDictionary<Symbol, Rule> rulemap;
149 public ExtendedGrammarBuilder(
Symbol root,
Symbol epsilon)
150 : base(root, epsilon)
152 epsilonRules =
new List<Rule>();
153 terminalRules =
new List<Rule>();
155 rulemap =
new ListMultiDictionary<Symbol, Rule>();
158 public ExtendedGrammarBuilder(Grammar source)
159 : this(source.Root, source.Epsilon)
161 for(
int ix = 0; ix < source.Rules.Count; ++ix)
163 Rule r = source.Rules[ix];
164 if (r.IsEpsilon) epsilonRules.Add(r);
167 if (r.RHS[0].Type ==
SymbolType.Terminal) terminalRules.Add(r);
168 rulemap.Add(r.RHS[0], r);
175 public ExtendedGrammarBuilder(ExtendedGrammar source)
176 : this(source.Root, source.
Epsilon)
178 epsilonRules.AddRange(source.EpsilonRules);
179 terminalRules.AddRange(source.TerminalRules);
180 rulemap =
new ListMultiDictionary<Symbol, Rule>(source.rulemap);
185 public static ExtendedGrammar ExtendGrammar(Grammar grammar)
186 {
return new ExtendedGrammarBuilder(grammar).GetExtendedGrammar(); }
188 public ExtendedGrammar GetExtendedGrammar()
190 return new ExtendedGrammar()
192 Nonterminals = nonterminals.ToList(),
193 Terminals = terminals.ToList(),
194 Rules = rules.ToList(),
196 Epsilon = this.Epsilon,
198 EpsilonRules = epsilonRules.ToList(),
199 TerminalRules = terminalRules.ToList(),
200 rulemap = this.rulemap
206 #region [ GrammarBuilder ]
208 public new ExtendedGrammarBuilder AddRule(Rule rule)
210 int cntx = rules.Count;
213 if (cntx != rules.Count)
215 if (rule.IsEpsilon) epsilonRules.Add(rule);
216 else rulemap.Add(rule.RHS[0], rule);
219 terminalRules.Add(rule);
IReadOnlyList< Symbol > RHS
The Right-Hand Side (RHS) of the rule.
virtual GrammarBuilder AddRule(Rule rule)
Adds a new rule to the grammar. If the rule contains symbols that are not in the grammar, they will be added. Rules that are already in the grammar will be ignored.
Global class containing cool static / convenience stuff.
Class that creates grammars.
SymbolType
Represents a type of symbol. Implemented as Flags since Symbol type inference is ambiguous.
GrammarBuilder(Symbol root, Symbol epsilon)
Creates a GrammarBuilder with custom Root and Epsilon symbols.
GrammarBuilder AddSymbol(Symbol newSymbol)
Adds a new symbol to the grammar. The destination set is determined by the symbol type...
Grammar GetGrammar()
A grammar from the builder.
Symbol LHS
The Left-Hand Side (LHS) of the rule.
GrammarBuilder AddRules(IEnumerable< Rule > rules)
Adds the collection of rules to the builder.
Represents a Context-Free Grammar rule. This is an immutable class.
GrammarBuilder()
Default constructor. Uses Root and Epsilon symbols that are specified in the configuration.
GrammarBuilder Include(GrammarBuilder other)
Includes the other builder.
Represents a single symbol of the grammar. This is an immutable class. For a symbol name to be val...
Represents a Context-Free Grammar. This is an immutable class, to create a grammar use Mercury...
An exception thrown when something wrong happens in the Mercury.Syntax
SymbolType Type
Symbol type