#!/usr/bin/env python3

# WARNING: 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.

# ruff: noqa: C405, COM812, I001, F401, PLR1702, PLC2801, SIM117

import sys
from pathlib import Path

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


KEYWORDS: set[str] = set()


class EBNFBootstrapBuffer(Buffer):
    def __init__(self, text, /, config: ParserConfig | None = None, **settings):
        config = ParserConfig.new(
            config,
            owner=self,
            whitespace='(?m)\\s+',
            nameguard=None,
            ignorecase=False,
            namechars='',
            parseinfo=True,
            comments='(?sm)[(][*](?:.|\\n)*?[*][)]',
            eol_comments='(?sm)*#[^\\n]*$',
            keywords=KEYWORDS,
            start='start',
        )
        config = config.replace(**settings)

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


class EBNFBootstrapParser(Parser):
    def __init__(self, /, config: ParserConfig | None = None, **settings):
        config = ParserConfig.new(
            config,
            owner=self,
            whitespace='\\s+',
            nameguard=None,
            ignorecase=False,
            namechars='',
            parseinfo=True,
            comments='(?sm)[(][*](?:.|\\n)*?[*][)]',
            eol_comments='(?m)#[^\\n]*$',
            keywords=KEYWORDS,
            start='start',
        )
        config = config.replace(**settings)

        super().__init__(config=config)

    @tatsumasu()
    def _start_(self):
        self._grammar_()

    @tatsumasu('Grammar')
    def _grammar_(self):
        self._constant('TATSU')
        self.name_last_node('title')

        def block0():
            with self._choice():
                with self._option():
                    self._directive_()
                    self.add_last_node_to_name('directives')
                with self._option():
                    self._keyword_()
                    self.add_last_node_to_name('keywords')
                self._error(
                    'expecting one of: '
                    '<directive> <keyword>'
                )
        self._closure(block0)
        self._rule_()
        self.add_last_node_to_name('rules')

        def block1():
            with self._choice():
                with self._option():
                    self._rule_()
                    self.add_last_node_to_name('rules')
                with self._option():
                    self._keyword_()
                    self.add_last_node_to_name('keywords')
                self._error(
                    'expecting one of: '
                    '<keyword> <rule>'
                )
        self._closure(block1)
        self._check_eof()
        self._define(
            ['title'],
            ['directives', 'keywords', 'rules'],
        )

    @tatsumasu()
    def _directive_(self):
        self._token('@@')
        with self._ifnot():
            self._token('keyword')
        self._cut()
        with self._group():
            with self._choice():
                with self._option():
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._token('comments')
                            with self._option():
                                self._token('eol_comments')
                            self._error(
                                'expecting one of: '
                                "'comments' 'eol_comments'"
                            )
                    self.name_last_node('name')
                    self._cut()
                    self._cut()
                    self._token('::')
                    self._cut()
                    self._regex_()
                    self.name_last_node('value')
                    self._define(['name', 'value'], [])
                with self._option():
                    with self._group():
                        self._token('whitespace')
                    self.name_last_node('name')
                    self._cut()
                    self._cut()
                    self._token('::')
                    self._cut()
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._regex_()
                            with self._option():
                                self._string_()
                            with self._option():
                                self._token('None')
                            with self._option():
                                self._token('False')
                            with self._option():
                                self._constant('None')
                            self._error(
                                'expecting one of: '
                                "'False' 'None' <regex> <string>"
                            )
                    self.name_last_node('value')
                    self._define(['name', 'value'], [])
                with self._option():
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._token('nameguard')
                            with self._option():
                                self._token('ignorecase')
                            with self._option():
                                self._token('left_recursion')
                            with self._option():
                                self._token('parseinfo')
                            self._error(
                                'expecting one of: '
                                "'ignorecase' 'left_recursion'"
                                "'nameguard' 'parseinfo'"
                            )
                    self.name_last_node('name')
                    self._cut()
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._token('::')
                                self._cut()
                                self._boolean_()
                                self.name_last_node('value')
                                self._define(['value'], [])
                            with self._option():
                                self._constant(True)
                                self.name_last_node('value')
                            self._error(
                                'expecting one of: '
                                "'::'"
                            )
                    self._define(['name', 'value'], [])
                with self._option():
                    with self._group():
                        self._token('grammar')
                    self.name_last_node('name')
                    self._cut()
                    self._token('::')
                    self._cut()
                    self._word_()
                    self.name_last_node('value')
                    self._define(['name', 'value'], [])
                with self._option():
                    with self._group():
                        self._token('namechars')
                    self.name_last_node('name')
                    self._cut()
                    self._token('::')
                    self._cut()
                    self._string_()
                    self.name_last_node('value')
                    self._define(['name', 'value'], [])
                self._error(
                    'expecting one of: '
                    "'comments' 'eol_comments' 'grammar'"
                    "'ignorecase' 'left_recursion'"
                    "'namechars' 'nameguard' 'parseinfo'"
                    "'whitespace'"
                )
        self._cut()
        self._define(['name', 'value'], [])

    @tatsumasu()
    def _keywords_(self):

        def block0():
            self._keywords_()
        self._positive_closure(block0)

    @tatsumasu()
    def _keyword_(self):
        self._token('@@keyword')
        self._cut()
        self._token('::')
        self._cut()

        def block0():
            with self._group():
                with self._choice():
                    with self._option():
                        self._word_()
                    with self._option():
                        self._string_()
                    self._error(
                        'expecting one of: '
                        '<string> <word>'
                    )
            self.add_last_node_to_name('@')
            with self._ifnot():
                with self._group():
                    with self._choice():
                        with self._option():
                            self._token(':')
                        with self._option():
                            self._token('=')
                        self._error(
                            'expecting one of: '
                            "':' '='"
                        )
        self._closure(block0)

    @tatsumasu()
    def _paramdef_(self):
        with self._choice():
            with self._option():
                self._token('::')
                self._cut()
                self._params_()
                self.name_last_node('params')
                self._define(['params'], [])
            with self._option():
                self._token('(')
                self._cut()
                with self._group():
                    with self._choice():
                        with self._option():
                            self._kwparams_()
                            self.name_last_node('kwparams')
                        with self._option():
                            self._params_()
                            self.name_last_node('params')
                            self._token(',')
                            self._cut()
                            self._kwparams_()
                            self.name_last_node('kwparams')
                            self._define(['kwparams', 'params'], [])
                        with self._option():
                            self._params_()
                            self.name_last_node('params')
                        self._error(
                            'expecting one of: '
                            '<kwparams> <params>'
                        )
                self._token(')')
                self._define(['kwparams', 'params'], [])
            self._error(
                'expecting one of: '
                "'(' '::'"
            )

    @tatsumasu('Rule')
    def _rule_(self):

        def block0():
            self._decorator_()
        self._closure(block0)
        self.name_last_node('decorators')
        self._name_()
        self.name_last_node('name')
        self._cut()
        with self._optional():
            with self._choice():
                with self._option():
                    self._token('::')
                    self._cut()
                    self._params_()
                    self.name_last_node('params')
                    self._define(['params'], [])
                with self._option():
                    self._token('(')
                    self._cut()
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._kwparams_()
                                self.name_last_node('kwparams')
                            with self._option():
                                self._params_()
                                self.name_last_node('params')
                                self._token(',')
                                self._cut()
                                self._kwparams_()
                                self.name_last_node('kwparams')
                                self._define(['kwparams', 'params'], [])
                            with self._option():
                                self._params_()
                                self.name_last_node('params')
                            self._error(
                                'expecting one of: '
                                '<kwparams> <params>'
                            )
                    self._token(')')
                    self._define(['kwparams', 'params'], [])
                self._error(
                    'expecting one of: '
                    "'(' '::'"
                )
        with self._optional():
            self._token('<')
            self._cut()
            self._known_name_()
            self.name_last_node('base')
            self._define(['base'], [])
        self._token('=')
        self._cut()
        self._expre_()
        self.name_last_node('exp')
        self._token(';')
        self._cut()
        self._define(['base', 'decorators', 'exp', 'kwparams', 'name', 'params'], [])

    @tatsumasu()
    def _decorator_(self):
        self._token('@')
        with self._ifnot():
            self._token('@')
        self._cut()
        with self._group():
            with self._choice():
                with self._option():
                    self._token('override')
                with self._option():
                    self._token('name')
                with self._option():
                    self._token('nomemo')
                self._error(
                    'expecting one of: '
                    "'name' 'nomemo' 'override'"
                )
        self.name_last_node('@')

    @tatsumasu()
    def _params_(self):
        self._first_param_()
        self.add_last_node_to_name('@')

        def block0():
            self._token(',')
            self._literal_()
            self.add_last_node_to_name('@')
            with self._ifnot():
                self._token('=')
            self._cut()
        self._closure(block0)

    @tatsumasu()
    def _first_param_(self):
        with self._choice():
            with self._option():
                self._path_()
            with self._option():
                self._literal_()
            self._error(
                'expecting one of: '
                '(?!\\d)\\w+(?:::(?!\\d)\\w+)+ <boolean>'
                '<float> <hex> <int> <literal> <null>'
                '<path> <raw_string> <string> <word>'
            )

    @tatsumasu()
    def _kwparams_(self):

        def sep0():
            self._token(',')

        def block1():
            self._pair_()
        self._positive_gather(block1, sep0)

    @tatsumasu()
    def _pair_(self):
        self._word_()
        self.add_last_node_to_name('@')
        self._token('=')
        self._cut()
        self._literal_()
        self.add_last_node_to_name('@')

    @tatsumasu()
    def _expre_(self):
        with self._choice():
            with self._option():
                self._choice_()
            with self._option():
                self._sequence_()
            self._error(
                'expecting one of: '
                "'|' <choice> <element> <option>"
                '<sequence>'
            )

    @tatsumasu('Choice')
    def _choice_(self):
        with self._optional():
            self._token('|')
            self._cut()
        self._option_()
        self.add_last_node_to_name('@')

        def block0():
            self._token('|')
            self._cut()
            self._option_()
            self.add_last_node_to_name('@')
        self._positive_closure(block0)

    @tatsumasu('Option')
    def _option_(self):
        self._sequence_()
        self.name_last_node('@')

    @tatsumasu('Sequence')
    def _sequence_(self):

        def block0():
            self._element_()
        self._positive_closure(block0)
        self.name_last_node('sequence')

    @tatsumasu()
    def _element_(self):
        with self._choice():
            with self._option():
                self._rule_include_()
            with self._option():
                self._named_()
            with self._option():
                self._override_()
            with self._option():
                self._term_()
            self._error(
                'expecting one of: '
                "'>' <atom> <closure> <empty_closure>"
                '<gather> <group> <join> <left_join>'
                '<lookahead> <named> <named_list>'
                '<named_single> <negative_lookahead>'
                '<optional> <override> <override_list>'
                '<override_single>'
                '<override_single_deprecated>'
                '<positive_closure> <right_join>'
                '<rule_include> <skip_to> <special>'
                '<term> <void>'
            )

    @tatsumasu('RuleInclude')
    def _rule_include_(self):
        self._token('>')
        self._cut()
        self._known_name_()
        self.name_last_node('@')

    @tatsumasu()
    def _named_(self):
        with self._choice():
            with self._option():
                self._named_list_()
            with self._option():
                self._named_single_()
            self._error(
                'expecting one of: '
                '<name> <named_list> <named_single>'
            )

    @tatsumasu('NamedList')
    def _named_list_(self):
        self._name_()
        self.name_last_node('name')
        self._token('+:')
        self._cut()
        self._term_()
        self.name_last_node('exp')
        self._define(['exp', 'name'], [])

    @tatsumasu('Named')
    def _named_single_(self):
        self._name_()
        self.name_last_node('name')
        self._token(':')
        self._cut()
        self._term_()
        self.name_last_node('exp')
        self._define(['exp', 'name'], [])

    @tatsumasu()
    def _override_(self):
        with self._choice():
            with self._option():
                self._override_list_()
            with self._option():
                self._override_single_()
            with self._option():
                self._override_single_deprecated_()
            self._error(
                'expecting one of: '
                "'@' '@+:' '@:' <override_list>"
                '<override_single>'
                '<override_single_deprecated>'
            )

    @tatsumasu('OverrideList')
    def _override_list_(self):
        self._token('@+:')
        self._cut()
        self._term_()
        self.name_last_node('@')

    @tatsumasu('Override')
    def _override_single_(self):
        self._token('@:')
        self._cut()
        self._term_()
        self.name_last_node('@')

    @tatsumasu('Override')
    def _override_single_deprecated_(self):
        self._token('@')
        self._cut()
        self._term_()
        self.name_last_node('@')

    @tatsumasu()
    def _term_(self):
        with self._choice():
            with self._option():
                self._void_()
            with self._option():
                self._gather_()
            with self._option():
                self._join_()
            with self._option():
                self._left_join_()
            with self._option():
                self._right_join_()
            with self._option():
                self._group_()
            with self._option():
                self._empty_closure_()
            with self._option():
                self._positive_closure_()
            with self._option():
                self._closure_()
            with self._option():
                self._optional_()
            with self._option():
                self._special_()
            with self._option():
                self._skip_to_()
            with self._option():
                self._lookahead_()
            with self._option():
                self._negative_lookahead_()
            with self._option():
                self._atom_()
            self._error(
                'expecting one of: '
                "'!' '&' '(' '()' '->' '?(' '[' '{'"
                '<alert> <atom> <call> <closure>'
                '<constant> <cut> <cut_deprecated>'
                '<empty_closure> <eof> <gather> <group>'
                '<join> <left_join> <lookahead>'
                '<negative_lookahead> <optional>'
                '<pattern> <positive_closure>'
                '<right_join> <separator> <skip_to>'
                '<special> <token> <void>'
            )

    @tatsumasu('Group')
    def _group_(self):
        self._token('(')
        self._cut()
        self._expre_()
        self.name_last_node('exp')
        self._token(')')
        self._cut()
        self._define(['exp'], [])

    @tatsumasu()
    def _gather_(self):
        with self._if():
            with self._group():
                self._separator_()
                self._token('.{')
        self._cut()
        with self._group():
            with self._choice():
                with self._option():
                    self._positive_gather_()
                with self._option():
                    self._normal_gather_()
                self._error(
                    'expecting one of: '
                    '<normal_gather> <positive_gather>'
                )

    @tatsumasu('PositiveGather')
    def _positive_gather_(self):
        self._separator_()
        self.name_last_node('sep')
        self._token('.{')
        self._expre_()
        self.name_last_node('exp')
        self._token('}')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('+')
                with self._option():
                    self._token('-')
                self._error(
                    'expecting one of: '
                    "'+' '-'"
                )
        self._cut()
        self._define(['exp', 'sep'], [])

    @tatsumasu('Gather')
    def _normal_gather_(self):
        self._separator_()
        self.name_last_node('sep')
        self._token('.{')
        self._cut()
        self._expre_()
        self.name_last_node('exp')
        self._token('}')
        with self._optional():
            self._token('*')
            self._cut()
        self._cut()
        self._define(['exp', 'sep'], [])

    @tatsumasu()
    def _join_(self):
        with self._if():
            with self._group():
                self._separator_()
                self._token('%{')
        self._cut()
        with self._group():
            with self._choice():
                with self._option():
                    self._positive_join_()
                with self._option():
                    self._normal_join_()
                self._error(
                    'expecting one of: '
                    '<normal_join> <positive_join>'
                )

    @tatsumasu('PositiveJoin')
    def _positive_join_(self):
        self._separator_()
        self.name_last_node('sep')
        self._token('%{')
        self._expre_()
        self.name_last_node('exp')
        self._token('}')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('+')
                with self._option():
                    self._token('-')
                self._error(
                    'expecting one of: '
                    "'+' '-'"
                )
        self._cut()
        self._define(['exp', 'sep'], [])

    @tatsumasu('Join')
    def _normal_join_(self):
        self._separator_()
        self.name_last_node('sep')
        self._token('%{')
        self._cut()
        self._expre_()
        self.name_last_node('exp')
        self._token('}')
        with self._optional():
            self._token('*')
            self._cut()
        self._cut()
        self._define(['exp', 'sep'], [])

    @tatsumasu('LeftJoin')
    def _left_join_(self):
        self._separator_()
        self.name_last_node('sep')
        self._token('<{')
        self._cut()
        self._expre_()
        self.name_last_node('exp')
        self._token('}')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('+')
                with self._option():
                    self._token('-')
                self._error(
                    'expecting one of: '
                    "'+' '-'"
                )
        self._cut()
        self._define(['exp', 'sep'], [])

    @tatsumasu('RightJoin')
    def _right_join_(self):
        self._separator_()
        self.name_last_node('sep')
        self._token('>{')
        self._cut()
        self._expre_()
        self.name_last_node('exp')
        self._token('}')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('+')
                with self._option():
                    self._token('-')
                self._error(
                    'expecting one of: '
                    "'+' '-'"
                )
        self._cut()
        self._define(['exp', 'sep'], [])

    @tatsumasu()
    def _separator_(self):
        with self._choice():
            with self._option():
                self._group_()
            with self._option():
                self._token_()
            with self._option():
                self._constant_()
            with self._option():
                self._any_()
            with self._option():
                self._pattern_()
            self._error(
                'expecting one of: '
                "'(' '/./' '`' <any> <constant> <group>"
                '<pattern> <raw_string> <regexes>'
                '<string> <token>'
            )

    @tatsumasu('PositiveClosure')
    def _positive_closure_(self):
        self._token('{')
        self._expre_()
        self.name_last_node('@')
        self._token('}')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('-')
                with self._option():
                    self._token('+')
                self._error(
                    'expecting one of: '
                    "'+' '-'"
                )
        self._cut()

    @tatsumasu('Closure')
    def _closure_(self):
        self._token('{')
        self._expre_()
        self.name_last_node('@')
        self._token('}')
        with self._optional():
            self._token('*')
        self._cut()

    @tatsumasu('EmptyClosure')
    def _empty_closure_(self):
        self._token('{')
        self._void()
        self.name_last_node('@')
        self._token('}')

    @tatsumasu('Optional')
    def _optional_(self):
        self._token('[')
        self._cut()
        self._expre_()
        self.name_last_node('@')
        self._token(']')
        self._cut()

    @tatsumasu('Special')
    def _special_(self):
        self._token('?(')
        self._cut()
        self._pattern('.*?(?!\\)\\?)')
        self.name_last_node('@')
        self._token(')?')
        self._cut()

    @tatsumasu('Lookahead')
    def _lookahead_(self):
        self._token('&')
        self._cut()
        self._term_()
        self.name_last_node('@')

    @tatsumasu('NegativeLookahead')
    def _negative_lookahead_(self):
        self._token('!')
        self._cut()
        self._term_()
        self.name_last_node('@')

    @tatsumasu('SkipTo')
    def _skip_to_(self):
        self._token('->')
        self._cut()
        self._term_()
        self.name_last_node('@')

    @tatsumasu()
    def _atom_(self):
        with self._choice():
            with self._option():
                self._cut_()
            with self._option():
                self._cut_deprecated_()
            with self._option():
                self._token_()
            with self._option():
                self._alert_()
            with self._option():
                self._constant_()
            with self._option():
                self._call_()
            with self._option():
                self._pattern_()
            with self._option():
                self._eof_()
            self._error(
                'expecting one of: '
                "'$' '>>' '`' '~' <alert> <call>"
                '<constant> <cut> <cut_deprecated> <eof>'
                '<pattern> <raw_string> <regexes>'
                '<string> <token> <word> \\^+'
            )

    @tatsumasu('RuleRef')
    def _call_(self):
        self._word_()

    @tatsumasu('Void')
    def _void_(self):
        self._token('()')
        self._cut()

    @tatsumasu('Cut')
    def _cut_(self):
        self._token('~')
        self._cut()

    @tatsumasu('Cut')
    def _cut_deprecated_(self):
        self._token('>>')
        self._cut()

    @tatsumasu()
    def _known_name_(self):
        self._name_()
        self._cut()

    @tatsumasu()
    def _name_(self):
        self._word_()

    @tatsumasu('Constant')
    def _constant_(self):
        with self._if():
            self._token('`')
        with self._group():
            with self._choice():
                with self._option():
                    self._pattern('(?ms)```((?:.|\\n)*?)```')
                with self._option():
                    self._token('`')
                    self._literal_()
                    self.name_last_node('@')
                    self._token('`')
                with self._option():
                    self._pattern('`(.*?)`')
                self._error(
                    'expecting one of: '
                    "'`' (?ms)```((?:.|\\n)*?)``` `(.*?)`"
                )

    @tatsumasu('Alert')
    def _alert_(self):
        self._pattern('\\^+')
        self.name_last_node('level')
        self._constant_()
        self.name_last_node('message')
        self._define(['level', 'message'], [])

    @tatsumasu('Token')
    def _token_(self):
        with self._choice():
            with self._option():
                self._string_()
            with self._option():
                self._raw_string_()
            self._error(
                'expecting one of: '
                '<STRING> <raw_string> <string> r'
            )

    @tatsumasu()
    def _literal_(self):
        with self._choice():
            with self._option():
                self._string_()
            with self._option():
                self._raw_string_()
            with self._option():
                self._boolean_()
            with self._option():
                self._word_()
            with self._option():
                self._hex_()
            with self._option():
                self._float_()
            with self._option():
                self._int_()
            with self._option():
                self._null_()
            self._error(
                'expecting one of: '
                "'False' 'None' 'True' (?!\\d)\\w+"
                '0[xX](?:\\d|[a-fA-F])+ <STRING> <boolean>'
                '<float> <hex> <int> <null> <raw_string>'
                '<string> <word> [-'
                '+]?(?:\\d+\\.\\d*|\\d*\\.\\d+)(?:[Ee][-'
                '+]?\\d+)? [-+]?\\d+ r'
            )

    @tatsumasu()
    def _string_(self):
        self._STRING_()

    @tatsumasu()
    def _raw_string_(self):
        self._pattern('r')
        self._STRING_()
        self.name_last_node('@')

    @tatsumasu()
    def _STRING_(self):
        with self._choice():
            with self._option():
                self._pattern('"((?:[^"\\n]|\\\\"|\\\\\\\\)*?)"')
                self.name_last_node('@')
                self._cut()
            with self._option():
                self._pattern("'((?:[^'\\n]|\\\\'|\\\\\\\\)*?)'")
                self.name_last_node('@')
                self._cut()
            self._error(
                'expecting one of: '
                '"((?:[^"\\n]|\\"|\\\\)*?)"'
                "'((?:[^'\\n]|\\'|\\\\)*?)'"
            )

    @tatsumasu()
    def _hex_(self):
        self._pattern('0[xX](?:\\d|[a-fA-F])+')

    @tatsumasu()
    def _float_(self):
        self._pattern('[-+]?(?:\\d+\\.\\d*|\\d*\\.\\d+)(?:[Ee][-+]?\\d+)?')

    @tatsumasu()
    def _int_(self):
        self._pattern('[-+]?\\d+')

    @tatsumasu()
    def _path_(self):
        self._pattern('(?!\\d)\\w+(?:::(?!\\d)\\w+)+')

    @tatsumasu()
    def _word_(self):
        self._pattern('(?!\\d)\\w+')

    @tatsumasu('Any')
    def _any_(self):
        self._token('/./')

    @tatsumasu('Pattern')
    def _pattern_(self):
        self._regexes_()

    @tatsumasu()
    def _regexes_(self):

        def sep0():
            self._token('+')

        def block1():
            self._regex_()
        self._positive_gather(block1, sep0)

    @tatsumasu()
    def _regex_(self):
        with self._choice():
            with self._option():
                self._token('/')
                self._cut()
                self._pattern('(?:[^/\\\\]|\\\\/|\\\\.)*')
                self.name_last_node('@')
                self._token('/')
                self._cut()
            with self._option():
                self._token('?/')
                self._cut()
                self._pattern('(?:.|\\n)*?(?=/\\?)')
                self.name_last_node('@')
                self._pattern('/\\?+')
                self._cut()
            with self._option():
                self._token('?')
                self._STRING_()
                self.name_last_node('@')
            self._error(
                'expecting one of: '
                "'/' '?' '?/'"
            )

    @tatsumasu()
    def _boolean_(self):
        with self._choice():
            with self._option():
                self._token('True')
            with self._option():
                self._token('False')
            self._error(
                'expecting one of: '
                "'False' 'True'"
            )

    @tatsumasu()
    def _null_(self):
        self._token('None')

    @tatsumasu('EOF')
    def _eof_(self):
        self._token('$')
        self._cut()


def main(filename, **kwargs):
    if not filename or filename == '-':
        text = sys.stdin.read()
    else:
        text = Path(filename).read_text()
    parser = EBNFBootstrapParser()
    return parser.parse(
        text,
        filename=filename,
        **kwargs,
    )


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

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