#!/usr/bin/env python3
#
#  CAVEAT UTILITOR
#
#  This file was automatically generated by 竜TatSu v5.23.1b1
#
#     https://pypi.python.org/pypi/tatsu/
#
#  Any changes you make to it will be overwritten the next time
#  the file is generated.
#
# noqa # type: ignore # ruff: noqa
# copyright: ignore
# fmt: off

from __future__ import annotations

from typing import Any

from tatsu import decorators as tatsu
from tatsu.contexts import Ctx
from tatsu.config import ParserConfig
from tatsu.parsing import Parser
from tatsu.input.buffer import Buffer
from tatsu.input.textlines import TextLines

KEYWORDS = ()


class TatSuBootstrapText(TextLines):
    def __init__(
        self,
        text,
        /,
        config: ParserConfig | None = None,
        **settings,
    ) -> None:
        config = ParserConfig.new(
            config=config,
            name='TatSu',
            whitespace=None,
            nameguard=None,
            ignorecase=False,
            namechars='',
            parseinfo=True,
            comments=r'(?ms)[(][*]\s*(.*?)\s*[*][)]|/[*]\s*(.*?)\s*[*]/',
            eol_comments=r'(?ms)(?:#|//)(.*?)$',
            keywords=KEYWORDS,
            start='start',
        )
        assert isinstance(config, ParserConfig)
        config = config.override(**settings)

        super().__init__(text, config=config)

TatSuBootstrapTokenizer = TatSuBootstrapText


class TatSuBootstrapBuffer(Buffer):  # NOTE: backwards compatibility
    def __init__(
        self,
        text,
        /,
        config: ParserConfig | None = None,
        **settings,
    ) -> None:
        config = ParserConfig.new(
            config=config,
            name='TatSu',
            whitespace=None,
            nameguard=None,
            ignorecase=False,
            namechars='',
            parseinfo=True,
            comments=r'(?ms)[(][*]\s*(.*?)\s*[*][)]|/[*]\s*(.*?)\s*[*]/',
            eol_comments=r'(?ms)(?:#|//)(.*?)$',
            keywords=KEYWORDS,
            start='start',
        )
        assert isinstance(config, ParserConfig)
        config = config.override(**settings)

        super().__init__(text, config=config)


class TatSuBootstrapParser(Parser):
    def __init__(self, /, config: ParserConfig | None = None, **settings):
        config = ParserConfig.new(config, **settings)
        rulessource = TatSuBootstrapRules()
        assert isinstance(config, ParserConfig)

        super().__init__(rulessource, config=config)


