public Symbols GetTerminals() { Symbols symbols = new Symbols(); foreach (Symbol s in Symbols) { if (s is TerminalSymbol) { symbols.Add(s); } } return(symbols); }
public void DetermineProductionSymbols(Symbols symbols) { if (Type == RuleType.Terminal || Type == RuleType.NonTerminal) { symbols.Add(Symbol); } else { foreach (Rule rule in Rules) { rule.DetermineProductionSymbols(symbols); } } }
internal bool DetermineFirstTerminals(Symbols FirstTerminals, int index) { // indicates if Nonterminal can evaluate to an empty terminal (e.g. in case T -> a? or T -> a*) // in which case the parent rule should continue scanning after this nonterminal for Firsts. bool containsEmpty = false; // assume terminal is found switch (Type) { case RuleType.Terminal: if (Symbol == null) { return(true); } if (!FirstTerminals.Exists(Symbol)) { FirstTerminals.Add(Symbol); } else { Console.WriteLine("throw new Exception(\"Terminal already exists\");"); } break; case RuleType.NonTerminal: if (Symbol == null) { return(true); } NonTerminalSymbol nts = Symbol as NonTerminalSymbol; containsEmpty = nts.DetermineFirstTerminals(); // add first symbols of the nonterminal if not already added foreach (TerminalSymbol t in nts.FirstTerminals) { if (!FirstTerminals.Exists(t)) { FirstTerminals.Add(t); } else { Console.WriteLine("throw new Exception(\"Terminal already exists\");"); } } break; case RuleType.Choice: { // all subrules must be evaluated to determine if they contain first terminals // if any subrule contains an empty, then this rule also contains an empty foreach (Rule r in Rules) { containsEmpty |= r.DetermineFirstTerminals(FirstTerminals); } break; } case RuleType.OneOrMore: { // if a non-empty subrule was found, then stop further parsing. foreach (Rule r in Rules) { containsEmpty = r.DetermineFirstTerminals(FirstTerminals); if (!containsEmpty) // found the final set of first terminals { break; } } break; } case RuleType.Concat: { // if a non-empty subrule was found, then stop further parsing. // start scanning from Index for (int i = index; i < Rules.Count; i++) { containsEmpty = Rules[i].DetermineFirstTerminals(FirstTerminals); if (!containsEmpty) // found the final set of first terminals { break; } } // assign this concat rule to each terminal foreach (TerminalSymbol t in FirstTerminals) { t.Rule = this; } break; } case RuleType.Option: case RuleType.ZeroOrMore: { // empty due to the nature of this rule (A? or A* can always be empty) containsEmpty = true; // if a non-empty subrule was found, then stop further parsing. foreach (Rule r in Rules) { containsEmpty |= r.DetermineFirstTerminals(FirstTerminals); if (!containsEmpty) // found the final set of first terminals { break; } } break; } default: throw new NotImplementedException(); } return(containsEmpty); }