a
    VŸ$cý# ã                   @   s  d dl mZmZmZmZmZ d dlmZmZm	Z	m
Z
mZmZmZmZmZmZmZmZ d dlZd dlZd dlZd dlZd dlZd dlZd dlmZ g ad dlmZ dd„ ZG dd„ deƒZ G d	d
„ d
e!ƒZ"dd„ Z#e $dej%¡Z&dd„ Z'dd„ Z(dd„ Z)da*d©dd„Z+dd„ Z,e-g d¢ƒZ.g d¢Z/g d¢Z0d 1dd „ e/D ƒe0 ¡Z2d!Z3d"Z4G d#d$„ d$e!ƒZ5G d%d&„ d&e!ƒZ6dªd'd(„Z7d)d*„ Z8d+d,„ Z9d-d.„ Z:d/d0„ Z;d1d2„ Z<d3d4„ Z=G d5d6„ d6e!ƒZ>e>ƒ Z?d7d8„ Z@e@d9ƒd:d;„ ƒZAe@d<ƒd=d>„ ƒZBe@d?ƒd@dA„ ƒZCe@dBƒdCdD„ ƒZDe@dEƒdFdG„ ƒZEe@dHƒdIdJ„ ƒZFe@dKƒdLdM„ ƒZGe@dNƒdOdP„ ƒZHe@dQƒdRdS„ ƒZIe@dTƒdUdV„ ƒZJe@dWƒdXdY„ ƒZKe@dZƒd[d\„ ƒZLe@d]ƒd^d_„ ƒZe@d`ƒdadb„ ƒZMe@dcƒddde„ ƒZNe@dfƒdgdh„ ƒZOe@diƒdjdk„ ƒZPe@dlƒdmdn„ ƒZQe@doƒdpdq„ ƒZRe@drƒd«dsdt„ƒZSe@duƒdvdw„ ƒZTe@dxƒdydz„ ƒZUe@d{ƒd|d}„ ƒZVe@d~ƒdd€„ ƒZWdd‚„ ZXdƒd„„ ZYeZej[ \d…d†¡ƒZ]e@d‡ƒdˆd‰„ ƒZ^e@dŠƒd‹dŒ„ ƒZ_ddŽ„ Z`e@dƒdd‘„ ƒZae@d’ƒd“d”„ ƒZbe@d•ƒd–d—„ ƒZcd¬d™dš„Zdd›dœ„ Zee@dƒddž„ ƒZfdŸd „ Zgd¡d¢„ Zhd­d£d¤„Zid¥d¦„ Zjd§d¨„ ZkdS )®é    )ÚdivisionÚabsolute_importÚwith_statementÚprint_functionÚunicode_literals)ÚPY2Ú
basestringÚbchrÚbordÚchrÚopenÚpystrÚrangeÚroundÚstrÚtobytesÚunicodeN)Úmatch_logical_wordc                 C   sD   ddl }tj | ¡}z| ||¡p$d}W n ty>   d}Y n0 |S )zo
    Gets the text of a line, in a best-effort way, for debugging purposes. May
    return just a newline.
    r   NÚ
)Ú	linecacheÚrenpyÚexportsÚunelide_filenameÚgetlineÚ	Exception)ÚfilenameÚlinenor   Úfull_filenameÚline© r   úrenpy/parser.pyÚget_line_text,   s    
r!   c                   @   s   e Zd Zddd„Zdd„ ZdS )Ú
ParseErrorNFc                 C   s6  dt |ƒ||f }|r t|tƒr,d |¡}| d¡}t|ƒdkrÂd }	d}
|
t|d ƒk r²|d |
 }|dkrx|
d7 }
n0||	kr†d }	n"|	rŒn|dks¤|dks¤|d	kr¨|}	|
d7 }
qJ|	rÂ|d
|	 7 }|D ]X}|d| 7 }|d ur|t|ƒkr|dd|  d 7 }d }n|t|ƒ8 }|rÆ q qÆ|| _t | |¡ d S )NzFile "%s", line %d: %sÚ r   é   r   ú\ú`ú'ú"z:
(Perhaps you left out a %s at the end of the first line.)z
    ú ú^)	Úunicode_filenameÚ
isinstanceÚlistÚjoinÚsplitÚlenÚmessager   Ú__init__)Úselfr   ÚnumberÚmsgr   ÚposÚfirstr1   ÚlinesÚopen_stringÚiÚcÚlr   r   r    r2   ?   s@    





zParseError.__init__c                 C   s   | j S ©N)r1   ©r3   r   r   r    Ú__unicode__n   s    zParseError.__unicode__)NNF)Ú__name__Ú
__module__Ú__qualname__r2   r?   r   r   r   r    r"   =   s   
/r"   c                   @   s   e Zd ZdZdd„ ZdS )ÚLineNumberHolderz)
    Holds the expected line number.
    c                 C   s
   d| _ d S ©Nr   )r   r>   r   r   r    r2   y   s    zLineNumberHolder.__init__N)r@   rA   rB   Ú__doc__r2   r   r   r   r    rC   t   s   rC   c                 C   sX   t | tƒr| S z|  d¡W S  ty,   Y n0 z|  d¡W S  tyL   Y n0 |  d¡S )z4
    Converts the supplied filename to unicode.
    Úmbcsúutf-8zlatin-1)r,   r   Údecoder   )Úfnr   r   r    r+   }   s    
r+   z__(\w+)|\w+| +|.c                 C   sJ   t j | ¡}t j |¡d }| dd¡}dd„ }t d||¡}d| d S )	Nr   r)   Ú_c                 S   s   t t|  d¡ƒƒS rD   )ÚhexÚordÚgroup)Úmr   r   r    Ú
munge_char    s    z"munge_filename.<locals>.munge_charz[^a-zA-Z0-9_]Ú_m1_Ú__)ÚosÚpathÚbasenameÚsplitextÚreplaceÚreÚsub)rI   ÚrvrO   r   r   r    Úmunge_filenameš   s    rZ   c                 C   s   |   dd¡} tj tjj¡  dd¡d }tj tjj¡  dd¡d }| |¡rX||g}n||g}|D ]"}|  |¡rd| t	|ƒd… } qŒqd| }|S )zy
    Returns a version of fn that is either relative to the base directory,
    or relative to the Ren'Py directory.
    r%   ú/N)
rV   rR   rS   Úabspathr   ÚconfigÚbasedirÚ
renpy_baseÚ
startswithr0   )rI   r^   r_   ÚdirsÚdrY   r   r   r    Úelide_filename¨   s    


rc   c                 C   s‚   t j | ¡} tjjd ur:t j tjj| ¡}t j |¡r:|S t j tjj| ¡}t j |¡r\|S t j tjj	| ¡}t j |¡r~|S | S r=   )
rR   rS   Únormpathr   r]   Úalternate_unelide_pathr.   Úexistsr^   r_   )rI   Úfn0Úfn1Úfn2r   r   r    r   Å   s    r   r#   r$   Fc                    sð  ‡ fdd„}| a |r|}n:t| dƒ }| ¡  dd¡}W d  ƒ n1 sJ0    Y  t| ƒ} t| ƒ‰ |d7 }g }|}d}	t|ƒr”|d d	kr”|	d
7 }	|s¤tj 	¡ j
r®tjj}
ni }
t|ƒ}tjj | ¡ d}d}|	|k rÔ|}g }d}| |f}tj t ||	¡|
|< d}|	|k rÐ|	}||	 }|dkr0t| |dƒ‚|dkr|sd |¡}t d|¡sh| | ||f¡ |du rv|	}|d
 |
| _||d
  dv r¢|d
8 }q„||
| _||
| j|
| j… |
| _||
| j|
| j… |
| _|	d
7 }	|d
7 }d}g }qÐ|dkr|d
7 }d}|dkr.|	d
7 }	q|dkrh||	d
  dkrh|	d7 }	|d
7 }| d¡ q|dv rz|d
7 }|dv r’|r’|d
8 }|dkr¾|	}||	 dkr|	d
7 }	q q|dv rl|}| |¡ |	d
7 }	d}d}|	|d
 k r4||	 |kr4||	d
  |kr4| |¡ | |¡ |	d7 }	d}g }|	|k r<||	 }|dkr\|d
7 }|dkrr|	d
7 }	q8|r’d}|	d
7 }	| |¡ q8||kr|s¸|	d
7 }	| |¡ q<|	|d k r||	d
  |kr||	d  |kr|	d7 }	| |¡ | |¡ | |¡ q<|dkr"d}| |¡ |	d
7 }	q8q8d |¡}d|v r^t d||¡}| |¡ qt||	ƒ\}}}|r |dd… }d|vr ˆ | }| |¡ |}	|	| dkrt| |d |dd!‚qqÐ|rìt| |d"|dd!‚|S )#a  
    Reads `filename`, and divides it into logical lines.

    Returns a list of (filename, line number, line text) triples.

    If `filedata` is given, it should be a unicode string giving the file
    contents. In that case, `filename` need not exist.
    c                    sN   |   d¡}t|ƒd@ dkr$|   d¡S d|   d¡v r<|   d¡S |ˆ  |   d¡ S )Nr$   r   rQ   é   )rM   r0   )rN   Úbrackets©Úprefixr   r    Úmunge_stringæ   s    


z(list_logical_lines.<locals>.munge_stringÚrbrG   Úpython_strictNú

r   õ   ï»¿r$   ú	z1Tab characters are not allowed in Ren'Py scripts.r   r#   z^\s*$z úr%   rj   z\
z([{z}])ú#z"'`FTé   z[__z(\.|\[+)__(\w+)rQ   i   z:Overly long logical line. (Check strings and parenthesis.))r   r7   zBis not terminated with a newline. (Check strings and parenthesis.))Úoriginal_filenamer   ÚreadrH   rc   rZ   r0   r   ÚgameÚcontextÚ
init_phaseÚ
scripteditr8   ÚfilesÚaddÚLiner"   r.   rW   ÚmatchÚappendÚ	end_delimÚendÚstartÚtextÚ	full_textrX   r   )r   ÚfiledataÚ
linenumberÚ	add_linesrn   ÚdataÚfrY   r4   r6   r8   Úlen_datar   Ústart_numberÚ
parendepthÚlocÚendposÚstartposr;   ÚdelimÚescapeÚtriplequoteÚsÚwordÚmagicrƒ   Úrestr   rl   r    Úlist_logical_linesÜ   sþ    
.