class TatSuBootstrapRules:
    def __init__(self, /, config: ParserConfig | None = None, **settings):
        config = ParserConfig.new(
            config=config,
            name='TatSu',
            whitespace=None,
            nameguard=None,
            ignorecase=False,
            namechars='',
            parseinfo=True,
            comments=r'(?ms)[(][*]\s*(.*?)\s*[*][)]|/[*]\s*(.*?)\s*[*]/',
            eol_comments=r'(?ms)(?:#|//)(.*?)$',
            keywords=KEYWORDS,
            start='start',
        )
        assert isinstance(config, ParserConfig)
        config = config.override(**settings)
        self._config = config


    @tatsu.rule
    def start(self, ctx: Ctx) -> Any:
        self.grammar(ctx)

    @tatsu.rule('Grammar')
    def grammar(self, ctx: Ctx) -> Any:
        ctx.define(
            ['directives', 'keywords', 'rules', 'title'],
            ['directives', 'keywords', 'rules'],
        )
        with ctx.nameset('title'):
            ctx.constant('TATSU')
        with ctx.loopopt() as cl:
            @cl.exp
            def _(ctx: Ctx) -> Any:
                with ctx.choice() as α:
                    α.expecting('@@', '@@keyword', '→directive', '→keyword')

                    @α.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameadd('directives'):
                            self.directive(ctx)
                    @α.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameadd('keywords'):
                            self.keyword(ctx)
        with ctx.nameadd('rules'):
            self.rule(ctx)
        with ctx.loopopt() as clb:
            @clb.exp
            def _(ctx: Ctx) -> Any:
                with ctx.choice() as α:
                    α.expecting('<', '=|::=|:=?', '@@keyword', '→decorator', '→keyword', '→rule')

                    @α.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameadd('rules'):
                            self.rule(ctx)
                    @α.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameadd('keywords'):
                            self.keyword(ctx)
        ctx.eofcheck()

    @tatsu.rule
    def directive(self, ctx: Ctx) -> Any:
        ctx.define(['name', 'value'], [])
        ctx.token('@@')
        with ctx.ifnot_():
            ctx.token('keyword')
        ctx.cut()
        with ctx.group():
            with ctx.choice() as α:
                α.expecting(
                  'comments',
                  'eol_comments',
                  'grammar',
                  'ignorecase',
                  'left_recursion',
                  'memoization',
                  'namechars',
                  'nameguard',
                  'parseinfo',
                  'whitespace'
                )

                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['name', 'value'], [])
                    with ctx.nameset('name'):
                        with ctx.group():
                            with ctx.choice() as β:
                                β.expecting('comments', 'eol_comments')

                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('comments')
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('eol_comments')
                    ctx.cut()
                    ctx.token('::')
                    ctx.cut()
                    with ctx.nameset('value'):
                        self.regex(ctx)
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['name', 'value'], [])
                    with ctx.nameset('name'):
                        ctx.token('whitespace')
                    ctx.cut()
                    ctx.token('::')
                    ctx.cut()
                    with ctx.nameset('value'):
                        with ctx.group():
                            with ctx.choice() as β:
                                β.expecting('False', 'None', '→regex', '→string')

                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    self.regex(ctx)
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    self.string(ctx)
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('None')
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('False')
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.constant(None)
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['name', 'value'], [])
                    with ctx.nameset('name'):
                        with ctx.group():
                            with ctx.choice() as β:
                                β.expecting('ignorecase', 'left_recursion', 'memoization', 'nameguard', 'parseinfo')

                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('nameguard')
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('ignorecase')
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('left_recursion')
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('parseinfo')
                                @β.option
                                def _(ctx: Ctx) -> Any:
                                    ctx.token('memoization')
                    ctx.cut()
                    with ctx.group():
                        with ctx.choice() as β:
                            β.expecting('::')

                            @β.option
                            def _(ctx: Ctx) -> Any:
                                ctx.define(['value'], [])
                                ctx.token('::')
                                ctx.cut()
                                with ctx.nameset('value'):
                                    self.boolean(ctx)
                            @β.option
                            def _(ctx: Ctx) -> Any:
                                with ctx.nameset('value'):
                                    ctx.constant(True)
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['name', 'value'], [])
                    with ctx.nameset('name'):
                        ctx.token('grammar')
                    ctx.cut()
                    ctx.token('::')
                    ctx.cut()
                    with ctx.nameset('value'):
                        self.word(ctx)
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['name', 'value'], [])
                    with ctx.nameset('name'):
                        ctx.token('namechars')
                    ctx.cut()
                    ctx.token('::')
                    ctx.cut()
                    with ctx.nameset('value'):
                        self.string(ctx)
        ctx.cut()

    @tatsu.rule
    def keywords(self, ctx: Ctx) -> Any:
        with ctx.loopplus() as cl:
            @cl.exp
            def _(ctx: Ctx) -> Any:
                self.keyword(ctx)

    @tatsu.rule
    def keyword(self, ctx: Ctx) -> Any:
        ctx.token('@@keyword')
        ctx.cut()
        ctx.token('::')
        with ctx.group():
            with ctx.choice() as α:
                α.expecting('(', '→string', '→word')

                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.token('(')
                    ctx.cut()
                    with ctx.result():
                        with ctx.loopplus() as cl:
                            @cl.exp
                            def _(ctx: Ctx) -> Any:
                                with ctx.choice() as β:
                                    β.expecting('→string', '→word')

                                    @β.option
                                    def _(ctx: Ctx) -> Any:
                                        self.word(ctx)
                                    @β.option
                                    def _(ctx: Ctx) -> Any:
                                        self.string(ctx)
                    ctx.token(')')
                @α.option
                def _(ctx: Ctx) -> Any:
                    with ctx.loopplus() as clb:
                        @clb.exp
                        def _(ctx: Ctx) -> Any:
                            with ctx.resultadd():
                                with ctx.group():
                                    with ctx.choice() as β:
                                        β.expecting('→string', '→word')

                                        @β.option
                                        def _(ctx: Ctx) -> Any:
                                            self.word(ctx)
                                        @β.option
                                        def _(ctx: Ctx) -> Any:
                                            self.string(ctx)
                            with ctx.ifnot_():
                                with ctx.group():
                                    with ctx.choice() as β:
                                        β.expecting(':', '=')

                                        @β.option
                                        def _(ctx: Ctx) -> Any:
                                            ctx.token(':')
                                        @β.option
                                        def _(ctx: Ctx) -> Any:
                                            ctx.token('=')

    @tatsu.rule
    def params(self, ctx: Ctx) -> Any:
        with ctx.resultadd():
            self.first_param(ctx)
        with ctx.loopopt() as cl:
            @cl.exp
            def _(ctx: Ctx) -> Any:
                ctx.token(',')
                with ctx.resultadd():
                    self.literal(ctx)
                with ctx.ifnot_():
                    ctx.token('=')
                ctx.cut()

    @tatsu.rule
    def first_param(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '[_\\w][_\\w\\d]*(?:::[_\\w][_\\w\\d]*)+',
              '→boolean',
              '→float',
              '→hex',
              '→int',
              '→literal',
              '→none',
              '→path',
              '→raw_string',
              '→value',
              '→word'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.path(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.literal(ctx)

    @tatsu.rule
    def kwparams(self, ctx: Ctx) -> Any:
        with ctx.gatherplus() as g:
            @g.sep
            def _(ctx: Ctx) -> Any:
                ctx.token(',')

            @g.exp
            def _(ctx: Ctx) -> Any:
                self.pair(ctx)

    @tatsu.rule
    def the_params_at_last(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '→first_param',
              '→kwparams',
              '→literal',
              '→pair',
              '→params',
              '→path',
              '→word'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.nameset('kwparams'):
                    self.kwparams(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.define(['kwparams', 'params'], [])
                with ctx.nameset('params'):
                    self.params(ctx)
                ctx.token(',')
                ctx.cut()
                with ctx.nameset('kwparams'):
                    self.kwparams(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.nameset('params'):
                    self.params(ctx)

    @tatsu.rule
    def paramdef(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting('(', '::', '[')

            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.define(['kwparams', 'params'], [])
                ctx.token('[')
                ctx.cut()
                with ctx.choice() as β:
                    β.expecting(
                      '→first_param',
                      '→kwparams',
                      '→literal',
                      '→pair',
                      '→params',
                      '→path',
                      '→word'
                    )

                    @β.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameset('kwparams'):
                            self.kwparams(ctx)
                    @β.option
                    def _(ctx: Ctx) -> Any:
                        ctx.define(['kwparams', 'params'], [])
                        with ctx.nameset('params'):
                            self.params(ctx)
                        ctx.token(',')
                        ctx.cut()
                        with ctx.nameset('kwparams'):
                            self.kwparams(ctx)
                    @β.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameset('params'):
                            self.params(ctx)
                ctx.token(']')
            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.define(['kwparams', 'params'], [])
                ctx.token('(')
                ctx.cut()
                with ctx.choice() as β:
                    β.expecting(
                      '→first_param',
                      '→kwparams',
                      '→literal',
                      '→pair',
                      '→params',
                      '→path',
                      '→word'
                    )

                    @β.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameset('kwparams'):
                            self.kwparams(ctx)
                    @β.option
                    def _(ctx: Ctx) -> Any:
                        ctx.define(['kwparams', 'params'], [])
                        with ctx.nameset('params'):
                            self.params(ctx)
                        ctx.token(',')
                        ctx.cut()
                        with ctx.nameset('kwparams'):
                            self.kwparams(ctx)
                    @β.option
                    def _(ctx: Ctx) -> Any:
                        with ctx.nameset('params'):
                            self.params(ctx)
                ctx.token(')')
            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.define(['params'], [])
                ctx.token('::')
                ctx.cut()
                with ctx.nameset('params'):
                    self.params(ctx)

    @tatsu.rule('Rule')
    def rule(self, ctx: Ctx) -> Any:
        ctx.define(['base', 'decorators', 'exp', 'kwparams', 'name', 'params'], [])
        with ctx.nameset('decorators'):
            with ctx.loopopt() as cl:
                @cl.exp
                def _(ctx: Ctx) -> Any:
                    self.decorator(ctx)
        with ctx.nameset('name'):
            ctx.matchname()
        ctx.cut()
        with ctx.optional():
            with ctx.choice() as α:
                α.expecting('(', '::', '[')

                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['kwparams', 'params'], [])
                    ctx.token('[')
                    ctx.cut()
                    with ctx.choice() as β:
                        β.expecting(
                          '→first_param',
                          '→kwparams',
                          '→literal',
                          '→pair',
                          '→params',
                          '→path',
                          '→word'
                        )

                        @β.option
                        def _(ctx: Ctx) -> Any:
                            with ctx.nameset('kwparams'):
                                self.kwparams(ctx)
                        @β.option
                        def _(ctx: Ctx) -> Any:
                            ctx.define(['kwparams', 'params'], [])
                            with ctx.nameset('params'):
                                self.params(ctx)
                            ctx.token(',')
                            ctx.cut()
                            with ctx.nameset('kwparams'):
                                self.kwparams(ctx)
                        @β.option
                        def _(ctx: Ctx) -> Any:
                            with ctx.nameset('params'):
                                self.params(ctx)
                    ctx.token(']')
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['kwparams', 'params'], [])
                    ctx.token('(')
                    ctx.cut()
                    with ctx.choice() as β:
                        β.expecting(
                          '→first_param',
                          '→kwparams',
                          '→literal',
                          '→pair',
                          '→params',
                          '→path',
                          '→word'
                        )

                        @β.option
                        def _(ctx: Ctx) -> Any:
                            with ctx.nameset('kwparams'):
                                self.kwparams(ctx)
                        @β.option
                        def _(ctx: Ctx) -> Any:
                            ctx.define(['kwparams', 'params'], [])
                            with ctx.nameset('params'):
                                self.params(ctx)
                            ctx.token(',')
                            ctx.cut()
                            with ctx.nameset('kwparams'):
                                self.kwparams(ctx)
                        @β.option
                        def _(ctx: Ctx) -> Any:
                            with ctx.nameset('params'):
                                self.params(ctx)
                    ctx.token(')')
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.define(['params'], [])
                    ctx.token('::')
                    ctx.cut()
                    with ctx.nameset('params'):
                        self.params(ctx)
        with ctx.optional():
            ctx.define(['base'], [])
            ctx.token('<')
            ctx.cut()
            with ctx.nameset('base'):
                self.known_name(ctx)
        ctx.void()
        ctx.pattern(r'=|::=|:=?')
        ctx.cut()
        with ctx.nameset('exp'):
            self.expre(ctx)
        self.ENDRULE(ctx)
        ctx.cut()

    @tatsu.rule
    @tatsu.token
    def ENDRULE(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(';', '→BLANK', '→DEDENT', '→EOL')

            @α.option
            def _(ctx: Ctx) -> Any:
                self.DEDENT(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.BLANK(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.token(';')
            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.eofcheck()

    @tatsu.rule
    @tatsu.token
    def DEDENT(self, ctx: Ctx) -> Any:
        self.EOL(ctx)
        with ctx.if_():
            ctx.pattern(r'^\S')

    @tatsu.rule
    @tatsu.token
    def BLANK(self, ctx: Ctx) -> Any:
        self.EOL(ctx)
        self.EOL(ctx)

    @tatsu.rule
    @tatsu.token
    def EOL(self, ctx: Ctx) -> Any:
        ctx.pattern(r'(?m)[ \t]*$')
        ctx.pattern(r'(?m)(?:\r?\n|\r)')

    @tatsu.rule
    def decorator(self, ctx: Ctx) -> Any:
        ctx.token('@')
        with ctx.ifnot_():
            ctx.token('@')
        ctx.cut()
        with ctx.result():
            ctx.pattern(r'(override|name|isname|nomemo|nostak)\b')

    @tatsu.rule
    def pair(self, ctx: Ctx) -> Any:
        with ctx.resultadd():
            self.word(ctx)
        ctx.token('=')
        ctx.cut()
        with ctx.resultadd():
            self.literal(ctx)

    @tatsu.rule
    def expre(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              ';',
              '→BLANK',
              '→DEDENT',
              '→ENDRULE',
              '→choice',
              '→element',
              '→option',
              '→sequence',
              '|'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.choice(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.sequence(ctx)

    @tatsu.rule('Choice')
    def choice(self, ctx: Ctx) -> Any:
        with ctx.optional():
            ctx.token('|')
            ctx.cut()
        with ctx.resultadd():
            self.option(ctx)
        with ctx.loopplus() as cl:
            @cl.exp
            def _(ctx: Ctx) -> Any:
                ctx.token('|')
                ctx.cut()
                with ctx.resultadd():
                    self.option(ctx)

    @tatsu.rule('Option')
    def option(self, ctx: Ctx) -> Any:
        self.sequence(ctx)

    @tatsu.rule('Sequence')
    def sequence(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              ';',
              '→BLANK',
              '→DEDENT',
              '→ENDRULE',
              '→EOL',
              '→element',
              '→meta',
              '→named',
              '→override',
              '→rule_include',
              '→term'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.if_():
                    with ctx.group():
                        self.element(ctx)
                        ctx.token(',')
                with ctx.gatherplus() as g:
                    @g.sep
                    def _(ctx: Ctx) -> Any:
                        ctx.token(',')

                    @g.exp
                    def _(ctx: Ctx) -> Any:
                        self.element(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.loopplus() as cl:
                    @cl.exp
                    def _(ctx: Ctx) -> Any:
                        with ctx.ifnot_():
                            self.ENDRULE(ctx)
                        self.element(ctx)

    @tatsu.rule
    def element(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '>',
              '@(name|int|uint|float|bool)\\b',
              '→atom',
              '→closure',
              '→cut',
              '→cut_deprecated',
              '→empty_closure',
              '→gather',
              '→join',
              '→left_join',
              '→lookahead',
              '→meta',
              '→named',
              '→named_list',
              '→named_single',
              '→negative_lookahead',
              '→optional',
              '→override',
              '→override_list',
              '→override_single',
              '→positive_closure',
              '→right_join',
              '→rule_include',
              '→skip_to',
              '→term',
              '→void'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.override(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.meta(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.named(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.term(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.rule_include(ctx)

    @tatsu.rule('RuleInclude')
    def rule_include(self, ctx: Ctx) -> Any:
        ctx.token('>')
        ctx.cut()
        with ctx.result():
            self.known_name(ctx)

    @tatsu.rule
    def named(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting('[:=]', '\\+[:=]', '→named_list', '→named_single')

            @α.option
            def _(ctx: Ctx) -> Any:
                self.named_list(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.named_single(ctx)

    @tatsu.rule('NamedList')
    def named_list(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'name'], [])
        with ctx.nameset('name'):
            ctx.matchname()
        ctx.pattern(r'\+[:=]')
        ctx.cut()
        with ctx.nameset('exp'):
            self.term(ctx)

    @tatsu.rule('Named')
    def named_single(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'name'], [])
        with ctx.nameset('name'):
            ctx.matchname()
        ctx.pattern(r'[:=]')
        ctx.cut()
        with ctx.nameset('exp'):
            self.term(ctx)

    @tatsu.rule
    def override(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting('=|@:', '\\+=|@\\+:', '→override_list', '→override_single')

            @α.option
            def _(ctx: Ctx) -> Any:
                self.override_list(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.override_single(ctx)

    @tatsu.rule('OverrideList')
    def override_list(self, ctx: Ctx) -> Any:
        ctx.pattern(r'\+=|@\+:')
        ctx.cut()
        with ctx.result():
            self.term(ctx)

    @tatsu.rule('Override')
    def override_single(self, ctx: Ctx) -> Any:
        ctx.pattern(r'=|@:')
        ctx.cut()
        with ctx.result():
            self.term(ctx)

    @tatsu.rule
    def term(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '!',
              '&',
              '()',
              '(?:',
              '->',
              '>>',
              '[',
              '→alert',
              '→atom',
              '→call',
              '→closure',
              '→constant',
              '→cut',
              '→cut_deprecated',
              '→dot',
              '→empty_closure',
              '→eof',
              '→eol',
              '→gather',
              '→group',
              '→join',
              '→left_join',
              '→lookahead',
              '→meta',
              '→negative_lookahead',
              '→optional',
              '→pattern',
              '→positive_closure',
              '→right_join',
              '→skip',
              '→skip_to',
              '→token',
              '→void',
              '{',
              '{}',
              '~'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.gather(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.join(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.left_join(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.right_join(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.empty_closure(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.positive_closure(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.closure(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.optional(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.atom(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.void(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.skip_to(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.lookahead(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.negative_lookahead(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.cut(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.cut_deprecated(ctx)

    @tatsu.rule('Group')
    def group(self, ctx: Ctx) -> Any:
        with ctx.ifnot_():
            ctx.token('(?:')
        ctx.token('(')
        ctx.cut()
        with ctx.result():
            self.expre(ctx)
        ctx.token(')')
        ctx.cut()

    @tatsu.rule('SkipGroup')
    def skip(self, ctx: Ctx) -> Any:
        ctx.token('(?:')
        ctx.cut()
        with ctx.result():
            self.expre(ctx)
        ctx.token(')')
        ctx.cut()

    @tatsu.rule
    def gather(self, ctx: Ctx) -> Any:
        with ctx.if_():
            with ctx.group():
                self.atom(ctx)
                ctx.token('.{')
        ctx.cut()
        with ctx.group():
            with ctx.choice() as α:
                α.expecting('→normal_gather', '→positive_gather')

                @α.option
                def _(ctx: Ctx) -> Any:
                    self.positive_gather(ctx)
                @α.option
                def _(ctx: Ctx) -> Any:
                    self.normal_gather(ctx)

    @tatsu.rule('PositiveGather')
    def positive_gather(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'sep'], [])
        with ctx.nameset('sep'):
            self.atom(ctx)
        ctx.token('.{')
        with ctx.nameset('exp'):
            self.expre(ctx)
        ctx.token('}')
        with ctx.ifnot_():
            ctx.pattern(r'\+=')
        ctx.pattern(r'[+-]')
        ctx.cut()

    @tatsu.rule('Gather')
    def normal_gather(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'sep'], [])
        with ctx.nameset('sep'):
            self.atom(ctx)
        ctx.token('.{')
        ctx.cut()
        with ctx.nameset('exp'):
            self.expre(ctx)
        ctx.token('}')
        with ctx.optional():
            ctx.token('*')
            ctx.cut()
        ctx.cut()

    @tatsu.rule
    def join(self, ctx: Ctx) -> Any:
        with ctx.if_():
            with ctx.group():
                self.atom(ctx)
                ctx.token('%{')
        ctx.cut()
        with ctx.group():
            with ctx.choice() as α:
                α.expecting('→normal_join', '→positive_join')

                @α.option
                def _(ctx: Ctx) -> Any:
                    self.positive_join(ctx)
                @α.option
                def _(ctx: Ctx) -> Any:
                    self.normal_join(ctx)

    @tatsu.rule('PositiveJoin')
    def positive_join(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'sep'], [])
        with ctx.nameset('sep'):
            self.atom(ctx)
        ctx.token('%{')
        with ctx.nameset('exp'):
            self.expre(ctx)
        ctx.token('}')
        with ctx.ifnot_():
            ctx.pattern(r'\+=')
        ctx.pattern(r'[+-]')
        ctx.cut()

    @tatsu.rule('Join')
    def normal_join(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'sep'], [])
        with ctx.nameset('sep'):
            self.atom(ctx)
        ctx.token('%{')
        ctx.cut()
        with ctx.nameset('exp'):
            self.expre(ctx)
        ctx.token('}')
        with ctx.optional():
            ctx.token('*')
            ctx.cut()
        ctx.cut()

    @tatsu.rule('LeftJoin')
    def left_join(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'sep'], [])
        with ctx.nameset('sep'):
            self.atom(ctx)
        ctx.token('<{')
        ctx.cut()
        with ctx.nameset('exp'):
            self.expre(ctx)
        ctx.token('}')
        with ctx.ifnot_():
            ctx.pattern(r'\+=')
        ctx.pattern(r'[+-]')
        ctx.cut()

    @tatsu.rule('RightJoin')
    def right_join(self, ctx: Ctx) -> Any:
        ctx.define(['exp', 'sep'], [])
        with ctx.nameset('sep'):
            self.atom(ctx)
        ctx.token('>{')
        ctx.cut()
        with ctx.nameset('exp'):
            self.expre(ctx)
        ctx.token('}')
        with ctx.ifnot_():
            ctx.pattern(r'\+=')
        ctx.pattern(r'[+-]')
        ctx.cut()

    @tatsu.rule('PositiveClosure')
    def positive_closure(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '(?:',
              '→alert',
              '→atom',
              '→call',
              '→constant',
              '→dot',
              '→eof',
              '→eol',
              '→group',
              '→meta',
              '→pattern',
              '→skip',
              '→token',
              '{'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.token('{')
                with ctx.result():
                    self.expre(ctx)
                ctx.token('}')
                with ctx.ifnot_():
                    ctx.pattern(r'\+=')
                ctx.pattern(r'[+-]')
                ctx.cut()
            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.result():
                    self.atom(ctx)
                with ctx.ifnot_():
                    ctx.pattern(r'\+=')
                ctx.pattern(r'[+]')
                ctx.cut()

    @tatsu.rule('Closure')
    def closure(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '(?:',
              '→alert',
              '→atom',
              '→call',
              '→constant',
              '→dot',
              '→eof',
              '→eol',
              '→group',
              '→meta',
              '→pattern',
              '→skip',
              '→token',
              '{'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.token('{')
                with ctx.result():
                    self.expre(ctx)
                ctx.token('}')
                with ctx.optional():
                    ctx.token('*')
                ctx.cut()
            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.result():
                    self.atom(ctx)
                ctx.token('*')
                ctx.cut()

    @tatsu.rule('EmptyClosure')
    def empty_closure(self, ctx: Ctx) -> Any:
        ctx.token('{}')
        ctx.cut()
        with ctx.result():
            ctx.void()

    @tatsu.rule('Optional')
    def optional(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '(?:',
              '[',
              '→alert',
              '→atom',
              '→call',
              '→constant',
              '→dot',
              '→eof',
              '→eol',
              '→group',
              '→meta',
              '→pattern',
              '→skip',
              '→token'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.token('[')
                ctx.cut()
                with ctx.result():
                    self.expre(ctx)
                ctx.token(']')
                ctx.cut()
            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.result():
                    self.atom(ctx)
                with ctx.ifnot_():
                    with ctx.group():
                        with ctx.choice() as β:
                            β.expecting('?"', "?'", '?/')

                            @β.option
                            def _(ctx: Ctx) -> Any:
                                ctx.token('?"')
                            @β.option
                            def _(ctx: Ctx) -> Any:
                                ctx.token("?'")
                            @β.option
                            def _(ctx: Ctx) -> Any:
                                ctx.token('?/')
                ctx.token('?')
                ctx.cut()

    @tatsu.rule('Lookahead')
    def lookahead(self, ctx: Ctx) -> Any:
        ctx.token('&')
        ctx.cut()
        with ctx.result():
            self.term(ctx)

    @tatsu.rule('NegativeLookahead')
    def negative_lookahead(self, ctx: Ctx) -> Any:
        ctx.token('!')
        ctx.cut()
        with ctx.result():
            self.term(ctx)

    @tatsu.rule('SkipTo')
    def skip_to(self, ctx: Ctx) -> Any:
        ctx.token('->')
        ctx.cut()
        with ctx.result():
            self.term(ctx)

    @tatsu.rule
    def atom(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '$',
              '$->',
              '(?:',
              '/./',
              '@(name|int|uint|float|bool)\\b',
              '\\^+',
              '`',
              '→alert',
              '→call',
              '→constant',
              '→dot',
              '→eof',
              '→eol',
              '→group',
              '→meta',
              '→pattern',
              '→raw_string',
              '→regex',
              '→skip',
              '→string',
              '→token'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.meta(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.token(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.call(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.dot(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.pattern(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.skip(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.group(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.eol(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.eof(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.alert(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.constant(ctx)

    @tatsu.rule('Meta')
    def meta(self, ctx: Ctx) -> Any:
        ctx.pattern(r'@(name|int|uint|float|bool)\b')

    @tatsu.rule('Call')
    def call(self, ctx: Ctx) -> Any:
        ctx.matchname()

    @tatsu.rule('Void')
    def void(self, ctx: Ctx) -> Any:
        ctx.token('()')
        ctx.cut()

    @tatsu.rule('Fail')
    def fail(self, ctx: Ctx) -> Any:
        ctx.token('!()')
        ctx.cut()

    @tatsu.rule('Cut')
    def cut(self, ctx: Ctx) -> Any:
        ctx.token('~')
        ctx.cut()

    @tatsu.rule('Cut')
    def cut_deprecated(self, ctx: Ctx) -> Any:
        ctx.token('>>')
        ctx.cut()

    @tatsu.rule
    def known_name(self, ctx: Ctx) -> Any:
        ctx.matchname()
        ctx.cut()

    @tatsu.rule
    def name(self, ctx: Ctx) -> Any:
        self.word(ctx)

    @tatsu.rule('Constant')
    def constant(self, ctx: Ctx) -> Any:
        with ctx.if_():
            ctx.token('`')
        with ctx.group():
            with ctx.choice() as α:
                α.expecting('(?ms)```((?:.|\\n)*?)```', '`', '`(.*?)`')

                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.pattern(r'(?ms)```((?:.|\n)*?)```')
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.token('`')
                    with ctx.result():
                        self.literal(ctx)
                    ctx.token('`')
                @α.option
                def _(ctx: Ctx) -> Any:
                    ctx.pattern(r'`(.*?)`')

    @tatsu.rule('Alert')
    def alert(self, ctx: Ctx) -> Any:
        ctx.define(['level', 'message'], [])
        with ctx.nameset('level'):
            ctx.pattern(r'\^+')
        with ctx.nameset('message'):
            self.constant(ctx)

    @tatsu.rule('Token')
    def token(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting('"', "'", 'r["\\\']', '→raw_string', '→string')

            @α.option
            def _(ctx: Ctx) -> Any:
                self.string(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.raw_string(ctx)

    @tatsu.rule
    def literal(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '"',
              "'",
              '(?ms)\\s*([_\\w][_\\w\\d]*)\\b',
              '0[xX](?:\\d|[a-fA-F])+',
              'False',
              'None',
              'True',
              '[-+]?(?:\\d+\\.\\d*|\\d*\\.\\d+)(?:[Ee][-+]?\\d+)?',
              '[-+]?\\d+',
              '→boolean',
              '→false',
              '→float',
              '→hex',
              '→int',
              '→none',
              '→null',
              '→number',
              'r["\\\']',
              '→raw_string',
              '→string',
              '→true',
              '→value',
              '→word'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.raw_string(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.value(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.boolean(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.none(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.word(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.hex(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.float(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.int(ctx)

    @tatsu.rule
    def string(self, ctx: Ctx) -> Any:
        with ctx.if_():
            with ctx.group():
                with ctx.choice() as α:
                    α.expecting('"', "'")

                    @α.option
                    def _(ctx: Ctx) -> Any:
                        ctx.token('"')
                    @α.option
                    def _(ctx: Ctx) -> Any:
                        ctx.token("'")
        with ctx.group():
            with ctx.choice() as α:
                α.expecting('→doublequoted', '→multiline_string', '→singlequoted')

                @α.option
                def _(ctx: Ctx) -> Any:
                    self.multiline_string(ctx)
                @α.option
                def _(ctx: Ctx) -> Any:
                    self.singlequoted(ctx)
                @α.option
                def _(ctx: Ctx) -> Any:
                    self.doublequoted(ctx)

    @tatsu.rule
    def singlequoted(self, ctx: Ctx) -> Any:
        self.SINGLEQUOTED(ctx)

    @tatsu.rule
    def doublequoted(self, ctx: Ctx) -> Any:
        self.DOUBLEQUOTED(ctx)

    @tatsu.rule
    def raw_string(self, ctx: Ctx) -> Any:
        with ctx.if_():
            ctx.pattern(r'r["\']')
        ctx.pattern(r'r')
        with ctx.result():
            self.STRING(ctx)

    @tatsu.rule
    @tatsu.token
    def STRING(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '"((?:[^"\\n]|\\\\"|\\\\\\\\)*?)"',
              "'((?:[^'\\n]|\\\\'|\\\\\\\\)*?)'",
              '→DOUBLEQUOTED',
              '→SINGLEQUOTED'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.SINGLEQUOTED(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.DOUBLEQUOTED(ctx)

    @tatsu.rule
    @tatsu.token
    def SINGLEQUOTED(self, ctx: Ctx) -> Any:
        ctx.pattern(r"'((?:[^'\n]|\\'|\\\\)*?)'")
        ctx.cut()

    @tatsu.rule
    @tatsu.token
    def DOUBLEQUOTED(self, ctx: Ctx) -> Any:
        ctx.pattern(r'"((?:[^"\n]|\\"|\\\\)*?)"')
        ctx.cut()

    @tatsu.rule
    def multiline_string(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '(?ms)"""((?:\\\\\\\\|\\\\.|.)*?)"""',
              "(?ms)'''((?:\\\\\\\\|\\\\.|.)*?)'''"
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.pattern(r"(?ms)'''((?:\\\\|\\.|.)*?)'''")
                ctx.cut()
            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.pattern(r'(?ms)"""((?:\\\\|\\.|.)*?)"""')
                ctx.cut()

    @tatsu.rule
    def hex(self, ctx: Ctx) -> Any:
        ctx.pattern(r'0[xX](?:\d|[a-fA-F])+')

    @tatsu.rule
    def float(self, ctx: Ctx) -> Any:
        ctx.pattern(r'[-+]?(?:\d+\.\d*|\d*\.\d+)(?:[Ee][-+]?\d+)?')

    @tatsu.rule
    def int(self, ctx: Ctx) -> Any:
        ctx.pattern(r'[-+]?\d+')

    @tatsu.rule
    def path(self, ctx: Ctx) -> Any:
        ctx.pattern(r'[_\w][_\w\d]*(?:::[_\w][_\w\d]*)+')

    @tatsu.rule
    def word(self, ctx: Ctx) -> Any:
        ctx.pattern(r'(?ms)\s*([_\w][_\w\d]*)\b')

    @tatsu.rule('Dot')
    def dot(self, ctx: Ctx) -> Any:
        ctx.token('/./')

    @tatsu.rule('Pattern')
    def pattern(self, ctx: Ctx) -> Any:
        self.regex(ctx)

    @tatsu.rule
    def regex(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting('?/', '→deprecated_regex')

            @α.option
            def _(ctx: Ctx) -> Any:
                self.deprecated_regex(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                with ctx.ifnot_():
                    ctx.token('?/')
                with ctx.group():
                    with ctx.choice() as β:
                        β.expecting('?', '→REGEX')

                        @β.option
                        def _(ctx: Ctx) -> Any:
                            self.REGEX(ctx)
                        @β.option
                        def _(ctx: Ctx) -> Any:
                            ctx.token('?')
                            with ctx.result():
                                self.STRING(ctx)

    @tatsu.rule
    @tatsu.token
    def REGEX(self, ctx: Ctx) -> Any:
        with ctx.if_():
            ctx.token('/')
        ctx.pattern(r'(?ms)/((?:[^/\\]|\\/|\\.)*)/')
        ctx.cut()

    @tatsu.rule
    def deprecated_regex(self, ctx: Ctx) -> Any:
        ctx.token('?/')
        ctx.cut()
        with ctx.result():
            ctx.pattern(r'(?ms)((?:[^/\\]|\\/|\\.)*)')
        ctx.cut()
        ctx.token('/?')

    @tatsu.rule
    def boolean(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting('False', 'True')

            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.token('True')
            @α.option
            def _(ctx: Ctx) -> Any:
                ctx.token('False')

    @tatsu.rule
    def none(self, ctx: Ctx) -> Any:
        ctx.token('None')

    @tatsu.rule('EOF')
    def eof(self, ctx: Ctx) -> Any:
        ctx.token('$')
        ctx.cut()

    @tatsu.rule('EOL')
    def eol(self, ctx: Ctx) -> Any:
        ctx.token('$->')

    @tatsu.rule
    def value(self, ctx: Ctx) -> Any:
        with ctx.choice() as α:
            α.expecting(
              '"',
              "'",
              '-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?',
              'false',
              'null',
              '→number',
              '→string',
              'true'
            )

            @α.option
            def _(ctx: Ctx) -> Any:
                self.string(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.number(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.true(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.false(ctx)
            @α.option
            def _(ctx: Ctx) -> Any:
                self.null(ctx)

    @tatsu.rule
    def number(self, ctx: Ctx) -> Any:
        ctx.pattern(r'-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?')

    @tatsu.rule
    def true(self, ctx: Ctx) -> Any:
        ctx.token('true')

    @tatsu.rule
    def false(self, ctx: Ctx) -> Any:
        ctx.token('false')

    @tatsu.rule
    def null(self, ctx: Ctx) -> Any:
        ctx.token('null')


def main(filename, **kwargs):
    if not filename or filename == '-':
        import sys

        text = sys.stdin.read()
    else:
        import pathlib

        text = pathlib.Path(filename).read_text()

    parser = TatSuBootstrapParser()
    return parser.parse(text, filename=filename, **kwargs)


if __name__ == '__main__':
    import json
    from tatsu.parsing import generic_main
    from tatsu.util import asjson

    ast = generic_main(main, TatSuBootstrapParser, name='TatSuBootstrap')
    data = asjson(ast)
    print(json.dumps(data, indent=2))
