#!/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.parsing import graken, Parser
from grako.util import re, RE_FLAGS


__version__ = (2015, 12, 26, 22, 15, 59, 5)

__all__ = [
    'BParser',
    'BSemantics',
    'main'
]


class BParser(Parser):
    def __init__(self,
                 whitespace=None,
                 nameguard=None,
                 comments_re='/\\*((?:[^\\*]|\\*[^/]|\\n)*?)\\*+/',
                 eol_comments_re=None,
                 ignorecase=None,
                 left_recursion=False,
                 **kwargs):
        super(BParser, self).__init__(
            whitespace=whitespace,
            nameguard=nameguard,
            comments_re=comments_re,
            eol_comments_re=eol_comments_re,
            ignorecase=ignorecase,
            left_recursion=left_recursion,
            **kwargs
        )

    @graken()
    def _program_(self):

        def block1():
            self._definition_()
            self._cut()
        self._closure(block1)
        self.ast['@'] = self.last_node
        self._check_eof()

    @graken()
    def _definition_(self):
        with self._choice():
            with self._option():
                self._simpledef_()
            with self._option():
                self._vectordef_()
            with self._option():
                self._functiondef_()
            self._error('no available options')

    @graken()
    def _simpledef_(self):
        self._name_()
        self.ast['name'] = self.last_node
        with self._optional():
            self._ival_()
        self.ast['init'] = self.last_node
        self._token(';')

        self.ast._define(
            ['name', 'init'],
            []
        )

    @graken()
    def _vectordef_(self):
        self._name_()
        self.ast['name'] = self.last_node
        self._token('[')
        with self._optional():
            self._constantexpr_()
            self.ast['maxidx'] = self.last_node
        self._token(']')
        with self._optional():
            self._ivallist_()
            self.ast['ivals'] = self.last_node
        self._token(';')

        self.ast._define(
            ['name', 'maxidx', 'ivals'],
            []
        )

    @graken()
    def _ivallist_(self):
        self._ival_()
        self.ast.setlist('@', self.last_node)

        def block1():
            self._token(',')
            self._ival_()
            self.ast.setlist('@', self.last_node)
        self._closure(block1)

    @graken()
    def _ival_(self):
        with self._choice():
            with self._option():
                self._numericexpr_()
            with self._option():
                self._characterexpr_()
            with self._option():
                self._stringexpr_()
            self._error('no available options')

    @graken()
    def _functiondef_(self):
        self._name_()
        self.ast['name'] = self.last_node
        self._token('(')
        with self._optional():
            self._namelist_()
            self.ast['args'] = self.last_node
        self._token(')')
        self._cut()
        self._statement_()
        self.ast['body'] = self.last_node

        self.ast._define(
            ['name', 'args', 'body'],
            []
        )

    @graken()
    def _statement_(self):
        with self._choice():
            with self._option():
                self._labelstatement_()
            with self._option():
                self._gotostatement_()
            with self._option():
                self._switchstatement_()
            with self._option():
                self._casestatement_()
            with self._option():
                self._breakstatement_()
            with self._option():
                self._autostatement_()
            with self._option():
                self._extrnstatement_()
            with self._option():
                self._compoundstatement_()
            with self._option():
                self._ifstatement_()
            with self._option():
                self._whilestatement_()
            with self._option():
                self._returnstatement_()
            with self._option():
                self._exprstatement_()
            with self._option():
                self._nullstatement_()
            self._error('no available options')

    @graken()
    def _labelstatement_(self):
        with self._ifnot():
            with self._group():
                self._token('default')
        self._name_()
        self.ast['label'] = self.last_node
        self._token(':')
        self._statement_()
        self.ast['statement'] = self.last_node

        self.ast._define(
            ['label', 'statement'],
            []
        )

    @graken()
    def _gotostatement_(self):
        self._token('goto')
        self._cut()
        self._name_()
        self.ast['label'] = self.last_node
        self._token(';')

        self.ast._define(
            ['label'],
            []
        )

    @graken()
    def _switchstatement_(self):
        self._token('switch')
        self._cut()
        self._expr_()
        self.ast['rvalue'] = self.last_node
        self._cut()
        self._statement_()
        self.ast['body'] = self.last_node

        self.ast._define(
            ['rvalue', 'body'],
            []
        )

    @graken()
    def _casestatement_(self):
        with self._group():
            with self._choice():
                with self._option():
                    with self._group():
                        self._token('case')
                        self._constantexpr_()
                        self.ast['cond'] = self.last_node
                with self._option():
                    self._token('default')
                self._error('expecting one of: default')
        self._cut()
        self._token(':')
        self._statement_()
        self.ast['then'] = self.last_node

        self.ast._define(
            ['cond', 'then'],
            []
        )

    @graken()
    def _breakstatement_(self):
        self._token('break')
        self._token(';')

    @graken()
    def _autostatement_(self):
        self._token('auto')
        self._cut()
        self._autovar_()
        self.ast.setlist('@', self.last_node)

        def block1():
            self._token(',')
            self._autovar_()
            self.ast.setlist('@', self.last_node)
        self._closure(block1)
        self._token(';')

    @graken()
    def _autovar_(self):
        self._name_()
        self.ast['name'] = self.last_node
        with self._optional():
            self._token('[')
            self._constantexpr_()
            self.ast['maxidx'] = self.last_node
            self._token(']')

        self.ast._define(
            ['name', 'maxidx'],
            []
        )

    @graken()
    def _extrnstatement_(self):
        self._token('extrn')
        self._cut()
        self._namelist_()
        self.ast['@'] = self.last_node
        self._token(';')

    @graken()
    def _compoundstatement_(self):
        self._token('{')
        self._cut()

        def block1():
            self._statement_()
            self._cut()
        self._closure(block1)
        self.ast['@'] = self.last_node
        self._token('}')

    @graken()
    def _ifstatement_(self):
        self._token('if')
        self._cut()
        self._token('(')
        self._expr_()
        self.ast['cond'] = self.last_node
        self._token(')')
        self._statement_()
        self.ast['then'] = self.last_node
        with self._optional():
            self._token('else')
            self._statement_()
            self.ast['otherwise'] = self.last_node

        self.ast._define(
            ['cond', 'then', 'otherwise'],
            []
        )

    @graken()
    def _whilestatement_(self):
        self._token('while')
        self._cut()
        self._token('(')
        self._expr_()
        self.ast['cond'] = self.last_node
        self._token(')')
        self._statement_()
        self.ast['body'] = self.last_node

        self.ast._define(
            ['cond', 'body'],
            []
        )

    @graken()
    def _returnstatement_(self):
        self._token('return')
        self._cut()
        with self._optional():
            self._token('(')
            self._expr_()
            self.ast['return_value'] = self.last_node
            self._token(')')
        self._token(';')

        self.ast._define(
            ['return_value'],
            []
        )

    @graken()
    def _exprstatement_(self):
        self._expr_()
        self.ast['@'] = self.last_node
        self._token(';')

    @graken()
    def _nullstatement_(self):
        self._token(';')

    @graken()
    def _expr_(self):
        self._assignexpr_()

    @graken()
    def _assignexpr_(self):
        self._condexpr_()
        self.ast['lhs'] = self.last_node
        with self._optional():
            self._assignop_()
            self.ast['op'] = self.last_node
            self._assignexpr_()
            self.ast['rhs'] = self.last_node

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

    @graken()
    def _assignop_(self):
        self._pattern(r'=([+\-/\*%&^|]|[=!]=|>[=>]?|<[=<]?)?')

    @graken()
    def _condexpr_(self):
        self._orexpr_()
        self.ast['cond'] = self.last_node
        with self._optional():
            self._token('?')
            self._condexpr_()
            self.ast['then'] = self.last_node
            self._token(':')
            self._condexpr_()
            self.ast['otherwise'] = self.last_node

        self.ast._define(
            ['cond', 'then', 'otherwise'],
            []
        )

    @graken()
    def _orexpr_(self):
        self._xorexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._ortail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _ortail_(self):
        self._token('|')
        self.ast['op'] = self.last_node
        self._xorexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _xorexpr_(self):
        self._andexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._xortail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _xortail_(self):
        self._token('^')
        self.ast['op'] = self.last_node
        self._andexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _andexpr_(self):
        self._eqexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._andtail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _andtail_(self):
        self._token('&')
        self.ast['op'] = self.last_node
        self._eqexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _eqexpr_(self):
        self._relexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._eqtail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _eqtail_(self):
        self._eqop_()
        self.ast['op'] = self.last_node
        self._relexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _eqop_(self):
        self._pattern(r'[!=]=')

    @graken()
    def _relexpr_(self):
        self._shiftexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._reltail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _reltail_(self):
        self._relop_()
        self.ast['op'] = self.last_node
        self._shiftexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _relop_(self):
        self._pattern(r'[<>]={0,1}')

    @graken()
    def _shiftexpr_(self):
        self._addexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._shifttail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _shifttail_(self):
        self._shiftop_()
        self.ast['op'] = self.last_node
        self._addexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _shiftop_(self):
        self._pattern(r'<<|>>')

    @graken()
    def _addexpr_(self):
        self._multexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._addtail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _addtail_(self):
        self._addop_()
        self.ast['op'] = self.last_node
        self._multexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _addop_(self):
        self._pattern(r'[+-]')

    @graken()
    def _multexpr_(self):
        self._unaryexpr_()
        self.ast['lhs'] = self.last_node

        def block2():
            self._multtail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['lhs', 'tail'],
            []
        )

    @graken()
    def _multtail_(self):
        self._multop_()
        self.ast['op'] = self.last_node
        self._unaryexpr_()
        self.ast['rhs'] = self.last_node

        self.ast._define(
            ['op', 'rhs'],
            []
        )

    @graken()
    def _multop_(self):
        self._pattern(r'[/%\*]')

    @graken()
    def _unaryexpr_(self):

        def block1():
            self._leftunaryop_()
        self._closure(block1)
        self.ast['leftops'] = self.last_node
        self._primaryexpr_()
        self.ast['rhs'] = self.last_node

        def block4():
            self._rightunaryop_()
        self._closure(block4)
        self.ast['rightops'] = self.last_node

        self.ast._define(
            ['leftops', 'rhs', 'rightops'],
            []
        )

    @graken()
    def _leftunaryop_(self):
        self._pattern(r'[\*&!\~]|--?|\+\+')

    @graken()
    def _rightunaryop_(self):
        with self._choice():
            with self._option():
                self._token('++')
            with self._option():
                self._token('--')
            self._error('expecting one of: ++ --')

    @graken()
    def _primaryexpr_(self):
        self._primaryexprhead_()
        self.ast['head'] = self.last_node

        def block2():
            self._primaryexprtail_()
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['head', 'tail'],
            []
        )

    @graken()
    def _primaryexprhead_(self):
        with self._choice():
            with self._option():
                self._token('(')
                self._expr_()
                self.ast['@'] = self.last_node
                self._token(')')
            with self._option():
                self._builtinexpr_()
            with self._option():
                self._variableexpr_()
            with self._option():
                self._constantexpr_()
            with self._option():
                self._stringexpr_()
            self._error('no available options')

    @graken()
    def _primaryexprtail_(self):
        with self._choice():
            with self._option():
                self._token('(')
                with self._optional():
                    self._exprlist_()
                    self.ast['args'] = self.last_node
                self._token(')')
            with self._option():
                self._token('[')
                self._expr_()
                self.ast['index'] = self.last_node
                self._token(']')
            self._error('expecting one of: (')

        self.ast._define(
            ['args', 'index'],
            []
        )

    @graken()
    def _variableexpr_(self):
        with self._ifnot():
            self._builtinexpr_()
        self._name_()

    @graken()
    def _constantexpr_(self):
        with self._choice():
            with self._option():
                self._numericexpr_()
            with self._option():
                self._characterexpr_()
            self._error('no available options')

    @graken()
    def _builtinexpr_(self):
        self._token('__bytes_per_word')

    @graken()
    def _numericexpr_(self):

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

    @graken()
    def _characterexpr_(self):
        self._token("'")

        def block1():
            self._CHARACTERCONSTCHAR_()
        self._closure(block1)
        self.ast['@'] = self.last_node
        self._token("'")

    @graken()
    def _stringexpr_(self):
        self._token('"')

        def block1():
            self._STRINGCONSTCHAR_()
        self._closure(block1)
        self.ast['@'] = self.last_node
        self._token('"')

    @graken()
    def _name_(self):
        self._ALPHA_()
        self.ast['head'] = self.last_node

        def block2():
            with self._choice():
                with self._option():
                    self._ALPHA_()
                with self._option():
                    self._NUMERIC_()
                self._error('no available options')
        self._closure(block2)
        self.ast['tail'] = self.last_node

        self.ast._define(
            ['head', 'tail'],
            []
        )

    @graken()
    def _ALPHA_(self):
        self._pattern(r'[A-Za-z_\.\b]')

    @graken()
    def _NUMERIC_(self):
        self._pattern(r'[0-9]')

    @graken()
    def _CHARACTERCONSTCHAR_(self):
        self._pattern(r"([^'\*])|(\*.)")

    @graken()
    def _STRINGCONSTCHAR_(self):
        self._pattern(r'([^"\*])|(\*.)')

    @graken()
    def _exprlist_(self):
        self._expr_()
        self.ast.setlist('@', self.last_node)

        def block1():
            self._token(',')
            self._expr_()
            self.ast.setlist('@', self.last_node)
        self._closure(block1)

    @graken()
    def _namelist_(self):
        self._name_()
        self.ast.setlist('@', self.last_node)

        def block1():
            self._token(',')
            self._name_()
            self.ast.setlist('@', self.last_node)
        self._closure(block1)