.







2









r™   c                    sT   dd„ ‰ ‡ ‡‡fdd„‰ˆrFˆd \}}}ˆ |ƒd dkrFt ||dƒ‚ˆddƒd S )aE  
    This takes as input the list of logical line triples output from
    list_logical_lines, and breaks the lines into blocks. Each block
    is represented as a list of (filename, line number, line text,
    block) triples, where block is a block list (which may be empty if
    no block is associated with this line.)
    c                 S   s:   d}d}| | dkr*|d7 }|d7 }qq*q|| |d … fS )Nr   r)   r$   r   )r<   ÚdepthÚindexr   r   r    Údepth_splitÓ  s    z(group_logical_lines.<locals>.depth_splitc           
         sŽ   g }d }| t ˆƒk r†ˆ|  \}}}ˆ |ƒ\}}||k r8q†|d u rD|}||krXt||dƒ‚| d7 } ˆ| |d ƒ\}	} | ||||	f¡ q|| fS )NzIndentation mismatch.r$   )r0   r"   r   )
r:   Ú	min_depthrY   rš   r   r4   r…   Ú
line_depthr˜   Úblock©rœ   Úgll_corer8   r   r    r¡   è  s    z%group_logical_lines.<locals>.gll_corer   z(Unexpected indentation at start of file.)r"   )r8   r   r4   r…   r   r    r    Úgroup_logical_linesÉ  s    
r¢   )ú$ÚasÚatÚbehindÚcallÚ
expressionÚhideÚifÚinÚimageÚinitÚjumpÚmenuÚonlayerÚpythonÚreturnÚsceneÚshowÚwithÚwhileÚzorderÚ	transform)z<>z<<z<=ú<z>>z>=ú>z!=z==ú|r*   ú&ú+ú-z**Ú*z//r[   ú%ú~)z\bor\bz\band\bz\bnot\bz\bin\bz\bis\br»   c                 C   s   g | ]}t  |¡‘qS r   )rW   r“   )Ú.0r:   r   r   r    Ú
<listcomp>O  ó    rÃ   z0[a-zA-Z_\u00a0-\ufffd][0-9a-zA-Z_\u00a0-\ufffd]*z5[-0-9a-zA-Z_\u00a0-\ufffd][-0-9a-zA-Z_\u00a0-\ufffd]*c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚSubParsezs
    This represents the information about a subparse that can be provided to
    a creator-defined statement.
    c                 C   s
   || _ d S r=   )rŸ   )r3   rŸ   r   r   r    r2   [  s    zSubParse.__init__c                 C   s*   | j s
dS d | j d j| j d j¡S d S )Nz<SubParse empty>z<SubParse {}:{}>r   )rŸ   Úformatr   rˆ   r>   r   r   r    Ú__repr__^  s    zSubParse.__repr__N)r@   rA   rB   rE   r2   rÇ   r   r   r   r    rÅ   U  s   rÅ   c                   @   sŽ  e Zd ZdZdadd„Zdd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Z	dd„ Z
ejdd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zdbd"d#„Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ Zdcd4d5„Zd6d7„ Zd8d9„ Zd:d;„ Z d<d=„ Z!d>d?„ Z"dddAdB„Z#dedCdD„Z$dEdF„ Z%dfdGdH„Z&dIdJ„ Z'dKdL„ Z(dMdN„ Z)dOdP„ Z*dQdR„ Z+dgdSdT„Z,dUdV„ Z-dWdX„ Z.dYdZ„ Z/d[d\„ Z0d]d^„ Z1dhd_d`„Z2dS )iÚLexerz±
    The lexer that is used to lex script files. This works on the idea
    that we want to lex each line in a block individually, and use
    sub-lexers to lex sub-blocks.
    Fr   Nrq   c                 C   sd   || _ || _|| _d| _d| _d| _d| _d| _g | _|| _	d| _
d| _d| _d| _|| _|| _d S )NFéÿÿÿÿr#   r   )r­   Úinit_offsetrŸ   Úeobr   r   r…   r4   ÚsubblockÚglobal_labelr6   Úword_cache_posÚword_cache_newposÚ
word_cacheÚmonologue_delimiterÚ	subparses)r3   rŸ   r­   rÊ   rÍ   rÑ   rÒ   r   r   r    r2   m  s     zLexer.__init__c                 C   sT   |  j d7  _ | j t| jƒkr(d| _dS | j| j  \| _| _| _| _d| _d| _	dS )a'  
        Advances this lexer to the next line in the block. The lexer
        starts off before the first line, so advance must be called
        before any matching can be done. Returns True if we've
        successfully advanced to a line in the block, or False if we
        have advanced beyond all lines in the block. In general, once
        this method has returned False, the lexer is in an undefined
        state, and it doesn't make sense to call any method other than
        advance (which will always return False) on the lexer.
        r$   TFr   rÉ   )
r   r0   rŸ   rË   r   r4   r…   rÌ   r6   rÎ   r>   r   r   r    Úadvance‰  s    zLexer.advancec                 C   sF   |  j d8  _ d| _| j| j  \| _| _| _| _t| jƒ| _d| _	dS )z®
        Puts the parsing point at the end of the previous line. This is used
        after renpy_statement to prevent the advance that Ren'Py statements
        do.
        r$   FrÉ   N)
r   rË   rŸ   r   r4   r…   rÌ   r0   r6   rÎ   r>   r   r   r    Ú	unadvance¡  s
    zLexer.unadvancec                 C   sT   | j r
dS | jt| jƒkrdS t |tj¡ | j| j¡}|s@dS | ¡ | _| 	d¡S )a  
        Tries to match the given regexp at the current location on the
        current line. If it succeds, it returns the matched text (if
        any), and updates the current position to be after the
        match. Otherwise, returns None and the position is unchanged.
        Nr   )
rË   r6   r0   r…   rW   ÚcompileÚDOTALLr€   rƒ   rM   )r3   ÚregexprN   r   r   r    Úmatch_regexp®  s    
zLexer.match_regexpc                 C   s   |   d¡ dS )zQ
        Advances the current position beyond any contiguous whitespace.
        z(\s+|\\\n)+N)rØ   r>   r   r   r    Úskip_whitespaceÅ  s    zLexer.skip_whitespacec                 C   s   |   ¡  |  |¡S )zÁ
        Matches something at the current position, skipping past
        whitespace. Even if we can't match, the current position is
        still skipped past the leading whitespace.
        )rÙ   rØ   )r3   r×   r   r   r    r€   Î  s    zLexer.matchc                 C   s    | j }|  ¡ |kr|S || _ dS )zÓ
        Matches a keyword at the current position. A keyword is a word
        that is surrounded by things that aren't words, like
        whitespace. (This prevents a keyword from matching a prefix.)
        r#   )r6   r–   )r3   r–   Úoldposr   r   r    ÚkeywordØ  s
    zLexer.keywordc              
   c   s@   z
