B
    >?[B                 @   s:  d dl mZmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
mZ e ZG dd deZG dd	 d	e
ZeG d
d deZeG dd deZG dd deZG dd deZeG dd deZeG dd deZeG dd deZG dd deZG dd deZG dd deZdd Zed kr6e  d!S )"    )print_functionunicode_literals)string_types)Counter)python_2_unicode_compatible)LogicParserAPPc               @   s*   e Zd ZdZdZdZeegZeeg ZdS )Tokens()z-oN)__name__
__module____qualname__OPENCLOSEIMPZPUNCTTOKENS r   r   3lib/python3.7/site-packages/nltk/sem/linearlogic.pyr	      s
   r	   c               @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )LinearLogicParserz!A linear logic expression parser.c             C   s4   t |  tdtjdd di| _|  jtjg7  _d S )N         )r   __init__r   r	   r   Zoperator_precedenceZright_associated_operations)selfr   r   r   r   "   s    
zLinearLogicParser.__init__c             C   s   t jS )N)r	   r   )r   r   r   r   get_all_symbols(   s    z!LinearLogicParser.get_all_symbolsc             C   s0   |t jkr| ||S |t jkr,| ||S d S )N)r	   r   Zhandle_variabler   Zhandle_open)r   tokcontextr   r   r   handle+   s    

zLinearLogicParser.handlec             C   s   |t jkrtS d S d S )N)r	   r   ImpExpression)r   r   r   r   r   get_BooleanExpression_factory1   s    
z/LinearLogicParser.get_BooleanExpression_factoryc             C   s
   |||S )Nr   )r   factoryfirstsecondr   r   r   make_BooleanExpression7   s    z(LinearLogicParser.make_BooleanExpressionc             C   sT   |  t|rP| drP| dtjkrP|   | t}| tj t	||d}|S )zAttempt to make an application expression.  If the next tokens
        are an argument in parens, then the argument expression is a
        function being applied to the arguments.  Otherwise, return the
        argument expression.r   N)
Zhas_priorityr   ZinRangetokenr	   r   Zprocess_next_expressionZassertNextTokenr   ApplicationExpression)r   Z
expressionr   argumentr   r   r   attempt_ApplicationExpression:   s    
z/LinearLogicParser.attempt_ApplicationExpressionc             C   s    |d   rt|S t|S d S )Nr   )isupperVariableExpressionConstantExpression)r   namer   r   r   make_VariableExpressionG   s    z)LinearLogicParser.make_VariableExpressionN)r   r   r   __doc__r   r   r   r    r$   r(   r-   r   r   r   r   r      s   r   c               @   s8   e Zd Ze Zedd Zd
ddZdd Zdd	 Z	dS )
Expressionc             C   s   | j |S )N)_linear_logic_parserparse)clssr   r   r   
fromstringS   s    zExpression.fromstringNc             C   s   t | ||S )N)r&   )r   otherZother_indicesr   r   r   applytoW   s    zExpression.applytoc             C   s
   |  |S )N)r6   )r   r5   r   r   r   __call__Z   s    zExpression.__call__c             C   s   d| j j| f S )Nz<%s %s>)	__class__r   )r   r   r   r   __repr__]   s    zExpression.__repr__)N)
r   r   r   r   r0   classmethodr4   r6   r7   r9   r   r   r   r   r/   N   s
   
r/   c               @   sX   e Zd ZdddZdddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd ZdS )AtomicExpressionNc             C   s&   t |tst|| _|sg }|| _dS )z
        :param name: str for the constant name
        :param dependencies: list of int for the indices on which this atom is dependent
        N)
