#!/usr/bin/env python

# CAVEAT UTILITOR
#
# This file was automatically generated by TatSu.
#
#    https://pypi.python.org/pypi/tatsu/
#
# Any changes you make to it will be overwritten the next time
# the file is generated.

from __future__ import annotations

import sys

from tatsu.buffering import Buffer
from tatsu.parsing import Parser
from tatsu.parsing import tatsumasu
from tatsu.parsing import leftrec, nomemo, isname  # noqa
from tatsu.infos import ParserConfig
from tatsu.util import re, generic_main  # noqa


KEYWORDS = {}  # type: ignore


class KarpQueryV6Buffer(Buffer):
    def __init__(self, text, /, config: ParserConfig = None, **settings):
        base_config = ParserConfig.new(
            owner=self,
            whitespace=None,
            nameguard=None,
            comments_re=None,
            eol_comments_re=None,
            ignorecase=False,
            namechars="",
            parseinfo=False,
        )
        config = base_config.replace_config(config)
        config = config.merge(**settings)
        super().__init__(text, config=config)


class KarpQueryV6Parser(Parser):
    def __init__(self, config: ParserConfig = None, **settings):
        base_config = ParserConfig.new(
            owner=self,
            whitespace=None,
            nameguard=None,
            comments_re=None,
            eol_comments_re=None,
            ignorecase=False,
            namechars="",
            parseinfo=False,
            keywords=KEYWORDS,
        )
        config = base_config.replace_config(config)
        config = config.merge(**settings)
        super().__init__(config=config)

    @tatsumasu()
    def _start_(self):  # noqa
        self._expression_()
        self._check_eof()

    @tatsumasu()
    def _expression_(self):  # noqa
        with self._choice():
            with self._option():
                self._logical_expression_()
            with self._option():
                self._query_expression_()
            self._error(
                "expecting one of: "
                "<and> <or> <not> <logical_expression>"
                "<contains> <endswith> <equals> <exists>"
                "<freergxp> <freetext> <gt> <gte> <lt>"
                "<lte> <missing> <regexp> <startswith>"
                "<query_expression>"
            )

    @tatsumasu()
    def _query_expression_(self):  # noqa
        with self._choice():
            with self._option():
                self._contains_()
            with self._option():
                self._endswith_()
            with self._option():
                self._equals_()
            with self._option():
                self._exists_()
            with self._option():
                self._freergxp_()
            with self._option():
                self._freetext_()
            with self._option():
                self._gt_()
            with self._option():
                self._gte_()
            with self._option():
                self._lt_()
            with self._option():
                self._lte_()
            with self._option():
                self._missing_()
            with self._option():
                self._regexp_()
            with self._option():
                self._startswith_()
            self._error(
                "expecting one of: "
                "'contains' 'endswith' 'equals' 'exists'"
                "'freergxp' <freetext_any>"
                "<freetext_string> <freetext> 'gt' 'gte'"
                "'lt' 'lte' 'missing' 'regexp'"
                "'startswith'"
            )

    @tatsumasu()
    def _logical_expression_(self):  # noqa
        with self._choice():
            with self._option():
                self._and_()
            with self._option():
                self._or_()
            with self._option():
                self._not_()
            self._error("expecting one of: " "'and' 'or' 'not'")

    @tatsumasu("And")
    def _and_(self):  # noqa
        self._token("and")
        self.name_last_node("op")
        self._token("(")
        self._expression_()
        self.add_last_node_to_name("exps")

        def block2():
            self._token("||")
            self._expression_()
            self.add_last_node_to_name("exps")

        self._closure(block2)
        self._token(")")
        self._define(["op"], ["exps"])

    @tatsumasu("Contains")
    def _contains_(self):  # noqa
        self._token("contains")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._string_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Endswith")
    def _endswith_(self):  # noqa
        self._token("endswith")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._string_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Equals")
    def _equals_(self):  # noqa
        self._token("equals")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._argument_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Exists")
    def _exists_(self):  # noqa
        self._token("exists")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._define(["field", "op"], [])

    @tatsumasu("Freergxp")
    def _freergxp_(self):  # noqa
        self._token("freergxp")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("arg")
        self._define(["arg", "op"], [])

    @tatsumasu()
    def _freetext_(self):  # noqa
        with self._choice():
            with self._option():
                self._freetext_any_()
            with self._option():
                self._freetext_string_()
            self._error(
                "expecting one of: " "'freetext' <freetext_any>" "<freetext_string>"
            )

    @tatsumasu("FreetextAnyButString")
    def _freetext_any_(self):  # noqa
        self._token("freetext")
        self.name_last_node("op")
        self._token("|")
        self._any_but_string_()
        self.name_last_node("arg")
        self._define(["arg", "op"], [])

    @tatsumasu("FreetextString")
    def _freetext_string_(self):  # noqa
        self._token("freetext")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("arg")
        self._define(["arg", "op"], [])

    @tatsumasu("Gt")
    def _gt_(self):  # noqa
        self._token("gt")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._argument_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Gte")
    def _gte_(self):  # noqa
        self._token("gte")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._argument_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Lt")
    def _lt_(self):  # noqa
        self._token("lt")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._argument_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Lte")
    def _lte_(self):  # noqa
        self._token("lte")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._argument_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Missing")
    def _missing_(self):  # noqa
        self._token("missing")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._define(["field", "op"], [])

    @tatsumasu("Not")
    def _not_(self):  # noqa
        self._token("not")
        self.name_last_node("op")
        self._token("(")
        self._expression_()
        self.add_last_node_to_name("exps")

        def block2():
            self._token("||")
            self._expression_()
            self.add_last_node_to_name("exps")

        self._closure(block2)
        self._token(")")
        self._define(["op"], ["exps"])

    @tatsumasu("Or")
    def _or_(self):  # noqa
        self._token("or")
        self.name_last_node("op")
        self._token("(")
        self._expression_()
        self.add_last_node_to_name("exps")

        def block2():
            self._token("||")
            self._expression_()
            self.add_last_node_to_name("exps")

        self._closure(block2)
        self._token(")")
        self._define(["op"], ["exps"])

    @tatsumasu("Regexp")
    def _regexp_(self):  # noqa
        self._token("regexp")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._string_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu("Startswith")
    def _startswith_(self):  # noqa
        self._token("startswith")
        self.name_last_node("op")
        self._token("|")
        self._string_()
        self.name_last_node("field")
        self._token("|")
        self._string_()
        self.name_last_node("arg")
        self._define(["arg", "field", "op"], [])

    @tatsumasu()
    def _argument_(self):  # noqa
        with self._choice():
            with self._option():
                self._integer_()
            with self._option():
                self._string_()
            self._error("expecting one of: " "\\d+ <integer> [^|()]+ <string>")

    @tatsumasu()
    def _any_but_string_(self):  # noqa
        self._integer_()

    @tatsumasu()
    def _string_(self):  # noqa
        self._pattern("[^|()]+")

    @tatsumasu("int")
    def _integer_(self):  # noqa
        self._pattern("\\d+")