class BSemantics(object):
    def program(self, ast):
        return ast

    def definition(self, ast):
        return ast

    def simpledef(self, ast):
        return ast

    def vectordef(self, ast):
        return ast

    def ivallist(self, ast):
        return ast

    def ival(self, ast):
        return ast

    def functiondef(self, ast):
        return ast

    def statement(self, ast):
        return ast

    def labelstatement(self, ast):
        return ast

    def gotostatement(self, ast):
        return ast

    def switchstatement(self, ast):
        return ast

    def casestatement(self, ast):
        return ast

    def breakstatement(self, ast):
        return ast

    def autostatement(self, ast):
        return ast

    def autovar(self, ast):
        return ast

    def extrnstatement(self, ast):
        return ast

    def compoundstatement(self, ast):
        return ast

    def ifstatement(self, ast):
        return ast

    def whilestatement(self, ast):
        return ast

    def returnstatement(self, ast):
        return ast

    def exprstatement(self, ast):
        return ast

    def nullstatement(self, ast):
        return ast

    def expr(self, ast):
        return ast

    def assignexpr(self, ast):
        return ast

    def assignop(self, ast):
        return ast

    def condexpr(self, ast):
        return ast

    def orexpr(self, ast):
        return ast

    def ortail(self, ast):
        return ast

    def xorexpr(self, ast):
        return ast

    def xortail(self, ast):
        return ast

    def andexpr(self, ast):
        return ast

    def andtail(self, ast):
        return ast

    def eqexpr(self, ast):
        return ast

    def eqtail(self, ast):
        return ast

    def eqop(self, ast):
        return ast

    def relexpr(self, ast):
        return ast

    def reltail(self, ast):
        return ast

    def relop(self, ast):
        return ast

    def shiftexpr(self, ast):
        return ast

    def shifttail(self, ast):
        return ast

    def shiftop(self, ast):
        return ast

    def addexpr(self, ast):
        return ast

    def addtail(self, ast):
        return ast

    def addop(self, ast):
        return ast

    def multexpr(self, ast):
        return ast

    def multtail(self, ast):
        return ast

    def multop(self, ast):
        return ast

    def unaryexpr(self, ast):
        return ast

    def leftunaryop(self, ast):
        return ast

    def rightunaryop(self, ast):
        return ast

    def primaryexpr(self, ast):
        return ast

    def primaryexprhead(self, ast):
        return ast

    def primaryexprtail(self, ast):
        return ast

    def variableexpr(self, ast):
        return ast

    def constantexpr(self, ast):
        return ast

    def builtinexpr(self, ast):
        return ast

    def numericexpr(self, ast):
        return ast

    def characterexpr(self, ast):
        return ast

    def stringexpr(self, ast):
        return ast

    def name(self, ast):
        return ast

    def ALPHA(self, ast):
        return ast

    def NUMERIC(self, ast):
        return ast

    def CHARACTERCONSTCHAR(self, ast):
        return ast

    def STRINGCONSTCHAR(self, ast):
        return ast

    def exprlist(self, ast):
        return ast

    def namelist(self, ast):
        return ast