isinstancer   AssertionErrorr,   dependencies)r   r,   r>   r   r   r   r   c   s
    zAtomicExpression.__init__c             C   s   |r| |kr||  S | S dS )z
        If 'self' is bound by 'bindings', return the atomic to which it is bound.
        Otherwise, return self.

        :param bindings: ``BindingDict`` A dictionary of bindings used to simplify
        :return: ``AtomicExpression``
        Nr   )r   bindingsr   r   r   simplifyo   s    zAtomicExpression.simplifyc             C   s   g | _ | g fS )a3  
        From Iddo Lev's PhD Dissertation p108-109

        :param index_counter: ``Counter`` for unique indices
        :param glueFormulaFactory: ``GlueFormula`` for creating new glue formulas
        :return: (``Expression``,set) for the compiled linear logic and any newly created glue formulas
        )r>   )r   index_counterglueFormulaFactoryr   r   r   compile_pos|   s    zAtomicExpression.compile_posc             C   s   g | _ | g fS )a3  
        From Iddo Lev's PhD Dissertation p108-109

        :param index_counter: ``Counter`` for unique indices
        :param glueFormulaFactory: ``GlueFormula`` for creating new glue formulas
        :return: (``Expression``,set) for the compiled linear logic and any newly created glue formulas
        )r>   )r   rA   rB   r   r   r   compile_neg   s    zAtomicExpression.compile_negc             C   s   | | j | _d S )N)Zinitialize_labelr,   lower)r   fstructr   r   r   initialize_labels   s    z"AtomicExpression.initialize_labelsc             C   s   | j |j ko| j|jkS )N)r8   r,   )r   r5   r   r   r   __eq__   s    zAtomicExpression.__eq__c             C   s
   | |k S )Nr   )r   r5   r   r   r   __ne__   s    zAtomicExpression.__ne__c             C   s   | j }| jr|d| j 7 }|S )Nz%s)r,   r>   )r   Zaccumr   r   r   __str__   s    zAtomicExpression.__str__c             C   s
   t | jS )N)hashr,   )r   r   r   r   __hash__   s    zAtomicExpression.__hash__)N)N)r   r   r   r   r@   rC   rD   rG   rH   rI   rJ   rL   r   r   r   r   r;   a   s   

r;   c               @   s   e Zd Zdd ZdS )r+   c             C   s^   t |tstt |trBy|t|| fg S  tk
r>   Y qNX n| |krN|S t| ||dS )a  
        If 'other' is a constant, then it must be equal to 'self'.  If 'other' is a variable,
        then it must not be bound to anything other than 'self'.

        :param other: ``Expression``
        :param bindings: ``BindingDict`` A dictionary of all current bindings
        :return: ``BindingDict`` A new combined dictionary of of 'bindings' and any new binding
        :raise UnificationException: If 'self' and 'other' cannot be unified in the context of 'bindings'
        N)r<   r/   r=   r*   BindingDictVariableBindingExceptionUnificationException)r   r5   r?   r   r   r   unify   s    

zConstantExpression.unifyN)r   r   r   rP   r   r   r   r   r+      s   r+   c               @   s   e Zd Zdd ZdS )r*   c             C   sV   t |tsty"| |kr|S |t| |fg S W n  tk
rP   t| ||Y nX dS )a  
        'self' must not be bound to anything other than 'other'.

        :param other: ``Expression``
        :param bindings: ``BindingDict`` A dictionary of all current bindings
        :return: ``BindingDict`` A new combined dictionary of of 'bindings' and the new binding
        :raise UnificationException: If 'self' and 'other' cannot be unified in the context of 'bindings'
        N)r<   r/   r=   rM   rN   rO   )r   r5   r?   r   r   r   rP      s    	zVariableExpression.unifyN)r   r   r   rP   r   r   r   r   r*      s   r*   c               @   s^   e Zd Zdd ZdddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd ZdS )r   c             C   s,   t |tstt |tst|| _|| _dS )z
        :param antecedent: ``Expression`` for the antecedent
        :param consequent: ``Expression`` for the consequent
        N)r<   r/   r=   
