#!/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


KEYWORDS = {}


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


class pcodeParser(Parser):
    def __init__(
        self,
        whitespace=None,
        nameguard=None,
        comments_re=None,
        eol_comments_re=None,
        ignorecase=None,
        left_recursion=False,
        parseinfo=True,
        keywords=None,
        namechars='',
        buffer_class=pcodeBuffer,
        **kwargs
    ):
        if keywords is None:
            keywords = KEYWORDS
        super(pcodeParser, 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 _start_(self):
        self._statement_()
        with self._optional():
            self._token(';')
        self._check_eof()

    @graken()
    def _statement_(self):
        with self._choice():
            with self._option():
                self._token('if')
                self._expr0_()
                self._token('then')
                self._statement_()

                def block0():
                    self._token('else')
                    self._statement_()
                self._closure(block0)
            with self._option():
                self._token('UNPREDICTABLE')
            with self._option():
                self._token('UNDEFINED')
            with self._option():
                self._token('NOT_PERMITTED')
            with self._option():
                self._token('NOP')
            with self._option():
                self._token('nop')
            with self._option():
                self._token('SEE')
                self._whatever_()
            with self._option():
                self._tuple_()
                self._token('=')
                self._expr0_()
            with self._option():
                self._ident_()
                self._token('=')
                self._token('if')
                self._expr0_()
                self._token('then')
                self._expr0_()
                self._token('else')
                self._expr0_()
            with self._option():
                self._expr0_()
                self._token('=')
                self._expr0_()
            self._error('expecting one of: NOP NOT_PERMITTED UNDEFINED UNPREDICTABLE nop')

    @graken()
    def _tuple_(self):
        self._token('(')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('-')
                with self._option():
                    self._expr0_()
                self._error('expecting one of: -')

        def block1():
            self._token(',')
            with self._group():
                with self._choice():
                    with self._option():
                        self._token('-')
                    with self._option():
                        self._expr0_()
                    self._error('expecting one of: -')
        self._positive_closure(block1)
        self._token(')')

    @graken()
    def _expr0_(self):
        with self._choice():
            with self._option():
                self._expr1_()

                def block0():
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._token('EOR')
                            with self._option():
                                self._token('+')
                            with self._option():
                                self._token('-')
                            with self._option():
                                self._token('&&')
                            with self._option():
                                self._token('||')
                            self._error('expecting one of: && + - EOR ||')
                    self._expr1_()
                self._positive_closure(block0)
            with self._option():
                self._expr1_()
            self._error('no available options')

    @graken()
    def _expr1_(self):
        with self._choice():
            with self._option():
                self._expr2_()

                def block0():
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._token('*')
                            with self._option():
                                self._token('/')
                            with self._option():
                                self._token('<<')
                            with self._option():
                                self._token('>>')
                            with self._option():
                                self._token('DIV')
                            with self._option():
                                self._token('XOR')
                            self._error('expecting one of: * / << >> DIV XOR')
                    self._expr2_()
                self._positive_closure(block0)
            with self._option():
                self._expr2_()

                def block2():
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._token('==')
                            with self._option():
                                self._token('!=')
                            with self._option():
                                self._token('<=')
                            with self._option():
                                self._token('>=')
                            with self._option():
                                self._token('<')
                            with self._option():
                                self._token('>')
                            self._error('expecting one of: != < <= == > >=')
                    self._expr2_()
                self._positive_closure(block2)
            with self._option():
                self._expr2_()
            self._error('no available options')

    @graken()
    def _expr2_(self):
        with self._choice():
            with self._option():
                self._func_call_()
            with self._option():
                self._expr3_()
            self._error('no available options')

    @graken()
    def _expr3_(self):
        with self._choice():
            with self._option():
                self._builtin_value_()
            with self._option():
                self._sliceable_()
            with self._option():
                with self._group():
                    with self._choice():
                        with self._option():
                            self._ident_()
                        with self._option():
                            self._number_()
                        with self._option():
                            self._bits_()
                        self._error('no available options')

                def block1():
                    self._token(':')
                    with self._group():
                        with self._choice():
                            with self._option():
                                self._ident_()
                            with self._option():
                                self._number_()
                            with self._option():
                                self._bits_()
                            self._error('no available options')
                self._closure(block1)
            with self._option():
                self._tuple_()
            with self._option():
                self._token('(')
                self._expr0_()
                self._token(')')
            with self._option():
                self._token('!')
                self._expr0_()
            self._error('no available options')

    @graken()
    def _number_(self):
        self._pattern(r'\d+')

    @graken()
    def _bits_(self):
        self._pattern(r"'[01]+'")

    @graken()
    def _ident_(self):
        self._pattern(r'[a-zA-Z][\.\w]*')

    @graken()
    def _whatever_(self):
        self._pattern(r'.*')

    @graken()
    def _sliceable_(self):
        with self._choice():
            with self._option():
                self._token('index_align<')
                self._number_()
                self._token(':')
                self._number_()
                self._token('>')
            with self._option():
                self._token('index_align<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('align<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('mask<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('imod<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('imm6<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('imm6<')
                self._number_()
                self._token(':')
                self._number_()
                self._token('>')
            with self._option():
                self._token('imm8<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('Vd<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('Vn<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('Vm<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('Vm<')
                self._number_()
                self._token(':')
                self._number_()
                self._token('>')
            with self._option():
                self._token('cc<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('cmode<')
                self._number_()
                self._token('>')
            with self._option():
                self._token('cmode<')
                self._number_()
                self._token(':')
                self._number_()
                self._token('>')
            self._error('no available options')

    @graken()
    def _builtin_value_(self):
        with self._choice():
            with self._option():
                self._token('TRUE')
            with self._option():
                self._token('FALSE')
            with self._option():
                self._token('registers<')
                with self._group():
                    with self._choice():
                        with self._option():
                            self._number_()
                        with self._option():
                            self._ident_()
                        self._error('no available options')
                self._token('>')
            with self._option():
                self._token('list<')
                with self._group():
                    with self._choice():
                        with self._option():
                            self._number_()
                        with self._option():
                            self._ident_()
                        self._error('no available options')
                self._token('>')
            with self._option():
                self._token('cond<')
                self._number_()
                self._token(':')
                self._number_()
                self._token('>')
            with self._option():
                self._token('cond<')
                self._expr0_()
                self._token('>')
            with self._option():
                self._token('SRType_LSL')
            with self._option():
                self._token('SRType_LSR')
            with self._option():
                self._token('SRType_ASR')
            with self._option():
                self._token('SRType_ROR')
            with self._option():
                self._token('SRType_RRX')
            with self._option():
                self._token('InstrSet_ThumbEE')
            with self._option():
                self._token('ARM_GRP_INVALID')
            with self._option():
                self._token('ARM_GRP_JUMP')
            with self._option():
                self._token('ARM_GRP_CRYPT')
            with self._option():
                self._token('ARM_GRP_DATABARRIER')
            with self._option():
                self._token('ARM_GRP_DIVIDE')
            with self._option():
                self._token('ARM_GRP_FPARMV8')
            with self._option():
                self._token('ARM_GRP_MULTPRO')
            with self._option():
                self._token('ARM_GRP_NEON')
            with self._option():
                self._token('ARM_GRP_T2EXTRACTPACK')
            with self._option():
                self._token('ARM_GRP_THUMB2DSP')
            with self._option():
                self._token('ARM_GRP_TRUSTZONE')
            with self._option():
                self._token('ARM_GRP_V4T')
            with self._option():
                self._token('ARM_GRP_V5T')
            with self._option():
                self._token('ARM_GRP_V5TE')
            with self._option():
                self._token('ARM_GRP_V6')
            with self._option():
                self._token('ARM_GRP_V6T2')
            with self._option():
                self._token('ARM_GRP_V7')
            with self._option():
                self._token('ARM_GRP_V8')
            with self._option():
                self._token('ARM_GRP_VFP2')
            with self._option():
                self._token('ARM_GRP_VFP3')
            with self._option():
                self._token('ARM_GRP_VFP4')
            with self._option():
                self._token('ARM_GRP_ARM')
            with self._option():
                self._token('ARM_GRP_MCLASS')
            with self._option():
                self._token('ARM_GRP_NOTMCLASS')
            with self._option():
                self._token('ARM_GRP_THUMB')
            with self._option():
                self._token('ARM_GRP_THUMB1ONLY')
            with self._option():
                self._token('ARM_GRP_THUMB2')
            with self._option():
                self._token('ARM_GRP_PREV8')
            with self._option():
                self._token('ARM_GRP_FPVMLX')
            with self._option():
                self._token('ARM_GRP_MULOPS')
            with self._option():
                self._token('ARM_GRP_CRC')
            with self._option():
                self._token('ARM_GRP_DPVFP')
            with self._option():
                self._token('ARM_GRP_V6M')
            self._error('expecting one of: ARM_GRP_ARM ARM_GRP_CRC ARM_GRP_CRYPT ARM_GRP_DATABARRIER ARM_GRP_DIVIDE ARM_GRP_DPVFP ARM_GRP_FPARMV8 ARM_GRP_FPVMLX ARM_GRP_INVALID ARM_GRP_JUMP ARM_GRP_MCLASS ARM_GRP_MULOPS ARM_GRP_MULTPRO ARM_GRP_NEON ARM_GRP_NOTMCLASS ARM_GRP_PREV8 ARM_GRP_T2EXTRACTPACK ARM_GRP_THUMB ARM_GRP_THUMB1ONLY ARM_GRP_THUMB2 ARM_GRP_THUMB2DSP ARM_GRP_TRUSTZONE ARM_GRP_V4T ARM_GRP_V5T ARM_GRP_V5TE ARM_GRP_V6 ARM_GRP_V6M ARM_GRP_V6T2 ARM_GRP_V7 ARM_GRP_V8 ARM_GRP_VFP2 ARM_GRP_VFP3 ARM_GRP_VFP4 FALSE InstrSet_ThumbEE SRType_ASR SRType_LSL SRType_LSR SRType_ROR SRType_RRX TRUE')

    @graken()
    def _func_call_(self):
        with self._choice():
            with self._option():
                self._bitcount_()
            with self._option():
                self._badreg_()
            with self._option():
                self._consistent_()
            with self._option():
                self._decodeimmshift_()
            with self._option():
                self._thumbexpandimm_()
            with self._option():
                self._thumbexpandimm_c_()
            with self._option():
                self._advsimdexpandimm_()
            with self._option():
                self._vfpexpandimm_()
            with self._option():
                self._uint_()
            with self._option():
                self._zeroextend_()
            with self._option():
                self._zeros_()
            with self._option():
                self._initblock_()
            with self._option():
                self._lastinitblock_()
            with self._option():
                self._archversion_()
            with self._option():
                self._currentinstrset_()
            with self._option():
                self._signextend_()
            with self._option():
                self._not_()
            with self._option():
                self._issecure_()
            self._error('no available options')

    @graken()
    def _bitcount_(self):
        self._token('BitCount(')
        self._expr0_()
        self._token(')')

    @graken()
    def _badreg_(self):
        self._token('BadReg(')
        self._expr0_()
        self._token(')')

    @graken()
    def _consistent_(self):
        self._token('Consistent(')
        self._expr0_()
        self._token(')')

    @graken()
    def _decodeimmshift_(self):
        self._token('DecodeImmShift(')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(')')

    @graken()
    def _thumbexpandimm_(self):
        self._token('ThumbExpandImm(')
        self._expr0_()
        self._token(')')

    @graken()
    def _thumbexpandimm_c_(self):
        self._token('ThumbExpandImm_C(')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(')')

    @graken()
    def _advsimdexpandimm_(self):
        self._token('AdvSIMDExpandImm(')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(')')

    @graken()
    def _vfpexpandimm_(self):
        self._token('VFPExpandImm(')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(')')

    @graken()
    def _uint_(self):
        self._token('UInt(')
        self._expr0_()
        self._token(')')

    @graken()
    def _zeroextend_(self):
        self._token('ZeroExtend(')
        self._expr0_()
        self._token(',')
        self._expr0_()
        self._token(')')

    @graken()
    def _zeros_(self):
        self._token('Zeros(')
        self._expr0_()
        self._token(')')

    @graken()
    def _initblock_(self):
        self._token('InITBlock()')

    @graken()
    def _lastinitblock_(self):
        self._token('LastInITBlock()')

    @graken()
    def _archversion_(self):
        self._token('ArchVersion()')

    @graken()
    def _currentinstrset_(self):
        self._token('CurrentInstrSet()')

    @graken()
    def _signextend_(self):
        self._token('SignExtend(')
        self._expr3_()
        self._token(', 32)')

    @graken()
    def _not_(self):
        self._token('NOT(')
        self._expr0_()
        self._token(')')

    @graken()
    def _issecure_(self):
        self._token('IsSecure()')


class pcodeSemantics(object):
    def start(self, ast):
        return ast

    def statement(self, ast):
        return ast

    def tuple(self, ast):
        return ast

    def expr0(self, ast):
        return ast

    def expr1(self, ast):
        return ast

    def expr2(self, ast):
        return ast

    def expr3(self, ast):
        return ast

    def number(self, ast):
        return ast

    def bits(self, ast):
        return ast

    def ident(self, ast):
        return ast

    def whatever(self, ast):
        return ast

    def sliceable(self, ast):
        return ast

    def builtin_value(self, ast):
        return ast

    def func_call(self, ast):
        return ast

    def bitcount(self, ast):
        return ast

    def badreg(self, ast):
        return ast

    def consistent(self, ast):
        return ast

    def decodeimmshift(self, ast):
        return ast

    def thumbexpandimm(self, ast):
        return ast

    def thumbexpandimm_c(self, ast):
        return ast

    def advsimdexpandimm(self, ast):
        return ast

    def vfpexpandimm(self, ast):
        return ast

    def uint(self, ast):
        return ast

    def zeroextend(self, ast):
        return ast

    def zeros(self, ast):
        return ast

    def initblock(self, ast):
        return ast

    def lastinitblock(self, ast):
        return ast

    def archversion(self, ast):
        return ast

    def currentinstrset(self, ast):
        return ast

    def signextend(self, ast):
        return ast

    def not_(self, ast):
        return ast

    def issecure(self, ast):
        return ast


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


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

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