def main(filename, startrule, trace=False, whitespace=None, nameguard=None):
    import json
    with open(filename) as f:
        text = f.read()
    parser = BParser(parseinfo=False)
    ast = parser.parse(
        text,
        startrule,
        filename=filename,
        trace=trace,
        whitespace=whitespace,
        nameguard=nameguard)
    print('AST:')
    print(ast)
    print()
    print('JSON:')
    print(json.dumps(ast, indent=2))
    print()

if __name__ == '__main__':
    import argparse
    import string
    import sys

    class ListRules(argparse.Action):
        def __call__(self, parser, namespace, values, option_string):
            print('Rules:')
            for r in BParser.rule_list():
                print(r)
            print()
            sys.exit(0)

    parser = argparse.ArgumentParser(description="Simple parser for B.")
    parser.add_argument('-l', '--list', action=ListRules, nargs=0,
                        help="list all rules and exit")
    parser.add_argument('-n', '--no-nameguard', action='store_true',
                        dest='no_nameguard',
                        help="disable the 'nameguard' feature")
    parser.add_argument('-t', '--trace', action='store_true',
                        help="output trace information")
    parser.add_argument('-w', '--whitespace', type=str, default=string.whitespace,
                        help="whitespace specification")
    parser.add_argument('file', metavar="FILE", help="the input file to parse")
    parser.add_argument('startrule', metavar="STARTRULE",
                        help="the start rule for parsing")
    args = parser.parse_args()

    main(
        args.file,
        args.startrule,
        trace=args.trace,
        whitespace=args.whitespace,
        nameguard=not args.no_nameguard
    )
