/* * internal void DetermineLookAheadTree(LookAheadNode node) * { * //recursion here * foreach (Rule rule in Rules) * { * rule.DetermineLookAheadTree(node); * } * } */ internal bool DetermineFirstTerminals() { // check if nonterminal has already been visited x times // only determine firsts x times to allow for recursion of depth x, otherwise may wind up in endless loop if (visitCount > 10) { return(containsEmpty); } visitCount++; // reset terminals FirstTerminals = new Symbols(); //recursion here foreach (Rule rule in Rules) { containsEmpty |= rule.DetermineFirstTerminals(FirstTerminals); } return(containsEmpty); }
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); }
/* * internal void DetermineLookAheadTree(LookAheadNode node) * { * switch (Type) * { * case RuleType.Terminal: * LookAheadNode f = node.Nodes.Find(Symbol.Name); * if (f == null) * { * LookAheadNode n = new LookAheadNode(); * n.LookAheadTerminal = (TerminalSymbol) Symbol; * node.Nodes.Add(n); * } * else * Console.WriteLine("throw new Exception(\"Terminal already exists\");"); * break; * case RuleType.NonTerminal: * NonTerminalSymbol nts = Symbol as NonTerminalSymbol; * * break; * //case RuleType.Production: * case RuleType.Concat: * break; * case RuleType.OneOrMore: * break; * case RuleType.Option: * case RuleType.Choice: * case RuleType.ZeroOrMore: * break; * default: * throw new NotImplementedException(); * } * } */ internal bool DetermineFirstTerminals(Symbols FirstTerminals) { return(DetermineFirstTerminals(FirstTerminals, 0)); }
public Grammar() { Symbols = new Symbols(); SkipSymbols = new Symbols(); Directives = new Directives(); }