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


__version__ = (2014, 10, 21, 13, 45, 6, 1)

__all__ = [
    'htk_modelParser',
    'htk_modelSemantics',
    'main'
]


class htk_modelParser(Parser):
    def __init__(self, whitespace=None, nameguard=True, **kwargs):
        super(htk_modelParser, self).__init__(
            whitespace=whitespace,
            nameguard=nameguard,
            **kwargs
        )

    @graken()
    def _model_(self):

        def block0():
            self._macrodef_()
            self.ast.setlist('macros', self.last_node)
        self._closure(block0)

        def block2():
            self._hmmmacro_()
            self.ast.setlist('hmms', self.last_node)
        self._closure(block2)

        self.ast._define(
            [],
            ['macros', 'hmms']
        )

    @graken()
    def _macrodef_(self):
        with self._choice():
            with self._option():
                self._transPmacro_()
                self.ast['transition'] = self.last_node
            with self._option():
                self._stateinfomacro_()
                self.ast['state'] = self.last_node
            with self._option():
                self._optmacro_()
                self.ast['options'] = self.last_node
            with self._option():
                self._varmacro_()
                self.ast['variance'] = self.last_node
            with self._option():
                self._meanmacro_()
                self.ast['mean'] = self.last_node
            with self._option():
                self._durationmacro_()
                self.ast['duration'] = self.last_node
            self._error('no available options')

        self.ast._define(
            ['transition', 'state', 'options', 'variance', 'mean', 'duration'],
            []
        )

    @graken()
    def _hmmmacro_(self):
        with self._optional():
            self._hmmref_()
            self.ast['name'] = self.last_node
        self._hmmdef_()
        self.ast['definition'] = self.last_node

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

    @graken()
    def _optmacro_(self):
        self._token('~o')
        self._cut()
        self._globalOpts_()
        self.ast['definition'] = self.last_node

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

    @graken()
    def _transPmacro_(self):
        self._transPref_()
        self.ast['name'] = self.last_node
        self._transPdef_()
        self.ast['definition'] = self.last_node

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

    @graken()
    def _stateinfomacro_(self):
        self._stateinforef_()
        self.ast['name'] = self.last_node
        self._stateinfodef_()
        self.ast['definition'] = self.last_node

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

    @graken()
    def _varmacro_(self):
        self._varref_()
        self.ast['name'] = self.last_node
        self._vardef_()
        self.ast['definition'] = self.last_node

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

    @graken()
    def _meanmacro_(self):
        self._meanref_()
        self.ast['name'] = self.last_node
        self._meandef_()
        self.ast['definition'] = self.last_node

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

    @graken()
    def _durationmacro_(self):
        self._durationref_()
        self.ast['name'] = self.last_node
        self._durationdef_()
        self.ast['definition'] = self.last_node

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

    @graken()
    def _varref_(self):
        self._token('~v')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _transPref_(self):
        self._token('~t')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _stateinforef_(self):
        self._token('~s')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _hmmref_(self):
        self._token('~h')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _weightsref_(self):
        self._token('~w')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _mixpdfref_(self):
        self._token('~m')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _meanref_(self):
        self._token('~u')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _durationref_(self):
        self._token('~d')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _invref_(self):
        self._token('~i')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _xformref_(self):
        self._token('~x')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _inputXformref_(self):
        self._token('~j')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node

    @graken()
    def _macro_(self):
        self._string_()

    @graken()
    def _hmmdef_(self):
        self._token('<BeginHMM>')
        self._cut()
        with self._optional():
            self._globalOpts_()
            self.ast['options'] = self.last_node
        self._token('<NumStates>')
        self._cut()
        self._short_()
        self.ast['state_count'] = self.last_node

        def block2():
            self._state_()
            self.ast.setlist('states', self.last_node)
        self._positive_closure(block2)

        with self._optional():
            self._regTree_()
            self.ast['regression_tree'] = self.last_node
        self._transP_()
        self.ast['transition'] = self.last_node
        with self._optional():
            self._duration_()
            self.ast['duration'] = self.last_node
        self._token('<EndHMM>')

        self.ast._define(
            ['options', 'state_count', 'regression_tree', 'transition', 'duration'],
            ['states']
        )

    @graken()
    def _globalOpts_(self):

        def block1():
            self._option_()
        self._positive_closure(block1)

        self.ast['@'] = self.last_node

    @graken()
    def _option_(self):
        with self._choice():
            with self._option():
                self._token('<HmmSetId>')
                self._cut()
                self._string_()
                self.ast['hmm_set_id'] = self.last_node
            with self._option():
                self._token('<StreamInfo>')
                self._cut()
                self._streaminfo_()
                self.ast['stream_info'] = self.last_node
            with self._option():
                self._token('<VecSize>')
                self._cut()
                self._short_()
                self.ast['vector_size'] = self.last_node
            with self._option():
                self._token('<InputXform>')
                self._cut()
                self._inputXform_()
                self.ast['input_transform'] = self.last_node
            with self._option():
                self._covkind_()
                self.ast['covariance_kind'] = self.last_node
            with self._option():
                self._durkind_()
                self.ast['duration_kind'] = self.last_node
            with self._option():
                self._parmkind_()
                self.ast['parameter_kind'] = self.last_node
            self._error('no available options')

        self.ast._define(
            ['hmm_set_id', 'stream_info', 'vector_size', 'input_transform', 'covariance_kind', 'duration_kind', 'parameter_kind'],
            []
        )

    @graken()
    def _streaminfo_(self):
        self._short_()
        self.ast['count'] = self.last_node

        def block2():
            self._short_()
        self._closure(block2)
        self.ast['sizes'] = self.last_node

        self.ast._define(
            ['count', 'sizes'],
            []
        )

    @graken()
    def _covkind_(self):
        self._token('<')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('diagc')
                with self._option():
                    self._token('invdiagc')
                with self._option():
                    self._token('fullc')
                with self._option():
                    self._token('lltc')
                with self._option():
                    self._token('xformc')
                self._error('expecting one of: diagc fullc invdiagc lltc xformc')
        self.ast['@'] = self.last_node
        self._token('>')

    @graken()
    def _durkind_(self):
        self._token('<')
        with self._group():
            with self._choice():
                with self._option():
                    self._token('nulld')
                with self._option():
                    self._token('poissond')
                with self._option():
                    self._token('gammad')
                with self._option():
                    self._token('gen')
                self._error('expecting one of: gammad gen nulld poissond')
        self.ast['@'] = self.last_node
        self._token('>')

    @graken()
    def _parmkind_(self):
        self._token('<')
        self._basekind_()
        self.ast['base'] = self.last_node

        def block2():
            with self._choice():
                with self._option():
                    self._token('_D')
                with self._option():
                    self._token('_A')
                with self._option():
                    self._token('_T')
                with self._option():
                    self._token('_E')
                with self._option():
                    self._token('_N')
                with self._option():
                    self._token('_Z')
                with self._option():
                    self._token('_O')
                with self._option():
                    self._token('_V')
                with self._option():
                    self._token('_C')
                with self._option():
                    self._token('_K')
                self._error('expecting one of: _A _C _D _E _K _N _O _T _V _Z')
        self._closure(block2)
        self.ast['options'] = self.last_node
        self._token('>')

        self.ast._define(
            ['base', 'options'],
            []
        )

    @graken()
    def _basekind_(self):
        with self._choice():
            with self._option():
                self._token('discrete')
            with self._option():
                self._token('lpc')
            with self._option():
                self._token('lpcepstra')
            with self._option():
                self._token('mfcc')
            with self._option():
                self._token('fbank')
            with self._option():
                self._token('melspec')
            with self._option():
                self._token('lprefc')
            with self._option():
                self._token('lpdelcep')
            with self._option():
                self._token('user')
            self._error('expecting one of: discrete fbank lpc lpcepstra lpdelcep lprefc melspec mfcc user')

    @graken()
    def _state_(self):
        self._token('<State>')
        self._cut()
        self._short_()
        self.ast['index'] = self.last_node
        self._stateinfo_()
        self.ast['state'] = self.last_node

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

    @graken()
    def _stateinfo_(self):
        with self._choice():
            with self._option():
                self._stateinforef_()
                self.ast['@'] = self.last_node
            with self._option():
                self._stateinfodef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _stateinfodef_(self):
        with self._optional():
            self._mixes_()
            self.ast['streams_mixcount'] = self.last_node
        with self._optional():
            self._weights_()
            self.ast['weights'] = self.last_node

        def block2():
            self._stream_()
            self.ast.setlist('streams', self.last_node)
        self._positive_closure(block2)

        with self._optional():
            self._duration_()
            self.ast['duration'] = self.last_node

        self.ast._define(
            ['streams_mixcount', 'weights', 'duration'],
            ['streams']
        )

    @graken()
    def _mixes_(self):
        self._token('<NumMixes>')
        self._cut()

        def block1():
            self._short_()
        self._positive_closure(block1)

        self.ast['@'] = self.last_node

    @graken()
    def _weights_(self):
        with self._choice():
            with self._option():
                self._weightsref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._weightsdef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _weightsdef_(self):
        self._token('<SWeights>')
        self._cut()
        self._short_()
        self.ast['dim'] = self.last_node
        self._vector_()
        self.ast['vector'] = self.last_node

        self.ast._define(
            ['dim', 'vector'],
            []
        )

    @graken()
    def _stream_(self):
        with self._optional():
            self._token('<Stream>')
            self._cut()
            self._short_()
            self.ast['dim'] = self.last_node
        with self._group():
            with self._choice():
                with self._option():

                    def block1():
                        self._mixture_()
                        self.ast.setlist('mixtures', self.last_node)
                    self._positive_closure(block1)
                with self._option():
                    self._tmixpdf_()
                    self.ast['tmixpdf'] = self.last_node
                with self._option():
                    self._discpdf_()
                    self.ast['discpdf'] = self.last_node
                self._error('no available options')

        self.ast._define(
            ['dim', 'tmixpdf', 'discpdf'],
            ['mixtures']
        )

    @graken()
    def _mixture_(self):
        with self._optional():
            self._token('<Mixture>')
            self._cut()
            self._short_()
            self.ast['index'] = self.last_node
            self._float_()
            self.ast['weight'] = self.last_node
        self._mixpdf_()
        self.ast['pdf'] = self.last_node

        self.ast._define(
            ['index', 'weight', 'pdf'],
            []
        )

    @graken()
    def _tmixpdf_(self):
        self._token('<TMix>')
        self._cut()
        self._macro_()
        self._weightList_()

    @graken()
    def _weightList_(self):

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

    @graken()
    def _repShort_(self):
        self._short_()
        with self._optional():
            self._token('*')
            self._cut()
            self._char_()

    @graken()
    def _discpdf_(self):
        self._token('<DProb>')
        self._cut()
        self._weightList_()

    @graken()
    def _mixpdf_(self):
        with self._choice():
            with self._option():
                self._mixpdfref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._mixpdfdef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _mixpdfdef_(self):
        with self._optional():
            self._rclass_()
            self.ast['regression_class'] = self.last_node
        self._mean_()
        self.ast['mean'] = self.last_node
        self._cov_()
        self.ast['covariance'] = self.last_node
        with self._optional():
            self._token('<GConst>')
            self._cut()
            self._float_()
            self.ast['gconst'] = self.last_node

        self.ast._define(
            ['regression_class', 'mean', 'covariance', 'gconst'],
            []
        )

    @graken()
    def _rclass_(self):
        self._token('<RClass>')
        self._cut()
        self._short_()
        self.ast['@'] = self.last_node

    @graken()
    def _mean_(self):
        with self._choice():
            with self._option():
                self._meanref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._meandef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _meandef_(self):
        self._token('<Mean>')
        self._cut()
        self._short_()
        self.ast['dim'] = self.last_node
        self._vector_()
        self.ast['vector'] = self.last_node

        self.ast._define(
            ['dim', 'vector'],
            []
        )

    @graken()
    def _cov_(self):
        with self._choice():
            with self._option():
                self._var_()
                self.ast['variance'] = self.last_node
            with self._option():
                self._inv_()
            with self._option():
                self._xform_()
            self._error('no available options')

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

    @graken()
    def _var_(self):
        with self._choice():
            with self._option():
                self._varref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._vardef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _vardef_(self):
        self._token('<Variance>')
        self._cut()
        self._short_()
        self.ast['dim'] = self.last_node
        self._vector_()
        self.ast['vector'] = self.last_node

        self.ast._define(
            ['dim', 'vector'],
            []
        )

    @graken()
    def _inv_(self):
        with self._choice():
            with self._option():
                self._invref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._invdef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _invdef_(self):
        with self._group():
            with self._choice():
                with self._option():
                    self._token('<InvCovar>')
                with self._option():
                    self._token('<LLTCovar>')
                self._error('expecting one of: <InvCovar> <LLTCovar>')
        self.ast['type'] = self.last_node
        self._cut()
        self._short_()
        self.ast['dim'] = self.last_node
        self._tmatrix_()
        self.ast['matrix'] = self.last_node

        self.ast._define(
            ['type', 'dim', 'matrix'],
            []
        )

    @graken()
    def _xform_(self):
        with self._choice():
            with self._option():
                self._xformref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._xformdef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _xformdef_(self):
        self._token('<Xform>')
        self._cut()
        self._short_()
        self.ast['dim1'] = self.last_node
        self._short_()
        self.ast['dim2'] = self.last_node
        self._matrix_()
        self.ast['matrix'] = self.last_node

        self.ast._define(
            ['dim1', 'dim2', 'matrix'],
            []
        )

    @graken()
    def _tmatrix_(self):
        self._matrix_()

    @graken()
    def _duration_(self):
        with self._choice():
            with self._option():
                self._durationref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._durationdef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _durationdef_(self):
        self._token('<Duration>')
        self._cut()
        self._short_()
        self.ast['dim'] = self.last_node
        self._vector_()
        self.ast['vector'] = self.last_node

        self.ast._define(
            ['dim', 'vector'],
            []
        )

    @graken()
    def _regTree_(self):
        self._token('~r')
        self._cut()
        self._macro_()
        self.ast['@'] = self.last_node
        self._tree_()
        self.ast['tree'] = self.last_node

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

    @graken()
    def _tree_(self):
        self._token('<RegTree>')
        self._cut()
        self._short_()
        self._nodes_()

    @graken()
    def _nodes_(self):
        with self._group():
            with self._choice():
                with self._option():
                    self._token('<Node>')
                    self._cut()
                    self._short_()
                    self._short_()
                    self._short_()
                with self._option():
                    self._token('<TNode>')
                    self._cut()
                    self._short_()
                    self._int_()
                self._error('no available options')
        with self._optional():
            self._nodes_()

    @graken()
    def _transP_(self):
        with self._choice():
            with self._option():
                self._transPref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._transPdef_()
                self.ast['@'] = self.last_node
            self._error('no available options')

    @graken()
    def _transPdef_(self):
        self._token('<TransP>')
        self._cut()
        self._short_()
        self.ast['dim'] = self.last_node
        self._matrix_()
        self.ast['array'] = self.last_node

        self.ast._define(
            ['dim', 'array'],
            []
        )

    @graken()
    def _inputXform_(self):
        with self._choice():
            with self._option():
                self._inputXformref_()
                self.ast['@'] = self.last_node
            with self._option():
                self._inhead_()
                self._inmatrix_()
            self._error('no available options')

    @graken()
    def _inhead_(self):
        self._token('<MMFIdMask>')
        self._cut()
        self._string_()
        self._parmkind_()
        with self._optional():
            self._token('<PreQual>')

    @graken()
    def _inmatrix_(self):
        self._token('<LinXform>')
        self._token('<VecSize>')
        self._cut()
        self._short_()
        self._token('<BlockInfo>')
        self._cut()
        self._short_()

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


        def block1():
            self._block_()
        self._positive_closure(block1)

    @graken()
    def _block_(self):
        self._token('<Block>')
        self._cut()
        self._short_()
        self._xform_()

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

    @graken()
    def _vector_(self):
        self._pattern(r'[\d.\-\+eE \n]+')

    @graken()
    def _matrix_(self):
        self._pattern(r'[\d.\-\+eE \n]+')

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

    @graken()
    def _float_(self):
        self._pattern(r'[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?')

    @graken()
    def _char_(self):
        self._pattern(r'.')

    @graken()
    def _int_(self):
        self._pattern(r'[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)')


