/*
 * 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

#include "PathParser.h"

#include "PathParserListener.h"
#include "PathParserVisitor.h"

using namespace antlrcpp;
using namespace antlr4;

PathParser::PathParser(TokenStream* input) : Parser(input) {
    _interpreter = new atn::ParserATNSimulator(this, _atn, _decisionToDFA,
                                               _sharedContextCache);
}

PathParser::~PathParser() { delete _interpreter; }

std::string PathParser::getGrammarFileName() const { return "PathParser.g4"; }

const std::vector<std::string>& PathParser::getRuleNames() const {
    return _ruleNames;
}

dfa::Vocabulary& PathParser::getVocabulary() const { return _vocabulary; }

//----------------- PathContext
//------------------------------------------------------------------

PathParser::PathContext::PathContext(ParserRuleContext* parent,
                                     size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

PathParser::PrefixPathContext* PathParser::PathContext::prefixPath() {
    return getRuleContext<PathParser::PrefixPathContext>(0);
}

tree::TerminalNode* PathParser::PathContext::EOF() {
    return getToken(PathParser::EOF, 0);
}

PathParser::SuffixPathContext* PathParser::PathContext::suffixPath() {
    return getRuleContext<PathParser::SuffixPathContext>(0);
}

size_t PathParser::PathContext::getRuleIndex() const {
    return PathParser::RulePath;
}

void PathParser::PathContext::enterRule(tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->enterPath(this);
}

void PathParser::PathContext::exitRule(tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->exitPath(this);
}

antlrcpp::Any PathParser::PathContext::accept(tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitPath(this);
    else
        return visitor->visitChildren(this);
}

PathParser::PathContext* PathParser::path() {
    PathContext* _localctx =
        _tracker.createInstance<PathContext>(_ctx, getState());
    enterRule(_localctx, 0, PathParser::RulePath);

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        setState(22);
        _errHandler->sync(this);
        switch (_input->LA(1)) {
            case PathParser::ROOT: {
                enterOuterAlt(_localctx, 1);
                setState(16);
                prefixPath();
                setState(17);
                match(PathParser::EOF);
                break;
            }

            case PathParser::STAR:
            case PathParser::DOUBLE_STAR:
            case PathParser::DURATION_LITERAL:
            case PathParser::INTEGER_LITERAL:
            case PathParser::ID:
            case PathParser::QUOTED_ID: {
                enterOuterAlt(_localctx, 2);
                setState(19);
                suffixPath();
                setState(20);
                match(PathParser::EOF);
                break;
            }

            default:
                throw NoViableAltException(this);
        }

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

//----------------- PrefixPathContext
//------------------------------------------------------------------

PathParser::PrefixPathContext::PrefixPathContext(ParserRuleContext* parent,
                                                 size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

tree::TerminalNode* PathParser::PrefixPathContext::ROOT() {
    return getToken(PathParser::ROOT, 0);
}

std::vector<tree::TerminalNode*> PathParser::PrefixPathContext::DOT() {
    return getTokens(PathParser::DOT);
}

tree::TerminalNode* PathParser::PrefixPathContext::DOT(size_t i) {
    return getToken(PathParser::DOT, i);
}

std::vector<PathParser::NodeNameContext*>
PathParser::PrefixPathContext::nodeName() {
    return getRuleContexts<PathParser::NodeNameContext>();
}

PathParser::NodeNameContext* PathParser::PrefixPathContext::nodeName(size_t i) {
    return getRuleContext<PathParser::NodeNameContext>(i);
}

size_t PathParser::PrefixPathContext::getRuleIndex() const {
    return PathParser::RulePrefixPath;
}

void PathParser::PrefixPathContext::enterRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->enterPrefixPath(this);
}

void PathParser::PrefixPathContext::exitRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->exitPrefixPath(this);
}

antlrcpp::Any PathParser::PrefixPathContext::accept(
    tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitPrefixPath(this);
    else
        return visitor->visitChildren(this);
}

PathParser::PrefixPathContext* PathParser::prefixPath() {
    PrefixPathContext* _localctx =
        _tracker.createInstance<PrefixPathContext>(_ctx, getState());
    enterRule(_localctx, 2, PathParser::RulePrefixPath);
    size_t _la = 0;

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        enterOuterAlt(_localctx, 1);
        setState(24);
        match(PathParser::ROOT);
        setState(29);
        _errHandler->sync(this);
        _la = _input->LA(1);
        while (_la == PathParser::DOT) {
            setState(25);
            match(PathParser::DOT);
            setState(26);
            nodeName();
            setState(31);
            _errHandler->sync(this);
            _la = _input->LA(1);
        }

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

//----------------- SuffixPathContext
//------------------------------------------------------------------

PathParser::SuffixPathContext::SuffixPathContext(ParserRuleContext* parent,
                                                 size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

std::vector<PathParser::NodeNameContext*>
PathParser::SuffixPathContext::nodeName() {
    return getRuleContexts<PathParser::NodeNameContext>();
}

PathParser::NodeNameContext* PathParser::SuffixPathContext::nodeName(size_t i) {
    return getRuleContext<PathParser::NodeNameContext>(i);
}

std::vector<tree::TerminalNode*> PathParser::SuffixPathContext::DOT() {
    return getTokens(PathParser::DOT);
}

tree::TerminalNode* PathParser::SuffixPathContext::DOT(size_t i) {
    return getToken(PathParser::DOT, i);
}

size_t PathParser::SuffixPathContext::getRuleIndex() const {
    return PathParser::RuleSuffixPath;
}

void PathParser::SuffixPathContext::enterRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->enterSuffixPath(this);
}

void PathParser::SuffixPathContext::exitRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->exitSuffixPath(this);
}

antlrcpp::Any PathParser::SuffixPathContext::accept(
    tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitSuffixPath(this);
    else
        return visitor->visitChildren(this);
}

PathParser::SuffixPathContext* PathParser::suffixPath() {
    SuffixPathContext* _localctx =
        _tracker.createInstance<SuffixPathContext>(_ctx, getState());
    enterRule(_localctx, 4, PathParser::RuleSuffixPath);
    size_t _la = 0;

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        enterOuterAlt(_localctx, 1);
        setState(32);
        nodeName();
        setState(37);
        _errHandler->sync(this);
        _la = _input->LA(1);
        while (_la == PathParser::DOT) {
            setState(33);
            match(PathParser::DOT);
            setState(34);
            nodeName();
            setState(39);
            _errHandler->sync(this);
            _la = _input->LA(1);
        }

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

//----------------- NodeNameContext
//------------------------------------------------------------------

PathParser::NodeNameContext::NodeNameContext(ParserRuleContext* parent,
                                             size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

std::vector<PathParser::WildcardContext*>
PathParser::NodeNameContext::wildcard() {
    return getRuleContexts<PathParser::WildcardContext>();
}

PathParser::WildcardContext* PathParser::NodeNameContext::wildcard(size_t i) {
    return getRuleContext<PathParser::WildcardContext>(i);
}

PathParser::NodeNameSliceContext* PathParser::NodeNameContext::nodeNameSlice() {
    return getRuleContext<PathParser::NodeNameSliceContext>(0);
}

PathParser::NodeNameWithoutWildcardContext*
PathParser::NodeNameContext::nodeNameWithoutWildcard() {
    return getRuleContext<PathParser::NodeNameWithoutWildcardContext>(0);
}

size_t PathParser::NodeNameContext::getRuleIndex() const {
    return PathParser::RuleNodeName;
}

void PathParser::NodeNameContext::enterRule(tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->enterNodeName(this);
}

void PathParser::NodeNameContext::exitRule(tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->exitNodeName(this);
}

antlrcpp::Any PathParser::NodeNameContext::accept(
    tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitNodeName(this);
    else
        return visitor->visitChildren(this);
}

PathParser::NodeNameContext* PathParser::nodeName() {
    NodeNameContext* _localctx =
        _tracker.createInstance<NodeNameContext>(_ctx, getState());
    enterRule(_localctx, 6, PathParser::RuleNodeName);
    size_t _la = 0;

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        setState(50);
        _errHandler->sync(this);
        switch (getInterpreter<atn::ParserATNSimulator>()->adaptivePredict(
            _input, 4, _ctx)) {
            case 1: {
                enterOuterAlt(_localctx, 1);
                setState(40);
                wildcard();
                break;
            }

            case 2: {
                enterOuterAlt(_localctx, 2);
                setState(41);
                wildcard();
                setState(42);
                nodeNameSlice();
                setState(44);
                _errHandler->sync(this);

                _la = _input->LA(1);
                if (_la == PathParser::STAR

                    || _la == PathParser::DOUBLE_STAR) {
                    setState(43);
                    wildcard();
                }
                break;
            }

            case 3: {
                enterOuterAlt(_localctx, 3);
                setState(46);
                nodeNameSlice();
                setState(47);
                wildcard();
                break;
            }

            case 4: {
                enterOuterAlt(_localctx, 4);
                setState(49);
                nodeNameWithoutWildcard();
                break;
            }

            default:
                break;
        }

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

//----------------- NodeNameWithoutWildcardContext
//------------------------------------------------------------------

PathParser::NodeNameWithoutWildcardContext::NodeNameWithoutWildcardContext(
    ParserRuleContext* parent, size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

PathParser::IdentifierContext*
PathParser::NodeNameWithoutWildcardContext::identifier() {
    return getRuleContext<PathParser::IdentifierContext>(0);
}

size_t PathParser::NodeNameWithoutWildcardContext::getRuleIndex() const {
    return PathParser::RuleNodeNameWithoutWildcard;
}

void PathParser::NodeNameWithoutWildcardContext::enterRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr)
        parserListener->enterNodeNameWithoutWildcard(this);
}

void PathParser::NodeNameWithoutWildcardContext::exitRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr)
        parserListener->exitNodeNameWithoutWildcard(this);
}

antlrcpp::Any PathParser::NodeNameWithoutWildcardContext::accept(
    tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitNodeNameWithoutWildcard(this);
    else
        return visitor->visitChildren(this);
}

PathParser::NodeNameWithoutWildcardContext*
PathParser::nodeNameWithoutWildcard() {
    NodeNameWithoutWildcardContext* _localctx =
        _tracker.createInstance<NodeNameWithoutWildcardContext>(_ctx,
                                                                getState());
    enterRule(_localctx, 8, PathParser::RuleNodeNameWithoutWildcard);

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        enterOuterAlt(_localctx, 1);
        setState(52);
        identifier();

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

//----------------- NodeNameSliceContext
//------------------------------------------------------------------

PathParser::NodeNameSliceContext::NodeNameSliceContext(
    ParserRuleContext* parent, size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

PathParser::IdentifierContext* PathParser::NodeNameSliceContext::identifier() {
    return getRuleContext<PathParser::IdentifierContext>(0);
}

tree::TerminalNode* PathParser::NodeNameSliceContext::INTEGER_LITERAL() {
    return getToken(PathParser::INTEGER_LITERAL, 0);
}

size_t PathParser::NodeNameSliceContext::getRuleIndex() const {
    return PathParser::RuleNodeNameSlice;
}

void PathParser::NodeNameSliceContext::enterRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->enterNodeNameSlice(this);
}

void PathParser::NodeNameSliceContext::exitRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->exitNodeNameSlice(this);
}

antlrcpp::Any PathParser::NodeNameSliceContext::accept(
    tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitNodeNameSlice(this);
    else
        return visitor->visitChildren(this);
}

PathParser::NodeNameSliceContext* PathParser::nodeNameSlice() {
    NodeNameSliceContext* _localctx =
        _tracker.createInstance<NodeNameSliceContext>(_ctx, getState());
    enterRule(_localctx, 10, PathParser::RuleNodeNameSlice);

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        setState(56);
        _errHandler->sync(this);
        switch (_input->LA(1)) {
            case PathParser::DURATION_LITERAL:
            case PathParser::ID:
            case PathParser::QUOTED_ID: {
                enterOuterAlt(_localctx, 1);
                setState(54);
                identifier();
                break;
            }

            case PathParser::INTEGER_LITERAL: {
                enterOuterAlt(_localctx, 2);
                setState(55);
                match(PathParser::INTEGER_LITERAL);
                break;
            }

            default:
                throw NoViableAltException(this);
        }

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

//----------------- IdentifierContext
//------------------------------------------------------------------

PathParser::IdentifierContext::IdentifierContext(ParserRuleContext* parent,
                                                 size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

tree::TerminalNode* PathParser::IdentifierContext::DURATION_LITERAL() {
    return getToken(PathParser::DURATION_LITERAL, 0);
}

tree::TerminalNode* PathParser::IdentifierContext::ID() {
    return getToken(PathParser::ID, 0);
}

tree::TerminalNode* PathParser::IdentifierContext::QUOTED_ID() {
    return getToken(PathParser::QUOTED_ID, 0);
}

size_t PathParser::IdentifierContext::getRuleIndex() const {
    return PathParser::RuleIdentifier;
}

void PathParser::IdentifierContext::enterRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->enterIdentifier(this);
}

void PathParser::IdentifierContext::exitRule(
    tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->exitIdentifier(this);
}

antlrcpp::Any PathParser::IdentifierContext::accept(
    tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitIdentifier(this);
    else
        return visitor->visitChildren(this);
}

PathParser::IdentifierContext* PathParser::identifier() {
    IdentifierContext* _localctx =
        _tracker.createInstance<IdentifierContext>(_ctx, getState());
    enterRule(_localctx, 12, PathParser::RuleIdentifier);
    size_t _la = 0;

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        enterOuterAlt(_localctx, 1);
        setState(58);
        _la = _input->LA(1);
        if (!((((_la & ~0x3fULL) == 0) &&
               ((1ULL << _la) & ((1ULL << PathParser::DURATION_LITERAL) |
                                 (1ULL << PathParser::ID) |
                                 (1ULL << PathParser::QUOTED_ID))) != 0))) {
            _errHandler->recoverInline(this);
        } else {
            _errHandler->reportMatch(this);
            consume();
        }

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

//----------------- WildcardContext
//------------------------------------------------------------------

PathParser::WildcardContext::WildcardContext(ParserRuleContext* parent,
                                             size_t invokingState)
    : ParserRuleContext(parent, invokingState) {}

tree::TerminalNode* PathParser::WildcardContext::STAR() {
    return getToken(PathParser::STAR, 0);
}

tree::TerminalNode* PathParser::WildcardContext::DOUBLE_STAR() {
    return getToken(PathParser::DOUBLE_STAR, 0);
}

size_t PathParser::WildcardContext::getRuleIndex() const {
    return PathParser::RuleWildcard;
}

void PathParser::WildcardContext::enterRule(tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->enterWildcard(this);
}

void PathParser::WildcardContext::exitRule(tree::ParseTreeListener* listener) {
    auto parserListener = dynamic_cast<PathParserListener*>(listener);
    if (parserListener != nullptr) parserListener->exitWildcard(this);
}

antlrcpp::Any PathParser::WildcardContext::accept(
    tree::ParseTreeVisitor* visitor) {
    if (auto parserVisitor = dynamic_cast<PathParserVisitor*>(visitor))
        return parserVisitor->visitWildcard(this);
    else
        return visitor->visitChildren(this);
}

PathParser::WildcardContext* PathParser::wildcard() {
    WildcardContext* _localctx =
        _tracker.createInstance<WildcardContext>(_ctx, getState());
    enterRule(_localctx, 14, PathParser::RuleWildcard);
    size_t _la = 0;

#if __cplusplus > 201703L
    auto onExit = finally([=, this] {
#else
    auto onExit = finally([=] {
#endif
        exitRule();
    });
    try {
        enterOuterAlt(_localctx, 1);
        setState(60);
        _la = _input->LA(1);
        if (!(_la == PathParser::STAR

              || _la == PathParser::DOUBLE_STAR)) {
            _errHandler->recoverInline(this);
        } else {
            _errHandler->reportMatch(this);
            consume();
        }

    } catch (RecognitionException& e) {
        _errHandler->reportError(this, e);
        _localctx->exception = std::current_exception();
        _errHandler->recover(this, _localctx->exception);
    }

    return _localctx;
}

// Static vars and initialization.
std::vector<dfa::DFA> PathParser::_decisionToDFA;
atn::PredictionContextCache PathParser::_sharedContextCache;

// We own the ATN which in turn owns the ATN states.
atn::ATN PathParser::_atn;
std::vector<uint16_t> PathParser::_serializedATN;

std::vector<std::string> PathParser::_ruleNames = {"path",
                                                   "prefixPath",
                                                   "suffixPath",
                                                   "nodeName",
                                                   "nodeNameWithoutWildcard",
                                                   "nodeNameSlice",
                                                   "identifier",
                                                   "wildcard"};

std::vector<std::string> PathParser::_literalNames = {
    "",    "",     "",    "",     "",     "'-'", "'+'",  "'/'",
    "'%'", "'=='", "'='", "'>'",  "'>='", "'<'", "'<='", "",
    "'&'", "'&&'", "'|'", "'||'", "'!'",  "'.'", "','",  "';'",
    "'*'", "'**'", "'('", "')'",  "'['",  "']'", "'::'"};

std::vector<std::string> PathParser::_symbolicNames = {"",
                                                       "ROOT",
                                                       "WS",
                                                       "TIME",
                                                       "TIMESTAMP",
                                                       "MINUS",
                                                       "PLUS",
                                                       "DIV",
                                                       "MOD",
                                                       "OPERATOR_DEQ",
                                                       "OPERATOR_SEQ",
                                                       "OPERATOR_GT",
                                                       "OPERATOR_GTE",
                                                       "OPERATOR_LT",
                                                       "OPERATOR_LTE",
                                                       "OPERATOR_NEQ",
                                                       "OPERATOR_BITWISE_AND",
                                                       "OPERATOR_LOGICAL_AND",
                                                       "OPERATOR_BITWISE_OR",
                                                       "OPERATOR_LOGICAL_OR",
                                                       "OPERATOR_NOT",
                                                       "DOT",
                                                       "COMMA",
                                                       "SEMI",
                                                       "STAR",
                                                       "DOUBLE_STAR",
                                                       "LR_BRACKET",
                                                       "RR_BRACKET",
                                                       "LS_BRACKET",
                                                       "RS_BRACKET",
                                                       "DOUBLE_COLON",
                                                       "STRING_LITERAL",
                                                       "DURATION_LITERAL",
                                                       "DATETIME_LITERAL",
                                                       "INTEGER_LITERAL",
                                                       "EXPONENT_NUM_PART",
                                                       "ID",
                                                       "QUOTED_ID"};

dfa::Vocabulary PathParser::_vocabulary(_literalNames, _symbolicNames);

std::vector<std::string> PathParser::_tokenNames;

PathParser::Initializer::Initializer() {
    for (size_t i = 0; i < _symbolicNames.size(); ++i) {
        std::string name = _vocabulary.getLiteralName(i);
        if (name.empty()) {
            name = _vocabulary.getSymbolicName(i);
        }

        if (name.empty()) {
            _tokenNames.push_back("<INVALID>");
        } else {
            _tokenNames.push_back(name);
        }
    }

    static const uint16_t serializedATNSegment0[] = {
        0x3,  0x608b, 0xa72a, 0x8133, 0xb9ed, 0x417c, 0x3be7, 0x7786, 0x5964,
        0x3,  0x27,   0x41,   0x4,    0x2,    0x9,    0x2,    0x4,    0x3,
        0x9,  0x3,    0x4,    0x4,    0x9,    0x4,    0x4,    0x5,    0x9,
        0x5,  0x4,    0x6,    0x9,    0x6,    0x4,    0x7,    0x9,    0x7,
        0x4,  0x8,    0x9,    0x8,    0x4,    0x9,    0x9,    0x9,    0x3,
        0x2,  0x3,    0x2,    0x3,    0x2,    0x3,    0x2,    0x3,    0x2,
        0x3,  0x2,    0x5,    0x2,    0x19,   0xa,    0x2,    0x3,    0x3,
        0x3,  0x3,    0x3,    0x3,    0x7,    0x3,    0x1e,   0xa,    0x3,
        0xc,  0x3,    0xe,    0x3,    0x21,   0xb,    0x3,    0x3,    0x4,
        0x3,  0x4,    0x3,    0x4,    0x7,    0x4,    0x26,   0xa,    0x4,
        0xc,  0x4,    0xe,    0x4,    0x29,   0xb,    0x4,    0x3,    0x5,
        0x3,  0x5,    0x3,    0x5,    0x3,    0x5,    0x5,    0x5,    0x2f,
        0xa,  0x5,    0x3,    0x5,    0x3,    0x5,    0x3,    0x5,    0x3,
        0x5,  0x5,    0x5,    0x35,   0xa,    0x5,    0x3,    0x6,    0x3,
        0x6,  0x3,    0x7,    0x3,    0x7,    0x5,    0x7,    0x3b,   0xa,
        0x7,  0x3,    0x8,    0x3,    0x8,    0x3,    0x9,    0x3,    0x9,
        0x3,  0x9,    0x2,    0x2,    0xa,    0x2,    0x4,    0x6,    0x8,
        0xa,  0xc,    0xe,    0x10,   0x2,    0x4,    0x4,    0x2,    0x22,
        0x22, 0x26,   0x27,   0x3,    0x2,    0x1a,   0x1b,   0x2,    0x40,
        0x2,  0x18,   0x3,    0x2,    0x2,    0x2,    0x4,    0x1a,   0x3,
        0x2,  0x2,    0x2,    0x6,    0x22,   0x3,    0x2,    0x2,    0x2,
        0x8,  0x34,   0x3,    0x2,    0x2,    0x2,    0xa,    0x36,   0x3,
        0x2,  0x2,    0x2,    0xc,    0x3a,   0x3,    0x2,    0x2,    0x2,
        0xe,  0x3c,   0x3,    0x2,    0x2,    0x2,    0x10,   0x3e,   0x3,
        0x2,  0x2,    0x2,    0x12,   0x13,   0x5,    0x4,    0x3,    0x2,
        0x13, 0x14,   0x7,    0x2,    0x2,    0x3,    0x14,   0x19,   0x3,
        0x2,  0x2,    0x2,    0x15,   0x16,   0x5,    0x6,    0x4,    0x2,
        0x16, 0x17,   0x7,    0x2,    0x2,    0x3,    0x17,   0x19,   0x3,
        0x2,  0x2,    0x2,    0x18,   0x12,   0x3,    0x2,    0x2,    0x2,
        0x18, 0x15,   0x3,    0x2,    0x2,    0x2,    0x19,   0x3,    0x3,
        0x2,  0x2,    0x2,    0x1a,   0x1f,   0x7,    0x3,    0x2,    0x2,
        0x1b, 0x1c,   0x7,    0x17,   0x2,    0x2,    0x1c,   0x1e,   0x5,
        0x8,  0x5,    0x2,    0x1d,   0x1b,   0x3,    0x2,    0x2,    0x2,
        0x1e, 0x21,   0x3,    0x2,    0x2,    0x2,    0x1f,   0x1d,   0x3,
        0x2,  0x2,    0x2,    0x1f,   0x20,   0x3,    0x2,    0x2,    0x2,
        0x20, 0x5,    0x3,    0x2,    0x2,    0x2,    0x21,   0x1f,   0x3,
        0x2,  0x2,    0x2,    0x22,   0x27,   0x5,    0x8,    0x5,    0x2,
        0x23, 0x24,   0x7,    0x17,   0x2,    0x2,    0x24,   0x26,   0x5,
        0x8,  0x5,    0x2,    0x25,   0x23,   0x3,    0x2,    0x2,    0x2,
        0x26, 0x29,   0x3,    0x2,    0x2,    0x2,    0x27,   0x25,   0x3,
        0x2,  0x2,    0x2,    0x27,   0x28,   0x3,    0x2,    0x2,    0x2,
        0x28, 0x7,    0x3,    0x2,    0x2,    0x2,    0x29,   0x27,   0x3,
        0x2,  0x2,    0x2,    0x2a,   0x35,   0x5,    0x10,   0x9,    0x2,
        0x2b, 0x2c,   0x5,    0x10,   0x9,    0x2,    0x2c,   0x2e,   0x5,
        0xc,  0x7,    0x2,    0x2d,   0x2f,   0x5,    0x10,   0x9,    0x2,
        0x2e, 0x2d,   0x3,    0x2,    0x2,    0x2,    0x2e,   0x2f,   0x3,
        0x2,  0x2,    0x2,    0x2f,   0x35,   0x3,    0x2,    0x2,    0x2,
        0x30, 0x31,   0x5,    0xc,    0x7,    0x2,    0x31,   0x32,   0x5,
        0x10, 0x9,    0x2,    0x32,   0x35,   0x3,    0x2,    0x2,    0x2,
        0x33, 0x35,   0x5,    0xa,    0x6,    0x2,    0x34,   0x2a,   0x3,
        0x2,  0x2,    0x2,    0x34,   0x2b,   0x3,    0x2,    0x2,    0x2,
        0x34, 0x30,   0x3,    0x2,    0x2,    0x2,    0x34,   0x33,   0x3,
        0x2,  0x2,    0x2,    0x35,   0x9,    0x3,    0x2,    0x2,    0x2,
        0x36, 0x37,   0x5,    0xe,    0x8,    0x2,    0x37,   0xb,    0x3,
        0x2,  0x2,    0x2,    0x38,   0x3b,   0x5,    0xe,    0x8,    0x2,
        0x39, 0x3b,   0x7,    0x24,   0x2,    0x2,    0x3a,   0x38,   0x3,
        0x2,  0x2,    0x2,    0x3a,   0x39,   0x3,    0x2,    0x2,    0x2,
        0x3b, 0xd,    0x3,    0x2,    0x2,    0x2,    0x3c,   0x3d,   0x9,
        0x2,  0x2,    0x2,    0x3d,   0xf,    0x3,    0x2,    0x2,    0x2,
        0x3e, 0x3f,   0x9,    0x3,    0x2,    0x2,    0x3f,   0x11,   0x3,
        0x2,  0x2,    0x2,    0x8,    0x18,   0x1f,   0x27,   0x2e,   0x34,
        0x3a,
    };

    _serializedATN.insert(
        _serializedATN.end(), serializedATNSegment0,
        serializedATNSegment0 +
            sizeof(serializedATNSegment0) / sizeof(serializedATNSegment0[0]));

    atn::ATNDeserializer deserializer;
    _atn = deserializer.deserialize(_serializedATN);

    size_t count = _atn.getNumberOfDecisions();
    _decisionToDFA.reserve(count);
    for (size_t i = 0; i < count; i++) {
        _decisionToDFA.emplace_back(_atn.getDecisionState(i), i);
    }
}

PathParser::Initializer PathParser::_init;
