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

# CAVEAT UTILITOR
#
# This file was automatically generated by Grako.
#
#    https://pypi.python.org/pypi/grako/
#
# 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 grako.buffering import Buffer
from grako.parsing import graken, Parser
from grako.util import re, RE_FLAGS, generic_main  # noqa


__all__ = [
    'CFGMarkupParser',
    'CFGMarkupSemantics',
    'main'
]

KEYWORDS = set([])


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


class CFGMarkupParser(Parser):
    def __init__(self,
                 whitespace=None,
                 nameguard=None,
                 comments_re=None,
                 eol_comments_re='#.*?$',
                 ignorecase=None,
                 left_recursion=True,
                 parseinfo=True,
                 keywords=KEYWORDS,
                 namechars='',
                 buffer_class=CFGMarkupBuffer,
                 **kwargs):
        super(CFGMarkupParser, 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
        )

    @graken()
    def _CFG_(self):

        def block1():
            self._named_production_()
            self._token(';')
        self._closure(block1)
        self.name_last_node('named_production_list')
        self.ast._define(
            ['named_production_list'],
            []
        )

    @graken()
    def _named_production_(self):
        self._symbol_()
        self.name_last_node('name')
        self._token('->')
        self._production_()
        self.name_last_node('production')
        self.ast._define(
            ['name', 'production'],
            []
        )

    @graken()
    def _production_(self):
        self._production_element_()
        self.name_last_node('head')

        def block2():
            self._token('|')
            self._production_element_()
        self._closure(block2)
        self.name_last_node('rest')
        self.ast._define(
            ['head', 'rest'],
            []
        )

    @graken()
    def _production_element_(self):
        with self._choice():
            with self._option():
                self._production_list_()
            with self._option():
                self._production_single_()
            self._error('no available options')

    @graken()
    def _production_list_(self):
        self._production_single_()
        self.name_last_node('head')

        def block2():
            self._production_single_()
        self._positive_closure(block2)
        self.name_last_node('rest')
        self.ast._define(
            ['head', 'rest'],
            []
        )

    @graken()
    def _production_single_(self):
        with self._choice():
            with self._option():
                self._reference_()
            with self._option():
                self._terminal_()
            self._error('no available options')

    @graken()
    def _terminal_(self):
        self._pattern(r'"')
        self._pattern(r'[^"]*')
        self.name_last_node('value')
        self._pattern(r'"')
        with self._optional():
            self._token('{')
            with self._optional():
                self._pattern(r'[^\}]*')
            self._token('}')
        self.name_last_node('features')
        self.ast._define(
            ['features', 'value'],
            []
        )

    @graken()
    def _reference_(self):
        self._symbol_()
        self.name_last_node('key')
        self.ast._define(
            ['key'],
            []
        )

    @graken()
    def _symbol_(self):
        self._pattern(r'[a-zA-Z0-9]+')


class CFGMarkupSemantics(object):
    def CFG(self, ast):
        return ast

    def named_production(self, ast):
        return ast

    def production(self, ast):
        return ast

    def production_element(self, ast):
        return ast

    def production_list(self, ast):
        return ast

    def production_single(self, ast):
        return ast

    def terminal(self, ast):
        return ast

    def reference(self, ast):
        return ast

    def symbol(self, ast):
        return ast


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

if __name__ == '__main__':
    import json
    ast = generic_main(main, CFGMarkupParser, name='CFGMarkup')
    print('AST:')
    print(ast)
    print()
    print('JSON:')
    print(json.dumps(ast, indent=2))
    print()
