#!/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 = {
    'and',
    'not',
    'or',
}  # type: ignore


class BreakerDslBuffer(Buffer):
    def __init__(
        self,
        text,
        whitespace=' ',
        nameguard=None,
        comments_re=None,
        eol_comments_re=None,
        ignorecase=None,
        namechars='',
        **kwargs
    ):
        super(BreakerDslBuffer, self).__init__(
            text,
            whitespace=whitespace,
            nameguard=nameguard,
            comments_re=comments_re,
            eol_comments_re=eol_comments_re,
            ignorecase=ignorecase,
            namechars=namechars,
            **kwargs
        )


class BreakerDslParser(Parser):
    def __init__(
        self,
        whitespace=' ',
        nameguard=None,
        comments_re=None,
        eol_comments_re=None,
        ignorecase=None,
        left_recursion=True,
        parseinfo=True,
        keywords=None,
        namechars='',
        buffer_class=BreakerDslBuffer,
        **kwargs
    ):
        if keywords is None:
            keywords = KEYWORDS
        super(BreakerDslParser, 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 _or_(self):  # noqa
        self._token('|')

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

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

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

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

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

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

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

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

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

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

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

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

    @tatsumasu('float')
    def _float_(self):  # noqa
        self._pattern(r'\d+\.\d+')

    @tatsumasu('Name')
    def _name_(self):  # noqa
        self._pattern(r'[a-zA-z_][a-zA-z0-9_]*')
        self.name_last_node('data')
        self._check_name()
        self.ast._define(
            ['data'],
            []
        )

    @tatsumasu('Method')
    def _method_(self):  # noqa
        self._dot_()
        self._name_()
        self.name_last_node('name')
        self.ast._define(
            ['name'],
            []
        )

    @tatsumasu('LambdaExpr')
    def _lambda_(self):  # noqa
        self._wildcard_()

        def block1():
            self._method_()
        self._positive_closure(block1)
        self.name_last_node('methods')
        self.ast._define(
            ['methods'],
            []
        )

    @tatsumasu()
    def _arg_(self):  # noqa
        with self._choice():
            with self._option():
                self._lambda_()
            with self._option():
                self._name_()
            self._error('no available options')

    @tatsumasu('Cond')
    def _cond_(self):  # noqa
        self._name_()
        self.name_last_node('name')
        self._lpar_()

        def sep1():
            with self._group():
                self._comma_()

        def block1():
            self._arg_()
            self.name_last_node('args')
        self._positive_gather(block1, sep1)
        self._rpar_()
        self.ast._define(
            ['args', 'name'],
            []
        )

    @tatsumasu('CondStrict')
    def _condStrict_(self):  # noqa
        self._name_()
        self.name_last_node('name')
        self.ast._define(
            ['name'],
            []
        )

    @tatsumasu('OrCond')
    def _orCond_(self):  # noqa
        self._expr_()
        self.name_last_node('left')
        self._or_()
        self._expr_()
        self.name_last_node('right')
        self.ast._define(
            ['left', 'right'],
            []
        )

    @tatsumasu('AndCond')
    def _andCond_(self):  # noqa
        self._expr_()
        self.name_last_node('left')
        self._and_()
        self._expr_()
        self.name_last_node('right')
        self.ast._define(
            ['left', 'right'],
            []
        )

    @tatsumasu('NotCond')
    def _notExpr_(self):  # noqa
        self._not_()
        self._expr_()
        self.name_last_node('expr')
        self.ast._define(
            ['expr'],
            []
        )

    @tatsumasu()
    def _compoundExpr_(self):  # noqa
        with self._choice():
            with self._option():
                self._orCond_()
            with self._option():
                self._andCond_()
            with self._option():
                self._notExpr_()
            self._error('no available options')

    @tatsumasu()
    def _parensExpr_(self):  # noqa
        self._lpar_()
        self._expr_()
        self.name_last_node('@')
        self._rpar_()

    @tatsumasu('Prio')
    def _prio_(self):  # noqa
        self._float_()
        self.name_last_node('value')
        self.ast._define(
            ['value'],
            []
        )

    @tatsumasu('PrioCond')
    def _prioCond_(self):  # noqa
        self._prio_()
        self.name_last_node('prio')
        self._at_()
        self._expr_()
        self.name_last_node('expr')
        self.ast._define(
            ['expr', 'prio'],
            []
        )

    @tatsumasu()
    def _expr_(self):  # noqa
        with self._choice():
            with self._option():
                self._prioCond_()
            with self._option():
                self._parensExpr_()
            with self._option():
                self._compoundExpr_()
            with self._option():
                self._cond_()
            with self._option():
                self._condStrict_()
            with self._option():
                self._prio_()
            self._error('no available options')

    @tatsumasu()
    def _side_(self):  # noqa
        with self._choice():
            with self._option():
                self._before_()
            with self._option():
                self._after_()
            self._error('no available options')

    @tatsumasu('Side')
    def _sideExpr_(self):  # noqa
        self._side_()
        self.name_last_node('side')
        self._colon_()
        self._expr_()
        self.name_last_node('expr')
        self.ast._define(
            ['expr', 'side'],
            []
        )

    @tatsumasu('Top')
    def _top_(self):  # noqa

        def sep0():
            with self._group():
                self._plus_()

        def block0():
            self._sideExpr_()
            self.name_last_node('sides')
        self._positive_gather(block0, sep0)
        self.ast._define(
            ['sides'],
            []
        )


class BreakerDslSemantics(object):
    def or_(self, ast):  # noqa
        return ast

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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


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

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