예제 #1
0
 public Grammar(GrammarReturn root, IEnumerable <GrammarNonTerminal> nonTerminals)
 {
     Root         = root;
     NonTerminals = nonTerminals;
 }
예제 #2
0
        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);
        }