dV  W n0 t y: } zt |j¡ W Y d}~n
d}~0 0 dS )zm
        Catches errors, then causes the line to advance if it hasn't been
        advanced already.
        N)r"   Úparse_errorsr   r1   )r3   Úer   r   r    Úcatch_erroræ  s    
zLexer.catch_errorc                 C   sF   | j dkr*| jr*| jd \| _| _| _| _t| j| j|| j| jƒ‚dS )zc
        Convenience function for reporting a parse error at the current
        location.
        rÉ   r   N)r   rŸ   r   r4   r…   rÌ   r"   r6   )r3   r5   r   r   r    Úerrorò  s    zLexer.errorc                 C   s   |   ¡  | jt| jƒkS )z¤
        Returns True if, after skipping whitespace, the current
        position is at the end of the end of the current line, or
        False otherwise.
        )rÙ   r6   r0   r…   r>   r   r   r    Úeolý  s    z	Lexer.eolc                 C   s   |   ¡ s|  d¡ dS )zG
        If we are not at the end of the line, raise an error.
        zend of line expected.N)rà   rß   r>   r   r   r    Ú
expect_eol  s    zLexer.expect_eolc                 C   s(   | j r$|  ¡ }| ¡  | d| ¡ dS )zz
        Called to indicate this statement does not expect a block.
        If a block is found, raises an error.
        zoLine is indented, but the preceding %s statement does not expect a block. Please check this line's indentation.N)rÌ   Úsubblock_lexerrÓ   rß   )r3   ÚstmtÚllr   r   r    Úexpect_noblock  s    zLexer.expect_noblockc                 C   s   | j s|  d| ¡ dS )zk
        Called to indicate that the statement requires that a non-empty
        block is present.
        z%s expects a non-empty block.N)rÌ   rß   )r3   rã   r   r   r    Úexpect_block  s    zLexer.expect_blockc                 C   s
   t | jƒS )zL
        Called to check if the current line has a non-empty block.
        )ÚboolrÌ   r>   r   r   r    Ú	has_block#  s    zLexer.has_blockc                 C   s(   | j p|}t| j|| j| j| j| jdS )zk
        Returns a new lexer object, equiped to parse the block
        associated with this line.
        )r­   rÊ   rÍ   rÑ   rÒ   )r­   rÈ   rÌ   rÊ   rÍ   rÑ   rÒ   )r3   r­   r   r   r    râ   )  s    
zLexer.subblock_lexerc                 C   s”   |   d¡}|du r|   d¡}|du r.|   d¡}|du r:dS |d dkrXd}|dd… }nd	}|dd
… }dd„ }|st dd|¡}t d||¡}|S )a'  
        Lexes a string, and returns the string to the user, or None if
        no string could be found. This also takes care of expanding
        escapes and collapsing whitespace.

        Be a little careful, as this can return an empty string, which is
        different than None.
        zr?"([^\\"]|\\.)*"Nzr?'([^\\']|\\.)*'zr?`([^\\`]|\\.)*`r   ÚrTr$   FrÉ   c                 S   sr   |   d¡}|dkrdS |dkr"dS |dkr.dS |dkr:d	S |d
 dkrj|   d¡}|rntt|   d¡dƒƒS n|S d S ©Nr$   Ú{z{{ú[z[[rÀ   z%%Únr   r   Úurj   é   ©rM   r   Úint©rN   r;   Úgroup2r   r   r    ÚdequoteQ  s    

zLexer.string.<locals>.dequoteú\s+r)   ú\\(u([0-9a-fA-F]{1,4})|.))r€   rW   rX   )r3   r•   Úrawrô   r   r   r    Ústring3  s"    



zLexer.stringc                 C   sÔ   |   d¡}|du r|   d¡}|du r.|   d¡}|du r:dS |d dkrXd}|dd… }nd	}|d
d… }dd„ }|sÐt dd|¡}g }| | j¡D ]8}| ¡ }|s¤q’t dd|¡}t d||¡}| |¡ q’|S |S )zú
        Lexes a triple quoted string, intended for use with monologue mode.
        This is about the same as the double-quoted strings, except that
        runs of whitespace with multiple newlines are turned into a single
        newline.
        zr?"""([^\\"]|\\.)*"""Nzr?'''([^\\']|\\.)*'''zr?```([^\\`]|\\.)*```r   ré   Tr$   Frv   éýÿÿÿc                 S   sr   |   d¡}|dkrdS |dkr"dS |dkr.dS |dkr:d	S |d
 dkrj|   d¡}|rntt|   d¡dƒƒS n|S d S rê   rð   rò   r   r   r    rô   ˆ  s    

z$Lexer.triple_string.<locals>.dequotez *\n *r   rõ   r)   rö   )r€   rW   rX   r/   rÑ   Ústripr   )r3   r•   r÷   rô   rY   r   r   r    Útriple_stringl  s2    


zLexer.triple_stringc                 C   s
   |   d¡S )zf
        Tries to parse an integer. Returns a string containing the
        integer, or None.
        z(\+|\-)?\d+©r€   r>   r   r   r    Úinteger±  s    zLexer.integerc                 C   s
   |   d¡S )zk
        Tries to parse a number (float). Returns a string containing the
        number, or None.
        z((\+|\-)?(\d+\.?\d*|\.\d+)([eE][-+]?\d+)?rü   r>   r   r   r    Úfloat¹  s    zLexer.floatc                 C   s
   |   d¡S )zG
        Matches the characters in an md5 hash, and then some.
        z\w+rü   r>   r   r   r    ÚhashÁ  s    z
Lexer.hashc                 C   s>   | j | jkr| j| _ | jS | j | _|  t¡}|| _| j | _|S )z?
        Parses a name, which may be a keyword or not.
        )r6   rÎ   rÏ   rÐ   r€   Úword_regexp)r3   rY   r   r   r    r–   È  s    
z
Lexer.wordc                 C   s`   | j }|  ¡ }|dks&|dks&|dkrJ| j| j | j d … dv rJ|| _ dS |tv r\|| _ dS |S )zG
        This tries to parse a name. Returns the name or None.
        ré   rî   Úurr$   ©r(   r'   r&   N)r6   r–   r…   ÚKEYWORDS©r3   rÚ   rY   r   r   r    ÚnameØ  s    z
Lexer.namec                 C   s$   |r |d dkr |  d¡d | _dS )z¿
        Set current global_label, which is used for label_name calculations.
        label can be any valid label or None, but this has only effect if label
        has global part.
        r   Ú.N)r/   rÍ   )r3   Úlabelr   r   r    Úset_global_labelë  s    zLexer.set_global_labelc                 C   sš   | j }d}|  ¡ }|sN|  d¡r&| js0|| _ dS | j}|  ¡ }|s†|| _ dS n8|  d¡r†|rp|| jkrp|| _ dS |  ¡ }|s†|| _ dS |sŽ|S |d | S )a  
        Try to parse label name. Returns name in form of "global.local" if local
        is present, "global" otherwise; or None if it doesn't parse.

        If declare is True, allow only such names that are valid for declaration
        (e.g. forbid global name mismatch)
        Nú\.r  )r6   r  r€   rÍ   )r3   ÚdeclareÚold_posÚ
local_nameÚglobal_namer   r   r    Ú
label_nameô  s.    	
zLexer.label_namec                 C   s   | j ddS )z>
        Same as label_name, but set declare to True.
        T)r
  )r  r>   r   r   r    Úlabel_name_declare  s    zLexer.label_name_declarec                 C   sZ   | j }|  t¡}|dks |dkrD| j| j | j d … dv rD|| _ dS |tv rV|| _ dS |S )zˆ
        Matches a word that is a component of an image name. (These are
        strings of numbers, letters, and underscores.)
        ré   rî   r$   r  N)r6   r€   Úimage_word_regexpr…   r  r  r   r   r    Úimage_name_component"  s    
