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

# pylint: skip-file

# 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, generic_main  # noqa
from .lexer import Lambda, Var, Apply, Alias

__version__ = (2016, 6, 7, 6, 14, 58, 1)

__all__ = [
    'LambdaParser',
    'LambdaSemantics'
]

KEYWORDS = set([])
definitions = {}


class LambdaParser(Parser):
    def __init__(self,
                 whitespace=None,
                 nameguard=None,
                 comments_re=None,
                 eol_comments_re=None,
                 ignorecase=None,
                 left_recursion=True,
                 keywords=KEYWORDS,
                 namechars='',
                 **kwargs):
        super(LambdaParser, self).__init__(
            whitespace=whitespace,
            nameguard=nameguard,
            comments_re=comments_re,
            eol_comments_re=eol_comments_re,
            ignorecase=ignorecase,
            left_recursion=left_recursion,
            keywords=keywords,
            namechars=namechars,
            **kwargs
        )

    @graken()
    def _program_(self):

        def block0():
            self._line_()
        self._closure(block0)

    @graken()
    def _line_(self):
        with self._group():
            with self._choice():
                with self._option():
                    self._define_()
                with self._option():
                    self._function_()
                self._error('no available options')

    @graken()
    def _define_(self):
        self._token('@')
        self._alias_()
        self._token(':')
        self._function_()

    @graken()
    def _function_(self):
        with self._choice():
            with self._option():
                self._lambda_()
            with self._option():
                self._application_()
            self._error('no available options')

    @graken()
    def _lambda_(self):
        with self._group():
            with self._choice():
                with self._option():
                    self._token('\u03bb')
                with self._option():
                    self._token('\\')
                self._error('expecting one of: \\ \u03bb')
        self._variable_()
        self._token('.')
        self._expr_()

    @graken()
    def _application_(self):
        self._token('(')
        self._expr_()
        self._expr_()
        self._token(')')

    @graken()
    def _expr_(self):
        with self._group():
            with self._choice():
                with self._option():
                    self._lambda_()
                with self._option():
                    self._application_()
                with self._option():
                    self._variable_()
                with self._option():
                    self._alias_()
                self._error('no available options')

    @graken()
    def _variable_(self):
        self._pattern(r'[a-z]')

    @graken()
    def _alias_(self):
        self._pattern(r'[_A-Z][_A-Z0-9]*')


class LambdaSemantics(object):
    def program(self, ast):
        return ast, definitions

    def line(self, ast):
        return ast

    def define(self, ast):
        definitions[ast[1].name] = ast[3]
        return None

    def function(self, ast):
        return ast

    def lambda_(self, ast):
        return Lambda(ast[1], ast[3])

    def application(self, ast):
        return Apply(ast[1], ast[2])

    def expr(self, ast):
        return ast

    def variable(self, ast):
        return Var(ast.encode('utf-8'))

    def alias(self, ast):
        return Alias(ast)
