public void Load(GrammarDocumentGroup documentGroup)
 {
     if (documentGroup.Items == null)
     {
         throw new ArgumentException("Grammar documents not loaded", "documentGroup");
     }
     CheckGrammar(documentGroup);
     BuildSymbols(documentGroup);
 }
        static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Please provide the grammar folder argument");
                return((int)ReturnValue.InvalidArgument);
            }

            string grammarFolder = args[0];

            GrammarDocumentGroup.SchemaPath = "Schema.xsd";

            var  documentGroup = new GrammarDocumentGroup();
            bool success       = documentGroup.LoadWithValidation(grammarFolder, (sender, e) =>
            {
                string severity;
                switch (e.Severity)
                {
                case XmlSeverityType.Error:
                    severity = "Error";
                    break;

                case XmlSeverityType.Warning:
                    severity = "Warning";
                    break;

                default:
                    severity = "UnknownSeverityType";
                    break;
                }
                Console.WriteLine(severity + ": " + e.Message + $" ({e.Exception.Source})");
            });

            if (!success)
            {
                Console.WriteLine("Schema validation doesn't pass");
                return((int)ReturnValue.InvalidGrammar);
            }

            var grammar = new Grammar();

            try
            {
                grammar.Load(documentGroup);
            }
            catch (AggregateException pack)
            {
                foreach (Exception e in pack.InnerExceptions)
                {
                    Console.WriteLine("Error: " + e.Message);
                }
                return((int)ReturnValue.InvalidGrammar);
            }

            Console.WriteLine(grammar.ToText());
            return(0);
        }
        private void BuildSymbols(GrammarDocumentGroup documentGroup)
        {
            _symbols = new Dictionary <SymbolId, Symbol>();

            SymbolId startId = _idGenerator.Next();

            _start = new NonTerminalSymbol(startId, ReservedCharacter + "Start");
            _symbols.Add(startId, _start);

            foreach (GrammarDocument document in documentGroup.Items)
            {
                foreach (XmlElement element in document.Content.DocumentElement.ChildNodes)
                {
                    BuildSymbol(element);
                }
            }
        }
        private void CheckGrammar(GrammarDocumentGroup documentGroup)
        {
            var exceptions = new List <Exception>();

            foreach (GrammarDocument document in documentGroup.Items)
            {
                foreach (XmlElement element in document.Content.GetElementsByTagName("Production"))
                {
                    if (element.HasAttribute("output_order"))
                    {
                        string[] tokens = element.Attributes["output_order"].Value.Split(' ');
                        if (tokens.Length != element.ChildNodes.Count)
                        {
                            throw new IllegalOutputOrderException(document.Path);
                        }

                        var found = new bool[tokens.Length];
                        for (int i = 0; i < tokens.Length; i++)
                        {
                            if (int.TryParse(tokens[i], out int number) && number < tokens.Length && !found[number])
                            {
                                found[number] = true;
                            }
                            else
                            {
                                throw new IllegalOutputOrderException(document.Path);
                            }
                        }
                    }
                }
            }

            bool hasTopSymbol = false;
            var  symbolRefs   = new Dictionary <string, SymbolId>();
            var  idGenerator  = new SymbolId.Generator();

            void checkSymbolsByTagName(string tagName)
            {
                foreach (GrammarDocument document in documentGroup.Items)
                {
                    foreach (XmlElement element in document.Content.GetElementsByTagName(tagName))
                    {
                        if (element.HasAttribute("name"))
                        {
                            string name = element.Attributes["name"].Value;
                            if (symbolRefs.ContainsKey(name))
                            {
                                exceptions.Add(new SymbolRedefinitionException(document.Path, name));
                            }
                            else
                            {
                                symbolRefs.Add(name, idGenerator.Next());
                            }
                        }
                        if (element.HasAttribute("top") && XmlConvert.ToBoolean(element.Attributes["top"].Value))
                        {
                            hasTopSymbol = true;
                        }
                    }
                }
            }

            checkSymbolsByTagName("Terminal");
            checkSymbolsByTagName("Symbol");

            foreach (GrammarDocument document in documentGroup.Items)
            {
                foreach (XmlElement element in document.Content.GetElementsByTagName("SymbolRef"))
                {
                    Debug.Assert(element.HasAttribute("name"));

                    string name = element.Attributes["name"].Value;
                    if (!symbolRefs.ContainsKey(name))
                    {
                        exceptions.Add(new SymbolRefNotFoundException(document.Path, name));
                    }
                }
            }

            if (!hasTopSymbol)
            {
                exceptions.Add(new Exception("Grammar has no top level symbol"));
            }

            if (exceptions.Count > 0)
            {
                throw new AggregateException(exceptions);
            }

            _symbolRefs  = symbolRefs;
            _idGenerator = idGenerator;
        }