zLexer.image_name_componentc                 C   sÞ   |   ¡ rdS | j}| j| j }dD ]D}||kr0q"|  jd7  _| jt| jƒkrZ|| _ dS | j| j }q"|dvrz|| _dS |}|  jd7  _|   ¡ rž|  d¡ | j| j }||kr´qÌ|dkr~|  jd7  _q~|  jd7  _dS )zÞ
        This tries to match a python string at the current
        location. If it matches, it returns True, and the current
        position is updated to the end of the string. Otherwise,
        returns False.
        F)rî   ré   r‹   r$   )r(   r'   z)end of line reached while parsing string.r%   T)rà   r6   r…   r0   rß   )r3   r  r;   Úmodr’   r   r   r    Úpython_string6  s4    
zLexer.python_stringc                 C   sB   |   ¡ }|sdS |  d¡r>|   ¡ }|s0|  d¡ |d| 7 }q|S )aQ  
        This tries to match a dotted name, which is one or more names,
        separated by dots. Returns the dotted name if it can, or None
        if it cannot.

        Once this sees the first name, it commits to parsing a
        dotted_name. It will report an error if it then sees a dot
        without a name behind it.
        Nr	  zexpecting name.r  )r  r€   rß   )r3   rY   rí   r   r   r    Údotted_nameh  s    

zLexer.dotted_namec                 C   s   |s|S t j || j| j¡S r=   )r   ÚastÚPyExprr   r4   )r3   r•   Úexprr   r   r    r    s    z
Lexer.exprTc                 C   sx   | j }|  ¡ sf| j| j  }||v r:|  | j|| j … |¡S |dv rL|  ¡  q|  ¡ rVq|  j d7  _ q|  d| ¡ dS )a#  
        This matches python code up to, but not including, the non-whitespace
        delimiter characters. Returns a string containing the matched code,
        which may be empty if the first thing is the delimiter. Raises an
        error if EOL is reached before the delimiter.
        z'"r$   z(reached end of line when expecting '%s'.N)r6   rà   r…   r  r  Úparenthesised_pythonrß   )r3   r’   r  r„   r;   r   r   r    Údelimited_python‡  s    zLexer.delimited_pythonc                 C   s.   |   dd¡}|s|  d¡ |  | ¡ |¡}|S )zk
        Returns a python expression, which is arbitrary python code
        extending to a colon.
        ú:Fzexpected python_expression)r  rß   r  rú   )r3   r  ÚperY   r   r   r    Úpython_expression£  s
    
zLexer.python_expressionc                 C   s¬   | j | j }|dkr@|  jd7  _|  dd¡ |  jd7  _dS |dkrt|  jd7  _|  dd¡ |  jd7  _dS |dkr¨|  jd7  _|  d	d¡ |  jd7  _dS dS )
zÊ
        Tries to match a parenthesised python expression. If it can,
        returns true and updates the current position to be after the
        closing parenthesis. Returns False otherwise.
        ú(r$   ú)FTrì   ú]rë   Ú})r…   r6   r  )r3   r;   r   r   r    r  ²  s"    zLexer.parenthesised_pythonc                 C   sÔ   | j }|  t¡rq|  ¡ rq¤|  ¡ s>|  ¡ s>|  ¡ s>|  ¡ s>q¤|  ¡  |  ¡ rPq€|  d¡rr|  	¡ }|s>|  
d¡ q>|  ¡ r€q>q€q>|r|  t¡rq|r¤|  d¡r¤qq¤q| j|| j …  ¡ }|sÀdS tj || j| j¡S )zo
        Tries to parse a simple_expression. Returns the text if it can, or
        None if it cannot.
        r	  zexpecting name after dot.ú,N)r6   r€   Úoperator_regexprà   r  r  rþ   r  rÙ   r–   rß   r…   rú   r   r  r  r   r4   )r3   ÚcommaÚoperatorr„   rí   r…   r   r   r    Úsimple_expressionÏ  sB    
ÿþý

zLexer.simple_expressionc                 C   s   | j ddS )zt
        One or more simple expressions, separated by commas, including an
        optional trailing comma.
        T)r#  ©r%  r>   r   r   r    Úcomma_expression  s    zLexer.comma_expressionc                 C   s   | j ddS )z=
        Parses the name portion of a say statement.
        F)r$  r&  r>   r   r   r    Úsay_expression  s    zLexer.say_expressionc                 C   s&   | j | j| j| j| j| jtjj 	¡ fS )z
        Returns an opaque representation of the lexer state. This can be
        passed to revert to back the lexer up.
        )
r   r   r4   r…   rÌ   r6   r   r  r  Ú
checkpointr>   r   r   r    r)    s    zLexer.checkpointc                 C   sT   |\| _ | _| _| _| _| _}tjj 	|¡ d| _
| j t| jƒk rJd| _nd| _dS )z
        Reverts the lexer to the given state. State must have been returned
        by a previous checkpoint operation on this lexer.
        rÉ   FTN)r   r   r4   r…   rÌ   r6   r   r  r  ÚrevertrÎ   r0   rŸ   rË   )r3   ÚstateÚpyexpr_checkpointr   r   r    r*  "  s    zLexer.revertc                 C   s   | j | jfS )z–
        Returns a (filename, line number) tuple representing the current
        physical location of the start of the current logical line.
        )r   r4   r>   r   r   r    Úget_location2  s    zLexer.get_locationc                 C   sJ   t |tƒr|p|}|  |¡}n|p(|jj}|ƒ }|du rF|  d| ¡ |S )zþ
        Tries to parse thing, and reports an error if it cannot be done.

        If thing is a string, tries to parse it using
        self.match(thing). Otherwise, thing must be a method on this lexer
        object, which is called directly.
        Nzexpected '%s' not found.)r,   r   r€   Ú__func__r@   rß   )r3   Úthingr  rY   r   r   r    Úrequire:  s    	
zLexer.requirec                 C   s<   |   ¡  | j}t| jƒ| _tj | j|d…  ¡ | j| j	¡S )z 
        Skips whitespace, then returns the rest of the current
        line, and advances the current position to the end of
        the current line.
        N)
rÙ   r6   r0   r…   r   r  r  rú   r   r4   ©r3   r6   r   r   r    r˜   O  s    z
Lexer.restc                 C   s$   | j }t| jƒ| _ | j|d…  ¡ S )zG
        Like rest, but returns a string rather than a PyExpr.
        N)r6   r0   r…   rú   r1  r   r   r    Úrest_statement\  s    zLexer.rest_statementc                    s8   g ‰t ƒ ‰ | jˆ _‡ ‡‡fdd„‰ˆ| jdƒ d ˆ¡S )z¾
        Returns the subblock of this code, and subblocks of that
        subblock, as indented python code. This tries to insert
        whitespace to ensure line numbers match up.
        c                    sv   | D ]l\}}}}ˆ j |k r8ˆ |d ¡ ˆ  j d7  _ q|| d }ˆ |¡ ˆ  j | d¡7  _ ˆ||d ƒ qd S )Nr   r$   z    )r   r   Úcount)rŸ   ÚindentÚ_fnÚlnr…   rÌ   Úlinetext©ÚoÚprocessrY   r   r    r:  q  s    

z#Lexer.python_block.<locals>.processr#   )rC   r4   r   rÌ   r.   r>   r   r8  r    Úpython_blocke  s    zLexer.python_blockc                 C   s   t | ƒS )zo
        Returns an Argument object if there is a list of arguments, or None
        there is not one.
        )Úparse_argumentsr>   r   r   r    Ú	argumentsƒ  s    zLexer.argumentsc                 C   sJ   | j du rtdƒ‚t| ƒ}|  ¡  t|tƒs2|g}t|ƒ}| j  |¡ |S )zÆ
        Parses the remainder of the current line as a statement in the
        Ren'Py script language. Returns a SubParse corresponding to the
        AST node generated by that statement.
        NzHA renpy_statement can only be parsed inside a creator-defined statement.)rÒ   r   Úparse_statementrÔ   r,   r-   rÅ   r   )r3   rŸ   Úspr   r   r    Úrenpy_statement‹  s    

zLexer.renpy_statementc              
   C   sÖ   | j d u rtdƒ‚| jdk r$|  ¡  g }| js–z,t| ƒ}t|tƒrN| |¡ n