antecedent
consequent)r   rQ   rR   r   r   r   r      s    zImpExpression.__init__Nc             C   s   |  | j|| j|S )N)r8   rQ   r@   rR   )r   r?   r   r   r   r@      s    zImpExpression.simplifyc             C   sX   t |tsty$|| j|j| | j|j| S  tk
rR   t| ||Y nX dS )a  
        Both the antecedent and consequent of 'self' and 'other' must unify.

        :param other: ``ImpExpression``
        :param bindings: ``BindingDict`` A dictionary of all current bindings
        :return: ``BindingDict`` A new combined dictionary of of 'bindings' and any new bindings
        :raise UnificationException: If 'self' and 'other' cannot be unified in the context of 'bindings'
        N)r<   r   r=   rQ   rP   rR   rN   rO   )r   r5   r?   r   r   r   rP      s
    	$zImpExpression.unifyc             C   s6   | j ||\}}| j||\}}t|||| fS )a3  
        From Iddo Lev's PhD Dissertation p108-109

        :param index_counter: ``Counter`` for unique indices
        :param glueFormulaFactory: ``GlueFormula`` for creating new glue formulas
        :return: (``Expression``,set) for the compiled linear logic and any newly created glue formulas
        )rQ   rD   rR   rC   r   )r   rA   rB   aa_newcc_newr   r   r   rC      s    zImpExpression.compile_posc       	      C   s`   | j ||\}}| j||\}}| }|j| |d| |t|g}||| |g fS )aG  
        From Iddo Lev's PhD Dissertation p108-109

        :param index_counter: ``Counter`` for unique indices
        :param glueFormulaFactory: ``GlueFormula`` for creating new glue formulas
        :return: (``Expression``,list of ``GlueFormula``) for the compiled linear logic and any newly created glue formulas
        zv%s)rQ   rC   rR   rD   getr>   appendset)	r   rA   rB   rS   rT   rU   rV   Zfresh_indexZnew_vr   r   r   rD      s    zImpExpression.compile_negc             C   s   | j | | j| d S )N)rQ   rG   rR   )r   rF   r   r   r   rG     s    zImpExpression.initialize_labelsc             C   s$   | j |j ko"| j|jko"| j|jkS )N)r8   rQ   rR   )r   r5   r   r   r   rH     s    zImpExpression.__eq__c             C   s
   | |k S )Nr   )r   r5   r   r   r   rI     s    zImpExpression.__ne__c             C   s   dt j| jt j| jt jf S )Nz%s%s %s %s%s)r	   r   rQ   r   rR   r   )r   r   r   r   rJ     s    zImpExpression.__str__c             C   s    t dt | jtjt | jf S )Nz%s%s%s)rK   rQ   r	   r   rR   )r   r   r   r   rL   %  s    zImpExpression.__hash__)N)r   r   r   r   r@   rP   rC   rD   rG   rH   rI   rJ   rL   r   r   r   r   r      s   

	r   c               @   s@   e Zd ZdddZdddZdd Zdd	 Zd
d Zdd ZdS )r&   Nc          
   C   s   |  }|  }t|tstt|ts,tt }y>t|trH||j7 }t|tr\||j7 }||j	||7 }W n4 t
k
r } ztd|||f W dd}~X Y nX |rt|jj|k std||f t|jj|krtd||f || _|| _|| _dS )aY  
        :param function: ``Expression`` for the function
        :param argument: ``Expression`` for the argument
        :param argument_indices: set for the indices of the glue formula from which the argument came
        :raise LinearLogicApplicationException: If 'function' cannot be applied to 'argument' given 'argument_indices'.
        zCannot apply %s to %s. %sNzODependencies unfulfilled when attempting to apply Linear Logic formula %s to %szbDependencies not a proper subset of indices when attempting to apply Linear Logic formula %s to %s)r@   r<   r   r=   r/   rM   r&   r?   rQ   rP   rO   LinearLogicApplicationExceptionrY   r>   functionr'   )r   r[   r'   Zargument_indicesZfunction_simpZargument_simpr?   er   r   r   r   -  s4    



"zApplicationExpression.__init__c             C   s   |s
| j }| j|jS )a=  
        Since function is an implication, return its consequent.  There should be
        no need to check that the application is valid since the checking is done
        by the constructor.

        :param bindings: ``BindingDict`` A dictionary of bindings used to simplify
        :return: ``Expression``
        )r?   r[   r@   rR   )r   r?   r   r   r   r@   Y  s    	zApplicationExpression.simplifyc             C   s$   | j |j ko"| j|jko"| j|jkS )N)r8   r[   r'   )r   r5   r   r   r   rH   g  s    zApplicationExpression.__eq__c             C   s
   | |k S )Nr   )r   r5   r   r   r   rI   n  s    zApplicationExpression.__ne__c             C   s    d| j  tj d| j  tj S )Nz%s)r[   r	   r   r'   r   )r   r   r   r   rJ   q  s    zApplicationExpression.__str__c             C   s    t dt | jtjt | jf S )Nz%s%s%s)rK   rQ   r	   r   rR   )r   r   r   r   rL   t  s    zApplicationExpression.__hash__)N)N)	r   r   r   r   r@   rH   rI   rJ   rL   r   r   r   r   r&   +  s   
,
r&   c               @   sV   e Zd ZdddZdd Zdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd ZdS )rM   Nc             C   s:   i | _ t|tr| }|r6x|D ]\}}|| |< q"W dS )z
        :param bindings:
            list [(``VariableExpression``, ``AtomicExpression``)] to initialize the dictionary
            dict {``VariableExpression``: ``AtomicExpression``} to initialize the dictionary
        N)dr<   dictitems)r   r?   vbr   r   r   r   |  s    
zBindingDict.__init__c             C   s^   t |tstt |tst||ks(t| j|d}|rB||krN|| j|< ntd| dS )a  
        A binding is consistent with the dict if its variable is not already bound, OR if its
        variable is already bound to its argument.

        :param variable: ``VariableExpression`` The variable bind
        :param binding: ``Expression`` The expression to which 'variable' should be bound
        :raise VariableBindingException: If the variable cannot be bound in this dictionary
        Nz*Variable %s already bound to another value)r<   r*   r=   r/   r]   rW   rN   )r   variableZbindingexistingr   r   r   __setitem__  s    	zBindingDict.__setitem__c             C   sJ   t |tst| j| }x,|rDy| j| }W q tk
r@   |S X qW dS )zD
        Return the expression to which 'variable' is bound
        N)r<   r*   r=   r]   KeyError)r   rb   Zintermediater   r   r   __getitem__  s    
zBindingDict.__getitem__c             C   s
   || j kS )N)r]   )r   itemr   r   r   __contains__  s    zBindingDict.__contains__c             C   sp   yFt  }x| jD ]}| j| ||< qW x|jD ]}|j| ||< q.W |S  tk
rj   td| |f Y nX dS )a  
        :param other: ``BindingDict`` The dict with which to combine self
        :return: ``BindingDict`` A new dict containing all the elements of both parameters
        :raise VariableBindingException: If the parameter dictionaries are not consistent with each other
        zAAttempting to add two contradicting VariableBindingsLists: %s, %sN)rM   r]   rN   )r   r5   Zcombinedr`   r   r   r   __add__  s    zBindingDict.__add__c             C   s
   | |k S )Nr   )r   r5   r   r   r   rI     s    zBindingDict.__ne__c             C   s   t |tst| j|jkS )N)r<   rM   	TypeErrorr]   )r   r5   r   r   r   rH     s    