class htk_modelSemantics(object):
    def model(self, ast):
        return ast

    def macrodef(self, ast):
        return ast

    def hmmmacro(self, ast):
        return ast

    def optmacro(self, ast):
        return ast

    def transPmacro(self, ast):
        return ast

    def stateinfomacro(self, ast):
        return ast

    def varmacro(self, ast):
        return ast

    def meanmacro(self, ast):
        return ast

    def durationmacro(self, ast):
        return ast

    def varref(self, ast):
        return ast

    def transPref(self, ast):
        return ast

    def stateinforef(self, ast):
        return ast

    def hmmref(self, ast):
        return ast

    def weightsref(self, ast):
        return ast

    def mixpdfref(self, ast):
        return ast

    def meanref(self, ast):
        return ast

    def durationref(self, ast):
        return ast

    def invref(self, ast):
        return ast

    def xformref(self, ast):
        return ast

    def inputXformref(self, ast):
        return ast

    def macro(self, ast):
        return ast

    def hmmdef(self, ast):
        return ast

    def globalOpts(self, ast):
        return ast

    def option(self, ast):
        return ast

    def streaminfo(self, ast):
        return ast

    def covkind(self, ast):
        return ast

    def durkind(self, ast):
        return ast

    def parmkind(self, ast):
        return ast

    def basekind(self, ast):
        return ast

    def state(self, ast):
        return ast

    def stateinfo(self, ast):
        return ast

    def stateinfodef(self, ast):
        return ast

    def mixes(self, ast):
        return ast

    def weights(self, ast):
        return ast

    def weightsdef(self, ast):
        return ast

    def stream(self, ast):
        return ast

    def mixture(self, ast):
        return ast

    def tmixpdf(self, ast):
        return ast

    def weightList(self, ast):
        return ast

    def repShort(self, ast):
        return ast

    def discpdf(self, ast):
        return ast

    def mixpdf(self, ast):
        return ast

    def mixpdfdef(self, ast):
        return ast

    def rclass(self, ast):
        return ast

    def mean(self, ast):
        return ast

    def meandef(self, ast):
        return ast

    def cov(self, ast):
        return ast

    def var(self, ast):
        return ast

    def vardef(self, ast):
        return ast

    def inv(self, ast):
        return ast

    def invdef(self, ast):
        return ast

    def xform(self, ast):
        return ast

    def xformdef(self, ast):
        return ast

    def tmatrix(self, ast):
        return ast

    def duration(self, ast):
        return ast

    def durationdef(self, ast):
        return ast

    def regTree(self, ast):
        return ast

    def tree(self, ast):
        return ast

    def nodes(self, ast):
        return ast

    def transP(self, ast):
        return ast

    def transPdef(self, ast):
        return ast

    def inputXform(self, ast):
        return ast

    def inhead(self, ast):
        return ast

    def inmatrix(self, ast):
        return ast

    def block(self, ast):
        return ast

    def string(self, ast):
        return ast

    def vector(self, ast):
        return ast

    def matrix(self, ast):
        return ast

    def short(self, ast):
        return ast

    def float(self, ast):
        return ast

    def char(self, ast):
        return ast

    def int(self, ast):
        return ast


def main(filename, startrule, trace=False, whitespace=None):
    import json
    with open(filename) as f:
        text = f.read()
    parser = htk_modelParser(parseinfo=False)
    ast = parser.parse(
        text,
        startrule,
        filename=filename,
        trace=trace,
        whitespace=whitespace)
    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 htk_modelParser.rule_list():
                print(r)
            print()
            sys.exit(0)

    parser = argparse.ArgumentParser(description="Simple parser for htk_model.")
    parser.add_argument('-l', '--list', action=ListRules, nargs=0,
                        help="list all rules and exit")
    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
    )