| 	|¡ W q( t
y’ } z t 	|j¡ |  ¡  W Y d }~q(d }~0 0 q(|s¾|r´| 	t |  ¡ ¡¡ n
|  d¡ t|ƒ}| j  	|¡ |S )NzDA renpy_block can only be parsed inside a creator-defined statement.r   z*At least one Ren'Py statement is expected.)rÒ   r   r   rÓ   rË   r>  r,   r-   Úextendr   r"   rÜ   r1   r  ÚPassr-  rß   rÅ   )r3   ÚemptyrŸ   rã   rÝ   r?  r   r   r    Úrenpy_block   s*    


 
zLexer.renpy_block)Fr   Nrq   N)F)F)T)T)FT)N)F)3r@   rA   rB   rE   r2   rÓ   rÔ   rØ   rÙ   r€   rÛ   Ú
contextlibÚcontextmanagerrÞ   rß   rà   rá   rå   ræ   rè   râ   rø   rû   rý   rþ   rÿ   r–   r  r  r  r  r  r  r  r  r  r  r  r%  r'  r(  r)  r*  r-  r0  r˜   r2  r;  r=  r@  rD  r   r   r   r    rÈ   f  s^   
	


	

9E	
(2


=
	rÈ   c           	      C   sÒ   |   ¡ g}|  | j¡g}| |   ¡ ¡ |  ¡ }|s<| ¡  qL| | ¡ ¡ q|r†| |   ¡ ¡ |  ¡ }|dur~| t|ƒ¡ n| ¡  |rÊt||ƒD ]4\}}|r”|d dkr”|  	|¡ |  
¡  |  d¡ q”t|ƒS )zo
    This parses an image name, and returns it as a tuple. It requires
    that the image name be present.
    Nr   r¾   z/image name components may not begin with a '-'.)r)  r0  r  r   Úpoprú   r%  r   Úzipr*  rÙ   rß   Útuple)	r<   rø   ÚnodashÚpointsrY   rí   r•   r:   Úpr   r   r    Úparse_image_nameÄ  s*    

rM  c                 C   s8   |   | j¡g}|  d¡sq4|  ¡ }|s(q4| |¡ q|S )z¡
    This parses a comma-separated list of simple_expressions, and
    returns a list of strings. It requires at least one
    simple_expression be present.
    r!  )r0  r%  r€   r   )r<   rY   rÝ   r   r   r    Úparse_simple_expression_listí  s    
rN  c           	      C   sL  d}d}g }d}g }|   d¡s(|   d¡r@|  | j¡}| ¡ f}nt| dƒ}d}|   d¡rv|rh|  d¡ qN|  | j¡}qN|   d¡rš|r|  d¡ qNt| ƒ}qN|   d	¡rÂ|r´|  d
¡ qN|  | j¡}qN|   d¡rî|durà|  d¡ qN|  | j¡}qN|   d¡r:|r
|  d¡ |  | j¡}| |¡ |  	d¡s
qNq
qNq:qN|||||||fS )z)
    This parses an image specifier.
    Nr¨   r¬   Tr°   z(multiple onlayer clauses are prohibited.r¥   z#multiple at clauses are prohibited.r¤   z#multiple as clauses are prohibited.r·   z'multiple zorder clauses are prohibited.r¦   z'multiple behind clauses are prohibited.r!  )
rÛ   r0  r%  rú   rM  rß   r  rN  r   r€   )	r<   ÚtagÚlayerÚat_listr·   r¦   r¨   Ú
image_nameÚbhtagr   r   r    Úparse_image_specifier  sP    






rT  c                 C   s>   |   ¡ }|  d¡s|S |  | j¡}t |d|¡|t ||¡gS )zà
    Tries to parse the with clause associated with this statement. If
    one exists, then the node is wrapped in a list with the
    appropriate pair of With nodes. Otherwise, just returns the
    statement by itself.
    rµ   ÚNone)r-  rÛ   r0  r%  r  ÚWith)r<   Únoder   r  r   r   r    Ú
parse_withM  s    

þrX  c                 C   s|  |   ¡ }d}d }d}d }d }g }	g }
| ¡ r| d¡rX| |j¡}| ¡  | d¡ q$| d¡r‚| |j¡}| ¡  | d¡ q$| ¡ }| ¡ }t|ƒ}| 	d¡r®t|ƒ}nd }| 
¡ pÀ| ¡ }|d ur |d ur |rä| d¡ |rò| d¡ t|| ¡ ||||dd	}| ¡  | d
¡ q$| |¡ | ¡ }|d u rF| d¡ | ¡ rž|jrb| d¡ |rx|rx| d¡ |r‚d}|	 |dd f¡ |
 d ¡ q$d}d}|
 t|ƒ¡ | d¡rÌ| |j¡}| d¡ | ¡  | d¡ t|  ¡ ƒ}|	 |||f¡ q$|s|  d¡ g }|r*| |¡ | t ||	|||d upF|||
¡¡ t|ƒD ]\}}|rnd|_nd|_qX|S )NFrµ   zwith clauseÚsetzset menuitemú\@z:Say menuitems and captions may not exist in the same menu.z)Only one say menuitem may exist per menu.)Úinteractzsay menuitemzexpected menuitemzlLine is followed by a block, despite not being a menu choice. Did you forget a colon at the end of the line?z:Captions and say menuitems may not exist in the same menu.TÚTruerª   r  zchoice menuitemz"Menu does not contain any choices.ÚnormalÚforce)râ   rÓ   rÛ   r0  r%  rá   rå   r)  Úsay_attributesr€   rû   rø   rß   Ú
finish_sayr-  r*  rà   rÌ   r   r<  r  ræ   Úparse_blockr  ÚMenuÚ	enumerateÚrollback)Ústmtlr   r=  r<   Ú
has_choiceÚsay_astÚhas_captionÚwith_rY  ÚitemsÚitem_argumentsr+  ÚwhoÚ
attributesÚtemporary_attributesÚwhatr  Ú	conditionrŸ   rY   r›   r:   r   r   r    Ú
parse_menua  sŒ    




















&
rq  c                    s\  ˆ   d¡sdS g }g }d}d}d}d}d}d}d}	tƒ ‰‡ ‡fdd„}
ˆ   d¡rTq,ˆ   d¡r®ˆ  ˆ j¡}ˆ   d	¡r~ˆ  d
¡ |
|dƒ ˆ   d¡ ˆ   d¡s¦ˆ  d¡ q,nbˆ   d¡r|sÂ|rÌˆ  d¡ d}d}ˆ  ¡ }|durˆ   d	¡rúˆ  d¡ |
|dƒ nˆ   d¡r ˆ  d¡ nðˆ   d¡rx|s8|rDˆ  d¡ n&|durZˆ  d¡ n|sjˆ  d¡ |d d }n˜ˆ  ˆ j¡}|r’d}|}d}ˆ   d	¡rÎˆ  ¡  ˆ  d¡ ¡ }d}	|sèˆ  d¡ n|du rè|	rèˆ  d¡ |
||ƒ | ||f¡ |r| |¡ ˆ   d¡r q,ˆ  d¡ qF|rF|du rFˆ  d¡ t	j
 ||||||¡S )zV
    Parse a list of parameters according to PEP 570 semantic, if one is present.
    ú\(NTFc                    s&   | ˆv rˆ   d|  ¡ n
ˆ | ¡ d S )Nzduplicate argument '%s')rß   r~   )r  Úvalue©r<   Únamesr   r    Úname_parsedû  s    z%parse_parameters.<locals>.name_parsedú\)ú\*\*ú=z.var-keyword argument cannot have default valuer!  z,arguments cannot follow var-keyword argumentú\*z* may appear only oncez1var-positional argument cannot have default valuez/\*zexpected comma between / and *r[   z/ must be ahead of *z/ may appear only oncez$at least one argument must precede /rÉ   r   ú),zempty parameter defaultz-non-default argument follows default argumentz"named arguments must follow bare *)r€   rY  r0  r  rß   rÙ   r  rú   r   r   r  ÚParameterInfo)r<   Ú
parametersÚ
positionalÚextraposÚextrakwÚlast_posonlyÚfirst_kwonlyÚadd_positionalÚpending_kwonlyÚhas_defaultrv  r  Údefaultr   rt  r    Úparse_parametersÛ  s†    


















