private static Parser CreateParser()

in src/Kusto.Language/Parser/Grammars/GrammarParser.cs [102:282]


        private static Parser<char, Grammar> CreateParser()
        {
            // build the parser that parsers the simple grammar grammar
            Parser<char, Grammar> elementCore = null;
            var element = Forward(() => elementCore);

            var WhitespaceCount =
                Count(ZeroOrMore(Whitespace));

            Parser<char, string> TokenText(string text) =>
                Convert(Chars(text), text);

            var IdentifierScan =
                And(Or(Letter, Char('_')), ZeroOrMore(Or(Letter, Digit, Char('_'), Char('-'))));

            var IdentifierText =
                Text(IdentifierScan);

            var IdentifierTextAndOffset =
                TextAndOffset(IdentifierScan);

            var StringLiteralScan =
                And(Char('\''), ZeroOrMore(Not(Char('\''))), Char('\''));

            var StringLiteralText =
                Text(StringLiteralScan);

            var StringLiteralTextAndOffset =
                TextAndOffset(StringLiteralScan);

            Parser<char, string> Token(string text) =>
                Rule(WhitespaceCount, TokenText(text), (ws, tx) => tx);

            var Identifier =
                Rule(WhitespaceCount, IdentifierText, (ws, tx) => tx);

            var IdentifierAndOffset =
                Rule(WhitespaceCount, IdentifierTextAndOffset, (ws, tx) => tx);

            var StringLiteral =
                Rule(WhitespaceCount, StringLiteralText, (ws, tx) => tx);

            var StringLiteralAndOffset =
                Rule(WhitespaceCount, StringLiteralTextAndOffset, (ws, tx) => tx);

            var term =
                First(
                    Rule(Identifier, text => (Grammar)new TokenGrammar(text)),
                    Rule(StringLiteral, text => (Grammar)new TokenGrammar(KustoFacts.GetStringLiteralValue(text))))
                    .WithTag("<term>");

            var rule =
                Rule(
                    Token("<"), Text(OneOrMore(Not(Token(">")))), Token(">"),
                    (open, name, close) => (Grammar)new RuleGrammar(name))
                .WithTag("<rule>");

            var sequence = Produce(
                OneOrMore(element),
                (IReadOnlyList<Grammar> list) =>
                    list.Count == 1 ? list[0] : new SequenceGrammar(list.ToList()))
                .WithTag("<sequence>");

            var alternation =
                List(
                    elementParser: sequence,
                    separatorParser: Token("|"),
                    missingElement: null,
                    missingSeparator: null,
                    endOfList: null,
                    oneOrMore: true,
                    allowTrailingSeparator: false,
                    producer: list =>
                    {
                        if (list.Count == 1)
                        {
                            return list[0].Element;
                        }
                        else
                        {
                            return new AlternationGrammar(list.Select(eas => eas.Element).OfType<Grammar>().ToArray());
                        }
                    }).WithTag("<alternation>");

            var separator = Rule(
                Token(","), 
                term, 
                Optional(Token("~")),
                (comma, word, plus) => new SeparatorInfo(word, plus != null));

            var repeatition = Rule(
                    Token("{"),
                    alternation,
                    Optional(separator),
                    Token("}"),
                    Optional(First(Token("+"), Token("*"))),
                (open, elem, sep, close, kind) =>
                {
                    var zeroOrMore = kind == null || kind == "*";

                    if (zeroOrMore)
                    {
                        return (Grammar)new ZeroOrMoreGrammar(elem, sep?.Separator, sep?.AllowTrailing ?? false);
                    }
                    else
                    {
                        return (Grammar)new OneOrMoreGrammar(elem, sep?.Separator, sep?.AllowTrailing ?? false);
                    }
                }).WithTag("<repetition>");

            var grouped = Rule(
                Token("("), alternation, Token(")"),
                (open, grammar, close) => grammar)
                .WithTag("<grouping>");

            var optional = Rule(
                Token("["), alternation, Token("]"),
                (open, optioned, close) => (Grammar)new OptionalGrammar(optioned))
                .WithTag("<optional>");

            var primaryElement =
                First(
                    term,           // id or 'id'
                    rule,           // <rule>
                    grouped)        // ( ... )
                    .WithTag("<element>");

            // allow for some postfix abbreviations here
            var postfixPrimary =
                First(
                    optional,       // [a]
                    repeatition,    // {a}

                    ApplyOptional(
                        primaryElement,
                        _left =>
                            First(
                                Rule(_left, Token("!"),
                                    (left, bang) => (Grammar)new RequiredGrammar(left))
                                    .WithTag("<required>"),

                                // alternative to [] 
                                Rule(_left, Token("?"),
                                    (left, question) => (Grammar)new OptionalGrammar(left))
                                    .WithTag("<optional>"),

                                // alternative to { }*
                                Rule(_left, Token("*"),
                                    (left, star) => (Grammar)new ZeroOrMoreGrammar(left))
                                    .WithTag("<zero-or-more>"),

                                // alternative to { }+
                                Rule(_left, Token("+"),
                                    (left, plus) => (Grammar)new OneOrMoreGrammar(left))
                                    .WithTag("<one-or-more>")
                                    )));

            var hiddenPrimary =
                First(
                    Rule(Token("#"), postfixPrimary, 
                        (hat, hidden) => (Grammar)new HiddenGrammar(hidden)).WithTag("<hidden>"),
                    postfixPrimary);

            // allow for tag=elem
            var taggedPrimary =
                First(
                    If(And(Identifier, Token("=")),
                        Rule(Identifier, Token("="), hiddenPrimary,
                            (id, eq, elem) => (Grammar)new TaggedGrammar(id, elem))),

                    If(And(StringLiteral, Token("=")),
                        Rule(StringLiteral, Token("="), hiddenPrimary,
                            (str, eq, elem) => (Grammar)new TaggedGrammar(KustoFacts.GetStringLiteralValue(str), elem))),

                    hiddenPrimary
                    );

            elementCore = taggedPrimary;

            return alternation;
        }