zBindingDict.__eq__c                s"   dd  fdd jD  d S )N{z, c             3   s    | ]}d | j | f V  qdS )z%s: %sN)r]   ).0r`   )r   r   r   	<genexpr>  s    z&BindingDict.__str__.<locals>.<genexpr>})joinr]   )r   r   )r   r   rJ     s    zBindingDict.__str__c             C   s   d|  S )NzBindingDict: %sr   )r   r   r   r   r9     s    zBindingDict.__repr__)N)r   r   r   r   rd   rf   rh   ri   rI   rH   rJ   r9   r   r   r   r   rM   z  s   
rM   c               @   s   e Zd ZdS )rN   N)r   r   r   r   r   r   r   rN     s   rN   c               @   s   e Zd Zdd ZdS )rO   c             C   s   t | d|||f  d S )Nz Cannot unify %s with %s given %s)	Exceptionr   )r   rS   ra   r?   r   r   r   r     s    zUnificationException.__init__N)r   r   r   r   r   r   r   r   rO     s   rO   c               @   s   e Zd ZdS )rZ   N)r   r   r   r   r   r   r   rZ     s   rZ   c              C   sz   t j} t| d t| d t| d t| d t| d  t| d  t| d  t| d  d S )	Nfz(g -o f)z((g -o G) -o G)zg -o h -o fz(g -o f)(g)z(H -o f)(g)z((g -o G) -o G)((g -o f))z(H -o H)((g -o f)))r/   r4   printr@   )Zlexprr   r   r   demo  s    rs   __main__N)Z
__future__r   r   Zsixr   Znltk.internalsr   Znltk.compatr   Znltk.sem.logicr   r   Z_counterobjectr	   r   r/   r;   r+   r*   r   r&   rM   rp   rN   rO   rZ   rs   r   r   r   r   r   <module>   s2   /C[NY
