#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 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 print_function, division, absolute_import, unicode_literals

from tatsu.buffering import Buffer
from tatsu.parsing import Parser
from tatsu.parsing import tatsumasu
from tatsu.util import re, generic_main  # noqa


KEYWORDS = {}  # type: ignore


class AbleBuffer(Buffer):
    def __init__(
        self,
        text,
        whitespace=None,
        nameguard=None,
        comments_re=None,
        eol_comments_re='#([^\\n]*?)$',
        ignorecase=None,
        namechars='',
        **kwargs
    ):
        super(AbleBuffer, self).__init__(
            text,
            whitespace=whitespace,
            nameguard=nameguard,
            comments_re=comments_re,
            eol_comments_re=eol_comments_re,
            ignorecase=ignorecase,
            namechars=namechars,
            **kwargs
        )


class AbleParser(Parser):
    def __init__(
        self,
        whitespace=None,
        nameguard=None,
        comments_re=None,
        eol_comments_re='#([^\\n]*?)$',
        ignorecase=None,
        left_recursion=True,
        parseinfo=True,
        keywords=None,
        namechars='',
        buffer_class=AbleBuffer,
        **kwargs
    ):
        if keywords is None:
            keywords = KEYWORDS
        super(AbleParser, self).__init__(
            whitespace=whitespace,
            nameguard=nameguard,
            comments_re=comments_re,
            eol_comments_re=eol_comments_re,
            ignorecase=ignorecase,
            left_recursion=left_recursion,
            parseinfo=parseinfo,
            keywords=keywords,
            namechars=namechars,
            buffer_class=buffer_class,
            **kwargs
        )

    @tatsumasu()
    def _start_(self):  # noqa
        self._implicit_list_()
        self.name_last_node('@')
        self._check_eof()

    @tatsumasu()
    def _sign_(self):  # noqa
        with self._choice():
            with self._option():
                self._token('+')
            with self._option():
                self._token('-')
            self._error('no available options')

    @tatsumasu()
    def _DECIMAL_(self):  # noqa
        self._token('.')

    @tatsumasu()
    def _DECIMAL_FRAGMENT_(self):  # noqa
        self._pattern(r'[0-9]+')

    @tatsumasu()
    def _HEX_FRAGMENT_(self):  # noqa
        self._pattern(r'[0-9a-fA-F]+')

    @tatsumasu()
    def _BINARY_FRAGMENT_(self):  # noqa
        self._pattern(r'[01]+')

    @tatsumasu()
    def _hex_prefix_(self):  # noqa
        with self._choice():
            with self._option():
                self._token('0x')
            with self._option():
                self._token('0X')
            self._error('no available options')

    @tatsumasu()
    def _binary_prefix_(self):  # noqa
        with self._choice():
            with self._option():
                self._token('0b')
            with self._option():
                self._token('0B')
            self._error('no available options')

    @tatsumasu()
    def _numeric_float_(self):  # noqa
        with self._optional():
            self._sign_()
        self._DECIMAL_FRAGMENT_()
        self._DECIMAL_()
        self._DECIMAL_FRAGMENT_()

    @tatsumasu()
    def _infinity_(self):  # noqa
        self._pattern(r'(?i)[+-]?inf(inity)?')

    @tatsumasu()
    def _float_(self):  # noqa
        with self._choice():
            with self._option():
                self._numeric_float_()
            with self._option():
                self._token('nan')
            with self._option():
                self._infinity_()
            self._error('no available options')

    @tatsumasu()
    def _hex_integer_(self):  # noqa
        with self._optional():
            self._sign_()
        self._hex_prefix_()
        self._HEX_FRAGMENT_()

    @tatsumasu()
    def _binary_integer_(self):  # noqa
        with self._optional():
            self._sign_()
        self._binary_prefix_()
        self._BINARY_FRAGMENT_()

    @tatsumasu()
    def _decimal_integer_(self):  # noqa
        with self._optional():
            self._sign_()
        self._DECIMAL_FRAGMENT_()

    @tatsumasu()
    def _number_(self):  # noqa
        with self._choice():
            with self._option():
                self._float_()
            with self._option():
                self._hex_integer_()
            with self._option():
                self._binary_integer_()
            with self._option():
                self._decimal_integer_()
            self._error('no available options')

    @tatsumasu()
    def _double_quoted_string_(self):  # noqa
        self._token('"')
        self._pattern(r'[^"]+')
        self.name_last_node('@')
        self._token('"')

    @tatsumasu()
    def _single_quoted_string_(self):  # noqa
        self._token("'")
        self._pattern(r"[^']+")
        self.name_last_node('@')
        self._token("'")

    @tatsumasu()
    def _string_(self):  # noqa
        with self._choice():
            with self._option():
                self._double_quoted_string_()
            with self._option():
                self._single_quoted_string_()
            self._error('no available options')

    @tatsumasu()
    def _pair_(self):  # noqa
        self._pattern(r'[\w]+')
        self.name_last_node('@')
        self._token(':')
        self._value_()
        self.name_last_node('@')

    @tatsumasu()
    def _value_(self):  # noqa
        with self._choice():
            with self._option():
                self._number_()
            with self._option():
                self._string_()
            with self._option():
                self._pair_()
            with self._option():
                self._list_()
            self._error('no available options')

    @tatsumasu()
    def _list_(self):  # noqa
        self._token('[')

        def block1():
            self._value_()
        self._closure(block1)
        self.name_last_node('@')
        self._token(']')

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

        def block0():
            self._value_()
        self._closure(block0)


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


def main(filename, startrule, **kwargs):
    with open(filename) as f:
        text = f.read()
    parser = AbleParser()
    return parser.parse(text, startrule, filename=filename, **kwargs)


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

    ast = generic_main(main, AbleParser, name='Able')
    print('AST:')
    print(ast)
    print()
    print('JSON:')
    print(json.dumps(asjson(ast), indent=2))
    print()
