public Grammar(GrammarReturn root, IEnumerable <GrammarNonTerminal> nonTerminals) { Root = root; NonTerminals = nonTerminals; }
private GrammarReturn ParseImpl() { GrammarReturn final = null; var reader = new LexerStringReader(_grammar, 0); while (reader.IsInRange()) { if (reader.IsEndOfLine()) { reader.MoveNext(); continue; } if (reader.StartsWith(Comment.AsSpan())) { reader.MoveToNextLine(); continue; } reader.ReadTillEndOfWhitespace(); if (reader.StartsWith(GrammarNonTerminalStart.ToString().AsSpan())) { // _______________________________________ // <value> : Literal|<function-invokation> var nonTerminalName = new string(reader.ReadTillEndOfWord()); // <value> if (nonTerminalName.EndsWith(GrammarNonTerminalEnd) == false) { throw new GrammarParserException($"Non-terminal {nonTerminalName} name " + $"should finish with {GrammarNonTerminalEnd}"); } var nonTerminal = GetNonTerminalByName(nonTerminalName); if (nonTerminal.FullyParsed) { throw new GrammarParserException($"Cannot declare {nonTerminalName} more than once."); } // skip ':' var assign = new string(reader.ReadWhile(x => x != Assign)) + reader.CurrentChar; if (assign.EndsWith(Assign) == false) { throw new GrammarParserException($"Invalid syntax for {nonTerminalName}."); } reader.MoveNext(); reader.ReadTillEndOfWhitespace(); nonTerminal.Body = ParseNonTerminalBody(ref reader, nonTerminal); continue; } if (reader.StartsWith(Return.AsSpan())) { final = ParseReturn(ref reader); break; } throw new GrammarParserException($"Invalid grammar syntax. Line: {new string(reader.ReadTillNewLine())}"); } if (final == null) { throw new GrammarParserException("Return statement not found."); } var notExistingNonTerminal = _nonTerminals.Select(x => x.Value).FirstOrDefault(x => x.FullyParsed == false); if (notExistingNonTerminal != null) { throw new GrammarParserException($"Non-terminal '{notExistingNonTerminal.Name}' " + "is not declared. Are you sure your gramma is fine?"); } foreach (var nonTerminal in _nonTerminals.Select(x => x.Value)) { if (nonTerminal.Body.OrConditionOperands.All(x => x.IsRecursive)) { var msg = $"Infinite recursion detected in {nonTerminal.Name} non-terminal. " + "Use '|' to create escape path."; throw new GrammarParserException(msg); } } return(final); }