/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * License); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
// Generated from PathParser.g4 by ANTLR 4.9.3

#pragma once

#include "antlr4-runtime.h"

class PathParser : public antlr4::Parser {
   public:
    enum {
        ROOT = 1,
        WS = 2,
        TIME = 3,
        TIMESTAMP = 4,
        MINUS = 5,
        PLUS = 6,
        DIV = 7,
        MOD = 8,
        OPERATOR_DEQ = 9,
        OPERATOR_SEQ = 10,
        OPERATOR_GT = 11,
        OPERATOR_GTE = 12,
        OPERATOR_LT = 13,
        OPERATOR_LTE = 14,
        OPERATOR_NEQ = 15,
        OPERATOR_BITWISE_AND = 16,
        OPERATOR_LOGICAL_AND = 17,
        OPERATOR_BITWISE_OR = 18,
        OPERATOR_LOGICAL_OR = 19,
        OPERATOR_NOT = 20,
        DOT = 21,
        COMMA = 22,
        SEMI = 23,
        STAR = 24,
        DOUBLE_STAR = 25,
        LR_BRACKET = 26,
        RR_BRACKET = 27,
        LS_BRACKET = 28,
        RS_BRACKET = 29,
        DOUBLE_COLON = 30,
        STRING_LITERAL = 31,
        DURATION_LITERAL = 32,
        DATETIME_LITERAL = 33,
        INTEGER_LITERAL = 34,
        EXPONENT_NUM_PART = 35,
        ID = 36,
        QUOTED_ID = 37
    };

    enum {
        RulePath = 0,
        RulePrefixPath = 1,
        RuleSuffixPath = 2,
        RuleNodeName = 3,
        RuleNodeNameWithoutWildcard = 4,
        RuleNodeNameSlice = 5,
        RuleIdentifier = 6,
        RuleWildcard = 7
    };

    explicit PathParser(antlr4::TokenStream* input);
    ~PathParser();

    virtual std::string getGrammarFileName() const override;
    virtual const antlr4::atn::ATN& getATN() const override { return _atn; };
    virtual const std::vector<std::string>& getTokenNames() const override {
        return _tokenNames;
    };  // deprecated: use vocabulary instead.
    virtual const std::vector<std::string>& getRuleNames() const override;
    virtual antlr4::dfa::Vocabulary& getVocabulary() const override;

    class PathContext;
    class PrefixPathContext;
    class SuffixPathContext;
    class NodeNameContext;
    class NodeNameWithoutWildcardContext;
    class NodeNameSliceContext;
    class IdentifierContext;
    class WildcardContext;

    class PathContext : public antlr4::ParserRuleContext {
       public:
        PathContext(antlr4::ParserRuleContext* parent, size_t invokingState);
        virtual size_t getRuleIndex() const override;
        PrefixPathContext* prefixPath();
        antlr4::tree::TerminalNode* EOF();
        SuffixPathContext* suffixPath();

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    PathContext* path();

    class PrefixPathContext : public antlr4::ParserRuleContext {
       public:
        PrefixPathContext(antlr4::ParserRuleContext* parent,
                          size_t invokingState);
        virtual size_t getRuleIndex() const override;
        antlr4::tree::TerminalNode* ROOT();
        std::vector<antlr4::tree::TerminalNode*> DOT();
        antlr4::tree::TerminalNode* DOT(size_t i);
        std::vector<NodeNameContext*> nodeName();
        NodeNameContext* nodeName(size_t i);

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    PrefixPathContext* prefixPath();

    class SuffixPathContext : public antlr4::ParserRuleContext {
       public:
        SuffixPathContext(antlr4::ParserRuleContext* parent,
                          size_t invokingState);
        virtual size_t getRuleIndex() const override;
        std::vector<NodeNameContext*> nodeName();
        NodeNameContext* nodeName(size_t i);
        std::vector<antlr4::tree::TerminalNode*> DOT();
        antlr4::tree::TerminalNode* DOT(size_t i);

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    SuffixPathContext* suffixPath();

    class NodeNameContext : public antlr4::ParserRuleContext {
       public:
        NodeNameContext(antlr4::ParserRuleContext* parent,
                        size_t invokingState);
        virtual size_t getRuleIndex() const override;
        std::vector<WildcardContext*> wildcard();
        WildcardContext* wildcard(size_t i);
        NodeNameSliceContext* nodeNameSlice();
        NodeNameWithoutWildcardContext* nodeNameWithoutWildcard();

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    NodeNameContext* nodeName();

    class NodeNameWithoutWildcardContext : public antlr4::ParserRuleContext {
       public:
        NodeNameWithoutWildcardContext(antlr4::ParserRuleContext* parent,
                                       size_t invokingState);
        virtual size_t getRuleIndex() const override;
        IdentifierContext* identifier();

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    NodeNameWithoutWildcardContext* nodeNameWithoutWildcard();

    class NodeNameSliceContext : public antlr4::ParserRuleContext {
       public:
        NodeNameSliceContext(antlr4::ParserRuleContext* parent,
                             size_t invokingState);
        virtual size_t getRuleIndex() const override;
        IdentifierContext* identifier();
        antlr4::tree::TerminalNode* INTEGER_LITERAL();

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    NodeNameSliceContext* nodeNameSlice();

    class IdentifierContext : public antlr4::ParserRuleContext {
       public:
        IdentifierContext(antlr4::ParserRuleContext* parent,
                          size_t invokingState);
        virtual size_t getRuleIndex() const override;
        antlr4::tree::TerminalNode* DURATION_LITERAL();
        antlr4::tree::TerminalNode* ID();
        antlr4::tree::TerminalNode* QUOTED_ID();

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    IdentifierContext* identifier();

    class WildcardContext : public antlr4::ParserRuleContext {
       public:
        WildcardContext(antlr4::ParserRuleContext* parent,
                        size_t invokingState);
        virtual size_t getRuleIndex() const override;
        antlr4::tree::TerminalNode* STAR();
        antlr4::tree::TerminalNode* DOUBLE_STAR();

        virtual void enterRule(
            antlr4::tree::ParseTreeListener* listener) override;
        virtual void exitRule(
            antlr4::tree::ParseTreeListener* listener) override;

        virtual antlrcpp::Any accept(
            antlr4::tree::ParseTreeVisitor* visitor) override;
    };

    WildcardContext* wildcard();

   private:
    static std::vector<antlr4::dfa::DFA> _decisionToDFA;
    static antlr4::atn::PredictionContextCache _sharedContextCache;
    static std::vector<std::string> _ruleNames;
    static std::vector<std::string> _tokenNames;

    static std::vector<std::string> _literalNames;
    static std::vector<std::string> _symbolicNames;
    static antlr4::dfa::Vocabulary _vocabulary;
    static antlr4::atn::ATN _atn;
    static std::vector<uint16_t> _serializedATN;

    struct Initializer {
        Initializer();
    };
    static Initializer _init;
};