class KarpQueryV6Semantics(object):
    def start(self, ast):  # noqa
        return ast

    def expression(self, ast):  # noqa
        return ast

    def query_expression(self, ast):  # noqa
        return ast

    def logical_expression(self, ast):  # noqa
        return ast

    def and_(self, ast):  # noqa
        return ast

    def contains(self, ast):  # noqa
        return ast

    def endswith(self, ast):  # noqa
        return ast

    def equals(self, ast):  # noqa
        return ast

    def exists(self, ast):  # noqa
        return ast

    def freergxp(self, ast):  # noqa
        return ast

    def freetext(self, ast):  # noqa
        return ast

    def freetext_any(self, ast):  # noqa
        return ast

    def freetext_string(self, ast):  # noqa
        return ast

    def gt(self, ast):  # noqa
        return ast

    def gte(self, ast):  # noqa
        return ast

    def lt(self, ast):  # noqa
        return ast

    def lte(self, ast):  # noqa
        return ast

    def missing(self, ast):  # noqa
        return ast

    def not_(self, ast):  # noqa
        return ast

    def or_(self, ast):  # noqa
        return ast

    def regexp(self, ast):  # noqa
        return ast

    def startswith(self, ast):  # noqa
        return ast

    def argument(self, ast):  # noqa
        return ast

    def any_but_string(self, ast):  # noqa
        return ast

    def string(self, ast):  # noqa
        return ast

    def integer(self, ast):  # noqa
        return ast


def main(filename, start=None, **kwargs):
    if start is None:
        start = "start"
    if not filename or filename == "-":
        text = sys.stdin.read()
    else:
        with open(filename) as f:
            text = f.read()
    parser = KarpQueryV6Parser()
    return parser.parse(text, rule_name=start, filename=filename, **kwargs)


if __name__ == "__main__":
    import json
    from tatsu.util import asjson

    ast = generic_main(main, KarpQueryV6Parser, name="KarpQueryV6")
    data = asjson(ast)
    print(json.dumps(data, indent=2))
