3
dRC                 @   s   d dl mZ d dlmZmZ e ZG dd dZG dd deZG dd dZG d	d
 d
eZ	G dd de	Z
G dd de	ZG dd deZG dd deZG dd d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re  dS )    )Counter)APPLogicParserc               @   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   4/tmp/pip-build-v9q4h5k9/nltk/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 j|  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| j||S |t jkr,| j||S d S )N)r   r   Zhandle_variabler   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_factory-   s    
z/LinearLogicParser.get_BooleanExpression_factoryc             C   s
   |||S )Nr   )r   factoryfirstsecondr   r   r   make_BooleanExpression3   s    z(LinearLogicParser.make_BooleanExpressionc             C   sT   | j t|rP| jdrP| jdtjkrP| j  | jt}| j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_ApplicationExpression6   s    
z/LinearLogicParser.attempt_ApplicationExpressionc             C   s    |d j  rt|S t|S d S )Nr   )isupperVariableExpressionConstantExpression)r   namer   r   r   make_VariableExpressionC   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 j|S )N)_linear_logic_parserparse)clssr   r   r   
fromstringN   s    zExpression.fromstringNc             C   s   t | ||S )N)r#   )r   otherZother_indicesr   r   r   applytoR   s    zExpression.applytoc             C   s
   | j |S )N)r3   )r   r2   r   r   r   __call__U   s    zExpression.__call__c             C   s   d| j j d|  dS )N< >)	__class__r   )r   r   r   r   __repr__X   s    zExpression.__repr__)N)
r   r	   r
   r   r-   classmethodr1   r3   r4   r9   r   r   r   r   r,   J   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)
isinstancestrAssertionErrorr)   dependencies)r   r)   r?   r   r   r   r   ]   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   simplifyi   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_posv   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   rB   rC   r   r   r   compile_neg   s    zAtomicExpression.compile_negc             C   s   |j | j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   r2   r   r   r   __eq__   s    zAtomicExpression.__eq__c             C   s
   | |k S )Nr   )r   r2   r   r   r   __ne__   s    zAtomicExpression.__ne__c             C   s   | j }| jr|d| j 7 }|S )Nz%s)r)   r?   )r   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   rA   rD   rE   rH   rI   rJ   rL   rN   r   r   r   r   r;   \   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   r2   r@   r   r   r   unify   s    