r‡  c                 C   s4  |   d¡sdS g }tƒ }tƒ }d}d}tƒ }d}d}d}	|   d¡rFq$|   d¡r`d}| |¡ n|   d¡rxd}| |¡ |  ¡ }
|sä|sä|  ¡ }	|	rÆ|   d	¡rÆ|	|v r¶|  d
|	 ¡ n
| |	¡ d}n|rÖ|  d¡ n|  |
¡ d}	|  ¡  | |	|  	d¡f¡ |   d¡rq$|  
d¡ |d7 }q,tj |||¡S )zV
    Parse a list of arguments according to PEP 448 semantics, if one is present.
    rr  Nr   Frw  rx  Trz  ry  zkeyword argument repeated: '%s'z,positional argument follows keyword argumentr{  r!  r$   )r€   rY  r~   r)  r  rß   r*  rÙ   r   r  r0  r   r  ÚArgumentInfo)r<   r=  Ústarred_indexesÚdoublestarred_indexesr›   Úkeyword_parsedru  Úexpect_starredÚexpect_doublestarredr  r+  r   r   r    r<  _  sL    








r<  c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú	ParseTriezI
    This is a trie of words, that's used to pick a parser function.
    c                 C   s   d | _ i | _d S r=   )r†  Úwordsr>   r   r   r    r2   §  s    zParseTrie.__init__c                 C   sN   |s|| _ d S |d }|dd … }|| jvr8tƒ | j|< | j|  ||¡ d S )Nr   r$   )r†  r  rŽ  r~   )r3   r  Úfunctionr7   r˜   r   r   r    r~   «  s    
zParseTrie.addc                 C   s>   |j }| ¡ p| d¡}|| jvr.||_ | jS | j|  |¡S )Nz\$)r6   r–   r€   r  r†  Úparse)r3   r<   r  r–   r   r   r    r‘  ¹  s    
zParseTrie.parseN)r@   rA   rB   rE   r2   r~   r‘  r   r   r   r    rŽ  ¢  s   rŽ  c                    s   ˆ   ¡ ‰ ‡ fdd„}|S )z„
    A function decorator used to declare a statement. Keywords is a string
    giving the keywords that precede the statement.
    c                    s   t  ˆ | ¡ | S r=   )Ú
statementsr~   )r‹   ©Úkeywordsr   r    ÚwrapÑ  s    zstatement.<locals>.wrap)r/   )r”  r•  r   r“  r    Ú	statementÉ  s    r–  rª   c                 C   sø   g }|   | j¡}|   d¡ |  ¡  |  d¡ t|  ¡ ƒ}| ||f¡ |  ¡  |  d¡r¤|   | j¡}|   d¡ |  ¡  |  d¡ t|  ¡ ƒ}| ||f¡ |  ¡  qN|  d¡rì|   d¡ |  ¡  |  d¡ t|  ¡ ƒ}| d|f¡ |  ¡  t	 
||¡S )Nr  zif statementÚelifzelif clauseÚelsezelse clauser\  )r0  r  rá   ræ   ra  râ   r   rÓ   rÛ   r  ÚIf)r<   r   Úentriesrp  rŸ   r   r   r    Úif_statementÛ  s0    








r›  r¶   c                 C   sJ   |   | j¡}|   d¡ |  ¡  |  d¡ t|  ¡ ƒ}|  ¡  t |||¡S )Nr  zwhile statement)	r0  r  rá   ræ   ra  râ   rÓ   r  ÚWhile)r<   r   rp  rŸ   r   r   r    Úwhile_statement  s    

r  Úpassc                 C   s$   |   d¡ |  ¡  |  ¡  t |¡S )Nzpass statement)rå   rá   rÓ   r  rB  ©r<   r   r   r   r    Úpass_statement  s    
r   r¯   c                 C   sŠ   |   d¡ |  ¡ }|  |¡ t| ƒ}|  d¡ |  ¡  t| ||ƒ}|  ¡  g }|rh| t	 
||g d ¡¡ | |¡ |D ]}|d |_qv|S )Nzmenu statementr  r   )ræ   r  r  r<  r0  rá   rq  rÓ   r   r  ÚLabelrA  Ústatement_start)r<   r   r  r=  r¯   rY   r:   r   r   r    Úmenu_statement  s    



r£  r²   c                 C   s6   |   d¡ |  ¡ }|sd }|  ¡  |  ¡  t ||¡S )Nzreturn statement)rå   r˜   rá   rÓ   r  ÚReturn)r<   r   r˜   r   r   r    Úreturn_statement7  s    
r¥  r®   c                 C   sT   |   d¡ |  d¡r&d}|  | j¡}nd}|  | j¡}|  ¡  |  ¡  t |||¡S )Nzjump statementr¨   TF)	rå   rÛ   r0  r%  r  rá   rÓ   r  ÚJump)r<   r   r¨   Útargetr   r   r    Újump_statementE  s    

r¨  r§   c                 C   sú   |   d¡ |  d¡r&d}|  | j¡}nd}|  | j¡}|  d¡ t| ƒ}t ||||¡g}|  d¡rˆ|  | j¡}| 	t 
||g d ¡¡ nNtjjrÖ|tjjv rÖ|r¼tj dttjj| j¡ ntj |ttjj| j¡ | 	t |¡¡ |  ¡  |  ¡  |S )Nzcall statmentr¨   TFrž  Úfrom)rå   rÛ   r0  r%  r  r<  r  ÚCallr  r   r¡  r   r|   r8   Úadd_fromÚreport_missingrw   rƒ   rB  rá   rÓ   )r<   r   r¨   r§  r=  rY   r  r   r   r    Úcall_statementV  s(    



r­  r³   c                 C   sš   |   d¡r|  | j¡}nd}|  ¡ r:|  ¡  t |d |¡S t| ƒ}t |||d ¡}t| |ƒ}|  	d¡r|t
j |  ¡ ¡|_n
|  d¡ |  ¡  |  ¡  |S )Nr°   Úmasteré   r  zscene statement)rÛ   r0  r  rà   rÓ   r  ÚScenerT  rX  r€   r   ÚatlÚ	parse_atlrâ   rå   rá   )r<   r   rP  Úimspecrã   rY   r   r   r    Úscene_statement|  s    



r´  r´   c                 C   sZ   t | ƒ}t ||¡}t| |ƒ}|  d¡r<tj |  ¡ ¡|_n
|  	d¡ |  
¡  |  ¡  |S )Nr  zshow statement)rT  r  ÚShowrX  r€   r   r±  r²  râ   rå   rá   rÓ   )r<   r   r³  rã   rY   r   r   r    Úshow_statement—  s    


r¶  z
show layerc                 C   sr   |   | j¡}|  d¡r t| ƒ}ng }|  d¡r@tj |  ¡ ¡}nd }|  	d¡ |  
¡  |  ¡  t ||||¡}|S )Nr¥   r  zshow layer statement)r0  r  rÛ   rN  r€   r   r±  r²  râ   rå   rá   rÓ   r  Ú	ShowLayer©r<   r   rP  rQ  r±  rY   r   r   r    Úshow_layer_statement¨  s    



r¹  Úcamerac                 C   sr   |   ¡ p
d}|  d¡r t| ƒ}ng }|  d¡r@tj |  ¡ ¡}nd }|  d¡ |  	¡  |  
¡  t ||||¡}|S )Nr®  r¥   r  zcamera statement)r  rÛ   rN  r€   r   r±  r²  râ   rå   rá   rÓ   r  ÚCamerar¸  r   r   r    Úcamera_statementÀ  s    



r¼  r©   c                 C   s8   t | ƒ}t| t ||¡ƒ}|  ¡  |  d¡ |  ¡  |S )Nzhide statement)rT  rX  r  ÚHiderá   rå   rÓ   )r<   r   r³  rY   r   r   r    Úhide_statementØ  s    
r¾  rµ   c                 C   s2   |   | j¡}|  ¡  |  d¡ |  ¡  t ||¡S )Nzwith statement)r0  r%  rá   rå   rÓ   r  rV  )r<   r   r  r   r   r    r   ä  s
    
r   r¬   c                 C   sš   t | dd}|  d¡r4|  ¡  d }tj |  ¡ ¡}n.|  d¡ |  ¡ }|sT|  	d¡ d }|  
d¡ t ||||¡}| jsŽt ||gd| j ¡}|  ¡  |S )NT)rJ  r  ry  úexpected expressionzimage statementéô  )rM  r€   rá   r   r±  r²  râ   r0  r˜   rß   rå   r  ÚImager­   ÚInitrÊ   rÓ   )r<   r   r  r  r±  rY   r   r   r    Úimage_statementî  s     



rÃ  Údefinec           	      C   sþ   |   ¡ }|rt|ƒ}nd}d}|  | j¡}|  d¡rN|d | }|  | j¡}q*|  d¡rp|  dd¡}|  d¡ nd }|  d¡r„d	}n|  d
¡r”d}n|  d¡ d}|  ¡ }|s¸|  d¡ |  d¡ t	 
||||||¡}| jsòt	 ||g|| j ¡}|  ¡  |S )Nr   Ústorer	  r  z\[r  Tz\+=z+=z\|=z|=ry  r¿  zdefine statement)rý   rñ   r0  r–   r€   r  r˜   rß   rå   r  ÚDefiner­   rÂ  rÊ   rÓ   )	r<   r   ÚpriorityrÅ  r  r›   r$  r  rY   r   r   r    Údefine_statement	  s8    







rÈ  r†  c                 C   s°   |   ¡ }|rt|ƒ}nd}d}|  | j¡}|  d¡rN|d | }|  | j¡}q*|  d¡ |  ¡ }|sn|  d¡ |  d¡ t 	||||¡}| j
s¤t ||g|| j ¡}|  ¡  |S )Nr   rÅ  r	  r  ry  r¿  zdefault statement)rý   rñ   r0  r–   r€   r˜   rß   rå   r  ÚDefaultr­   rÂ  rÊ   rÓ   )r<   r   rÇ  rÅ  r  r  rY   r   r   r    Údefault_statement:	  s&    




rÊ  r¸   c                 C   s¢   |   ¡ }|rt|ƒ}nd}|  | j¡}t| ƒ}|rH|js>|jrH|  d¡ |  d¡ |  ¡  t	j
 |  ¡ ¡}t ||||¡}| js–t ||g|| j ¡}|  ¡  |S )Nr   zAtransform statement does not take a variable number of parametersr  )rý   rñ   r0  r  r‡  r€  r  rß   rá   r   r±  r²  râ   r  Ú	Transformr­   rÂ  rÊ   rÓ   )r<   r   rÇ  r  r}  r±  rY   r   r   r    Útransform_statement\	  s     


rÌ  r£   c                 C   s8   |   ¡ }|s|  d¡ |  d¡ |  ¡  tj||ddS )Nzexpected python codezone-line python statementrÅ  ©rÅ  )r2  rß   rå   rÓ   r  ÚPython)r<   r   Úpython_coder   r   r    Úone_line_pythonz	  s    

rÐ  r±   c                 C   sš   d}d}d}|   d¡rd}|   d¡r(d}|   d¡rBd|  | j¡ }|  d¡ |  ¡  |  d	¡ |  ¡ }|  ¡  |r„tj||||d
S tj	||||d
S d S )NFrÅ  ÚearlyTr©   r«   zstore.r  zpython blockrÍ  )
rÛ   r0  r  rá   ræ   r;  rÓ   r  ÚEarlyPythonrÎ  )r<   r   r©   rÑ  rÅ  rÏ  r   r   r    Úpython_statement‡	  s"    




rÓ  r  c                 C   sn   |   | j¡}|  |¡ t| ƒ}|  d¡r.d}nd}|   d¡ |  ¡  t|  |¡ƒ}|  ¡  t	j
|||||dS )Nr©   TFr  )r©   )r0  r  r  r‡  rÛ   rá   ra  râ   rÓ   r  r¡  )r<   r   r­   r  r}  r©   rŸ   r   r   r    Úlabel_statement¥	  s    


rÔ  zinit offsetc                 C   s>   |   d¡ |   | j¡}|  ¡  |  d¡ |  ¡  t|ƒ| _g S )Nry  zinit offset statement)r0  rý   rá   rå   rÓ   rñ   rÊ   )r<   r   Úoffsetr   r   r    Úinit_offset_statement¼	  s    


rÖ  z
init labelc                 C   s   t | |ddS )NT)r­   )rÔ  rŸ  r   r   r    Úinit_label_statementÊ	  s    r×  r­   c                 C   sŒ   |   ¡ }|rt|ƒ}nd}|  d¡rN|  ¡  |  d¡ t|  d¡ƒ}|  ¡  n*| j}zd| _t	| ƒg}W || _n|| _0 t
 |||| j ¡S )Nr   r  zinit statementT)rý   rñ   r€   rá   ræ   ra  râ   rÓ   r­   r>  r  rÂ  rÊ   )r<   r   rL  rÇ  rŸ   Úold_initr   r   r    Úinit_statementÏ	  s    



rÙ  úrpy monologuec                 C   sL   |   d¡rd| _n|   d¡r$d| _n
|  d¡ |  ¡  |  d¡ |  ¡  g S )NÚdoublerq   Úsingler   z.rpy monologue expects either single or double.rÚ  )rÛ   rÑ   rß   rá   rå   rÓ   rŸ  r   r   r    Úrpy_statementñ	  s    



rÝ  c                 C   sH   t j | ¡}|  ¡  |sg S t ||¡}| jsDt ||gd| j ¡}|S ©Niþÿÿ)	r   Ú
screenlangÚparse_screenrÓ   r  ÚScreenr­   rÂ  rÊ   ©r<   r   ÚscreenrY   r   r   r    Úscreen1_statement
  s    rä  c                 C   sD   t jj | |¡}|  ¡  t ||¡}| js@t ||gd| j	 ¡}|S rÞ  )
r   Úsl2Úslparserrà  rÓ   r  rá  r­   rÂ  rÊ   râ  r   r   r    Úscreen2_statement
  s    rç  ZRENPY_SCREEN_LANGUAGEÚ2rã  c                 C   sN   t }|  ¡ }|d urt|ƒ}|dkr.t| |ƒS |dkr@t| |ƒS |  d¡ d S )Nr$   rj   zBad screen language version.)Údefault_screen_languagerý   rñ   rä  rç  rß   )r<   r   Úscreen_languageÚslverr   r   r    Úscreen_statement)
  s    

rì  Útestcasec                 C   sr   |   | j¡}|   d¡ |  ¡  |  d¡ tjj |  ¡ |¡}|  	¡  t
 |||¡}| jsnt
 ||gd| j ¡}|S )Nr  ztestcase statementrÀ  )r0  r  rá   ræ   r   ÚtestÚ
testparserra  râ   rÓ   r  ÚTestcaser­   rÂ  rÊ   )r<   r   r  rî  rY   r   r   r    Útestcase_statement:
  s    

rñ  c           	   	      s^  |  d¡ | ¡  | d¡ | ¡ ‰ g }d }d }‡ fdd„}ˆ  ¡ r*ˆ  d¡rš|d urbˆ  d¡ ˆ  ¡ }z|ˆ  ¡ ƒ}W n t	y–   ˆ  d¡ Y n0 q<ˆ  d¡r|d u r¸ˆ  d	¡ ˆ  ¡ }z|ˆ  ¡ ƒ}W n  t	yð   ˆ  d¡ d }Y n0 | 
tj |||||¡¡ d }d }d }d }q<ˆ  d
¡ q<|r:ˆ  d¡ | ¡  |jrN|S t | ||j¡S )Nr  ztranslate strings statementc                    sN   |   ¡ } z$t| ddtjjdƒ}t|tjjƒW S  tyH   ˆ  	d¡ Y n0 d S )Nz<string>Úevalr$   zcould not parse string)
rú   rÕ   r   r±   Únew_compile_flagsrò  rÅ  Ú__dict__r   rß   )r•   Úbc©rä   r   r    Úparse_stringY
  s    z'translate_strings.<locals>.parse_stringÚoldz(previous string is missing a translationzCould not parse string.Únewzno string to translatezunknown statementz%final string is missing a translation)r0  rá   ræ   râ   rÓ   rÛ   rß   r-  r˜   r   r   r   r  ÚTranslateStringr­   rÂ  rÊ   )	Úinit_locÚlanguager<   rŸ   rø  r   r÷  Únewlocrù  r   rö  r    Útranslate_stringsM
  sL    

	






rþ  Ú	translatec                 C   s  |   | j¡}|dkrd }|   | j¡}|dkr8t||| ƒS |dkr|| j}z*d| _t| |ƒg}t |||¡gW || _S || _0 nB|dkr¾| j}z*d| _t| |ƒg}t 	|||¡gW || _S || _0 |   d¡ |  
¡  |  d¡ t|  ¡ ƒ}|  ¡  t ||||¡t |¡gS )NrU  Ústringsr±   TÚstyler  ztranslate statement)r0  r  rÿ   rþ  r­   rÓ  r  ÚTranslateEarlyBlockÚstyle_statementÚTranslateBlockrá   ræ   ra  râ   rÓ   Ú	TranslateÚEndTranslate)r<   r   rü  Ú
identifierrØ  rŸ   r   r   r    Útranslate_statement’
  s<    þ
þ

r  r  c                    s¬   |   | j¡}d ‰ t ||¡‰‡ ‡fdd„}|| ƒr4q*|  d¡sR|  d¡ |  ¡  n6|  d¡ |  ¡  |  ¡ }| 	¡ rˆ||ƒr~qt| ¡  ql| j
s t |ˆg| j¡‰|  	¡  ˆS )Nc                    sN  |   d¡r.ˆ d ur|  d¡ |  | j¡ˆ_dS |   d¡rBdˆ_dS |   d¡rrˆjd ur`|  d¡ |  | j¡ˆ_dS |   d¡r²|  | j¡}|tj	j
vr¢|  d| ¡ ˆj |¡ dS |   d	¡râˆjd urÐ|  d
¡ |  | j¡ˆ_dS |  ¡ }|d urJ|dkr|tj	j
vr|  d| ¡ |ˆjv r4|  d| ¡ |  | j¡ˆj|< dS dS )NÚiszparent clause appears twice.TÚclearÚtakeztake clause appears twice.Údelzstyle property %s is not known.Úvariantzvariant clause appears twice.Ú
propertiesz style property %s appears twice.F)rÛ   rß   r0  r–   Úparentr
  r  r  r   r  Úprefixed_all_propertiesÚdelattrr   r  r%  r  )r<   Úpropname©r  rY   r   r    Úparse_clauseÌ
  sB    










