#!/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 TextGrammarBuffer(Buffer):
    def __init__(self, text, /, config: ParserConfig = None, **settings):
        config = ParserConfig.new(
            config,
            owner=self,
            whitespace=re.compile('[\\t ]+'),
            nameguard=None,
            comments_re=None,
            eol_comments_re='^(#.*|\\s*)\\n',
            ignorecase=False,
            namechars='',
            parseinfo=False,
        )
        config = config.replace(**settings)
        super().__init__(text, config=config)


class TextGrammarParser(Parser):
    def __init__(self, /, config: ParserConfig = None, **settings):
        config = ParserConfig.new(
            config,
            owner=self,
            whitespace=re.compile('[\\t ]+'),
            nameguard=None,
            comments_re=None,
            eol_comments_re='^(#.*|\\s*)\\n',
            ignorecase=False,
            namechars='',
            parseinfo=False,
            keywords=KEYWORDS,
            start='start',
        )
        config = config.replace(**settings)
        super().__init__(config=config)

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

    @tatsumasu()
    def _symbol_(self):  # noqa
        self._pattern('[\\w()/!<>-]+')

    @tatsumasu()
    def _literal_(self):  # noqa
        self._pattern('((?:[^;|<>\\n\\[\\]()]|\\[[^\\[\\]]*\\]|\\([^()]*\\))+(?<!\\s))')

    @tatsumasu('Literal')
    def _literalAlternative_(self):  # noqa
        self._literal_()
        self.name_last_node('value')

    @tatsumasu('AdjectiveNoun')
    def _adjectiveNoun_(self):  # noqa
        self._literal_()
        self.name_last_node('adjective')
        self._token('|')
        self._literal_()
        self.name_last_node('noun')

        self._define(
            ['adjective', 'noun'],
            []
        )

    @tatsumasu()
    def _entity_(self):  # noqa
        with self._choice():
            with self._option():
                self._adjectiveNoun_()
            with self._option():
                self._literalAlternative_()
            self._error(
                'expecting one of: '
                '((?:[^;|<>\\n\\[\\]()]|\\[[^\\[\\]]*\\]|\\([^()]'
                '*\\))+(?<!\\s)) <adjectiveNoun> <literal>'
                '<literalAlternative>'
            )

    @tatsumasu('Match')
    def _match_(self):  # noqa
        self._entity_()
        self.name_last_node('lhs')
        self._token('<->')
        self._entity_()
        self.name_last_node('rhs')

        self._define(
            ['lhs', 'rhs'],
            []
        )

    @tatsumasu()
    def _alternative_(self):  # noqa
        with self._choice():
            with self._option():
                self._match_()
            with self._option():
                self._entity_()
            with self._option():
                self._void()
            self._error(
                'expecting one of: '
                '((?:[^;|<>\\n\\[\\]()]|\\[[^\\[\\]]*\\]|\\([^()]'
                '*\\))+(?<!\\s)) <adjectiveNoun> <entity>'
                '<literal> <literalAlternative> <match>'
            )

    @tatsumasu()
    def _alternatives_(self):  # noqa

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

        def block0():
            self._alternative_()
        self._positive_gather(block0, sep0)

    @tatsumasu('ProductionRule')
    def _productionRule_(self):  # noqa
        self._symbol_()
        self.name_last_node('symbol')
        self._token(':')
        self._alternatives_()
        self.name_last_node('alternatives')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('\n')
                with self._option():
                    self._check_eof()
                self._error(
                    'expecting one of: '
                    "'\\n'"
                )

        self._define(
            ['alternatives', 'symbol'],
            []
        )

    @tatsumasu('TextGrammar')
    def _grammar_(self):  # noqa

        def block1():
            self._productionRule_()
        self._closure(block1)
        self.name_last_node('rules')
        self._check_eof()

        self._define(
            ['rules'],
            []
        )


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

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

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

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

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

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

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

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

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

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

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


def main(filename, **kwargs):
    if not filename or filename == '-':
        text = sys.stdin.read()
    else:
        with open(filename) as f:
            text = f.read()
    parser = TextGrammarParser()
    return parser.parse(
        text,
        filename=filename,
        **kwargs
    )


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

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