zConstantExpression.unifyN)r   r	   r
   rR   r   r   r   r   r(      s   r(   c               @   s   e Zd Zdd ZdS )r'   c             C   sf   t |tsty"| |kr|S |t| |fg S W n0 tk
r` } zt| |||W Y dd}~X 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>   rO   rP   rQ   )r   r2   r@   er   r   r   rR      s    	zVariableExpression.unifyN)r   r	   r
   rR   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   rT   rU   r   r   r   r      s    zImpExpression.__init__Nc             C   s   | j | jj|| jj|S )N)r8   rT   rA   rU   )r   r@   r   r   r   rA      s    zImpExpression.simplifyc             C   sh   t |tsty$|| jj|j| | jj|j| S  tk
rb } zt| |||W Y dd}~X 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>   rT   rR   rU   rP   rQ   )r   r2   r@   rS   r   r   r   rR      s
    	$zImpExpression.unifyc             C   s6   | j j||\}}| 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
        )rT   rE   rU   rD   r   )r   rB   rC   aa_newcc_newr   r   r   rD      s    zImpExpression.compile_posc       	      C   s\   | j j||\}}| jj||\}}|j }|jj| |d| ||h}||| |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)rT   rD   rU   rE   getr?   append)	r   rB   rC   rV   rW   rX   rY   Zfresh_indexZnew_vr   r   r   rE      s    zImpExpression.compile_negc             C   s   | j j| | jj| d S )N)rT   rH   rU   )r   rG   r   r   r   rH     s    zImpExpression.initialize_labelsc             C   s$   | j |j ko"| j|jko"| j|jkS )N)r8   rT   rU   )r   r2   r   r   r   rI     s    zImpExpression.__eq__c             C   s
   | |k S )Nr   )r   r2   r   r   r   rJ     s    zImpExpression.__ne__c             C   s   dj tj| jtj| jtjS )Nz{}{} {} {}{})formatr   r   rT   r   rU   r   )r   r   r   r   rL     s    zImpExpression.__str__c             C   s"   t t | j tj t | j S )N)rM   rT   r   r   rU   )r   r   r   r   rN     s    zImpExpression.__hash__)N)r   r	   r
   r   rA   rR   rD   rE   rH   rI   rJ   rL   rN   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
  |j  }|j  }t|tstt|ts,tt }y>t|trH||j7 }t|tr\||j7 }||jj	||7 }W n> t
k
r } z"td| d| d| |W Y dd}~X 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 z to z. NzODependencies 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)rA   r<   r   r>   r,   rO   r#   r@   rT   rR   rQ   LinearLogicApplicationExceptionsetr?   functionr$   )r   r_   r$   Zargument_indicesZfunction_simpZargument_simpr@   rS   r   r   r   r   #  s6    



zApplicationExpression.__init__c             C   s   |s
| j }| 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_   rA   rU   )r   r@   r   r   r   rA   O  s    	zApplicationExpression.simplifyc             C   s$   | j |j ko"| j|jko"| j|jkS )N)r8   r_   r$   )r   r2   r   r   r   rI   ]  s    zApplicationExpression.__eq__c             C   s
   | |k S )Nr   )r   r2   r   r   r   rJ   d  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   rL   g  s    zApplicationExpression.__str__c             C   s"   t t | j tj t | j S )N)rM   rT   r   r   rU   )r   r   r   r   rN   j  s    zApplicationExpression.__hash__)N)N)	r   r	   r
   r   rA   rI   rJ   rL   rN   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 )rO   Nc             C   s:   i | _ t|tr|j }|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   o  s    
zBindingDict.__init__c             C   s`   t |tstt |tst||ks(t| jj|d}| sD||krP|| 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`   rZ   rP   )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   re   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   s   yFt  }x| jD ]}| j| ||< qW x|jD ]}|j| ||< q.W |S  tk
rz } ztd| |f |W Y dd}~X 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)rO   r`   rP   )r   r2   Zcombinedrc   rS   r   r   r   __add__  s    
zBindingDict.__add__c             C   s
   | |k S )Nr   )r   r2   r   r   r   rJ     s    zBindingDict.__ne__c             C   s   t |tst| j|jkS )N)r<   rO   	TypeErrorr`   )r   r2   r   r   r   rI     s    
zBindingDict.__eq__c                s*   ddj  fddt jj D  d S )N{z, c             3   s"   | ]}| d  j |  V  qdS )z: N)r`   ).0rc   )r   r   r   	<genexpr>  s    z&BindingDict.__str__.<locals>.<genexpr>})joinsortedr`   keys)r   r   )r   r   rL     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   rg   ri   rk   rl   rJ   rI   rL   r9   r   r   r   r   rO   n  s   
rO   c               @   s   e Zd ZdS )rP   N)r   r	   r
   r   r   r   r   rP     s   rP   c               @   s   e Zd Zdd ZdS )rQ   c             C   s"   t j| d| d| d|  d S )NzCannot unify z with z given )	Exceptionr   )r   rV   rd   r@   r   r   r   r     s    zUnificationException.__init__N)r   r	   r
   r   r   r   r   r   rQ     s   rQ   c               @   s   e Zd ZdS )r]   N)r   r	   r
   r   r   r   r   r]     s   r]   c              C   sz   t j} t| d t| d t| d t| d t| dj  t| dj  t| dj  t| dj  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,   r1   printrA   )Zlexprr   r   r   demo  s    rx   __main__N)Znltk.internalsr   Znltk.sem.logicr   r   _counterr   r   r,   r;   r(   r'   r   r#   rO   ru   rP   rQ   r]   rx   r   r   r   r   r   <module>	   s"   /CYLY