z%style_statement.<locals>.parse_clauser  zstyle statement)r0  r–   r  ÚStyler€   rå   rá   ræ   râ   rÓ   r­   rÂ  rÊ   )r<   r   r  r  rä   r   r  r    r  Á
  s(    4




r  z
rpy pythonc                 C   s4   |   d¡ |  ¡  |  d¡ t |d¡}|  ¡  |S )NÚ3zrpy statement)r±   r  )r0  rá   rå   r  ÚRPYrÓ   )r<   r   rY   r   r   r    Úrpy_python_3  s    

r  Tc                 C   s  |d u rd S d }d }d }	|   d¡r(d}q|   d¡rR|d urD|  d¡ |  | j¡}q|   d¡rj|  | j¡}	qt| ƒ}
|
d u r|q”|d urŽ|  d¡ |
}qt|tƒrög }|D ]J}|dkrÎ| t	 
|dg d	i f¡¡ q¦| t	j|||||||||	d
	¡ q¦|S t	j|||||||||	d
	S d S )NÚ
nointeractFrµ   z&say can only take a single with clauseÚidz+say can only take a single set of argumentsz{clear}z	nvl clear)Únvlr
  )rm  r[  r=  rn  r  )rÛ   rß   r0  r%  r  r<  r,   r-   r   r  ÚUserStatementÚSay)r<   r   rl  ro  rm  rn  r[  ri  r=  r  ÚargsrY   r:   r   r   r    r`  )  s6    





$r`  c                 C   sN   g }|   d¡}|sd}|  ¡ }|du r(q8| || ¡ q|rFt|ƒ}nd}|S )zH
    Returns a list of say attributes, or None if there aren't any.
    r¾   r#   N)r€   r  r   rI  )r<   rm  rm   Ú	componentr   r   r    r_  ]  s    

