示例#1
0
        public Symbols GetTerminals()
        {
            Symbols symbols = new Symbols();

            foreach (Symbol s in Symbols)
            {
                if (s is TerminalSymbol)
                {
                    symbols.Add(s);
                }
            }
            return(symbols);
        }
示例#2
0
文件: Rule.cs 项目: hobdrive/TinyPG
 public void DetermineProductionSymbols(Symbols symbols)
 {
     if (Type == RuleType.Terminal || Type == RuleType.NonTerminal)
     {
         symbols.Add(Symbol);
     }
     else
     {
         foreach (Rule rule in Rules)
         {
             rule.DetermineProductionSymbols(symbols);
         }
     }
 }
示例#3
0
文件: Rule.cs 项目: hobdrive/TinyPG
        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);
        }