r_  c                 C   sÜ   |   ¡ }|  ¡ p|  ¡ }t| |d |ƒ}|d urL|  ¡ rL|  d¡ |  ¡  |S |  |¡ |  ¡ }t	| ƒ}|  
d¡rzt	| ƒ}nd }|  ¡ pŒ|  ¡ }|d urÎ|d urÎt| |||||ƒ}|  ¡  |  d¡ |  ¡  |S |  d¡ d S )Nzsay statementrZ  úexpected statement.)r)  rû   rø   r`  rà   rå   rÓ   r*  r(  r_  r€   rá   rß   )r<   r   r+  ro  rY   rl  rm  rn  r   r   r    Úsay_statementw  s*    




r!  c                 C   s.   |   ¡ }t | ¡}|du r$|  d¡ || |ƒS )aR  
    This parses a Ren'Py statement. l is expected to be a Ren'Py lexer
    that has been advanced to a logical line. This function will
    advance l beyond the last logical line making up the current
    statement, and will return an AST object representing this
    statement, or a list of AST objects representing this statement.
    Nr   )r-  r’  r‘  rß   )r<   r   Úpfr   r   r    r>  ¨  s
    


r>  c              
   C   s~   |   ¡  g }| jszz,t| ƒ}t|tƒr2| |¡ n
| |¡ W q tyv } z t |j	¡ |   ¡  W Y d}~qd}~0 0 q|S )z¤
    This parses a block of Ren'Py statements. It returns a list of the
    statements contained within the block. l is a new Lexer object, for
    this block.
    N)
rÓ   rË   r>  r,   r-   rA  r   r"   rÜ   r1   )r<   rY   rã   rÝ   r   r   r    ra  ¼  s    
 ra  c              
   C   sž   d|  d t j_zt| ||ƒ}t|ƒ}W n2 tyZ } zt |j¡ W Y d}~dS d}~0 0 t	|ƒ}t
|ƒ}trtdS |rš| t |d j|d jfd¡¡ |S )aK  
    Parses a Ren'Py script contained within the file `fn`.

    Returns a list of AST objects representing the statements that were found
    at the top level of the file.

    If `filedata` is given, it should be a unicode string giving the file
    contents.

    If `linenumber` is given, the parse starts at `linenumber`.
    zWhile parsing r  NrÉ   )r   ry   Úexception_infor™   r¢   r"   rÜ   r   r1   rÈ   ra  r  r¤  r   rˆ   )rI   r‡   rˆ   r8   ÚnestedrÝ   r<   rY   r   r   r    r‘  ×  s    "r‘  c                  C   s   t } g a | S r=   )rÜ   )rY   r   r   r    Úget_parse_errorsú  s    r%  c               
   C   sd  t sdS d} tj dd¡\}}|Þ | d¡ td|d td|d td|d t D ]j}| |7 } | d	7 } t|tƒs€t|d
dƒ}td|d t||d ztdƒ t|ƒ W qV ty¾   Y qV0 qVtd|d tdtj	|d ttt
 ¡ ƒ|d W d   ƒ n1 s0    Y  tjj | |¡ z(tjjjdkrHtjj|gddd W n ty^   Y n0 dS )NFr#   z
errors.txtÚwrr   zFI'm sorry, but errors were detected in your script. Please correct the)Úfilez#errors listed below, and try again.rq   rG   rV   zRen'Py Version:Úrunr$   T)Ú	transient)rÜ   r   rß   Úopen_error_fileÚwriteÚprintr,   r   r   ÚversionÚtimeÚctimeÚdisplayÚreport_parse_errorsry   r  Úcommandr   Úlaunch_editor)r†   r‹   Úerror_fnr:   r   r   r    r1    s>    

4r1  )Nr$   F)FF)F)NNT)Nr$   )lÚ
__future__r   r   r   r   r   Úrenpy.compatr   r   r	   r
   r   r   r   r   r   r   r   r   ÚcodecsrW   rR   r.  rE  r   Ú	renpy.astr  rÜ   Úrenpy.parsersupportr   r!   r   r"   ÚobjectrC   r+   rÕ   ÚSÚlllwordrZ   rc   r   rw   r™   r¢   rY  r  Ú	OPERATORSÚESCAPED_OPERATORSr.   r"  r   r  rÅ   rÈ   rM  rN  rT  rX  rq  r‡  r<  rŽ  r’  r–  r›  r  r   r£  r¥  r¨  r­  r´  r¶  r¹  r¼  r¾  rÃ  rÈ  rÊ  rÌ  rÐ  rÓ  rÔ  rÖ  r×  rÙ  rÝ  rä  rç  rñ   ÚenvironÚgetré  rì  rñ  rþ  r  r  r  r`  r_  r!  r>  ra  r‘  r%  r1  r   r   r   r    Ú<module>   sì   87	
 nN      d
)Iz C$
*





%





	

.
!





!


E
.
Y

4
0
#