a
    Lg.t                     @   s   d dl mZ d dlZd dlZd dlmZmZmZmZm	Z	m
Z
mZmZmZ ddlmZ ddlmZmZ ddlmZ erddlmZmZ eee eeef eef ZG d	d
 d
eeef ZG dd deZG dd dZG dd dZdS )    )OrderedDictN)	TYPE_CHECKINGAnyDictListMappingMatchOptionalSetUnion   )
must_match)QAPISemErrorQAPISourceError)QAPISourceInfo)QAPISchemaFeatureQAPISchemaMemberc                       s4   e Zd Zdeeef eed d fddZ  Z	S )QAPIExpressionNQAPIDoc)datainfodocc                    s   t  | || _|| _d S N)super__init__r   r   )selfr   r   r   	__class__ >/home2/Puru_Virtio_Blk/virtio-demo/qemu/scripts/qapi/parser.pyr   1   s    zQAPIExpression.__init__)N)
__name__
__module____qualname__r   strobjectr   r	   r   __classcell__r   r   r   r   r   /   s    
r   c                       s(   e Zd ZdZded fddZ  ZS )QAPIParseErrorz/Error class for all QAPI schema parsing errors.QAPISchemaParser)parsermsgc                    sT   d}|j |j|j D ]&}|dkr4|d d d }q|d7 }qt |j|| d S )Nr   	      )srcline_posposr   r   r   )r   r(   r)   colchr   r   r   r   <   s    
zQAPIParseError.__init__)r    r!   r"   __doc__r#   r   r%   r   r   r   r   r&   :   s   r&   c                   @   s^  e Zd ZdZd+eeee  ee dddZddddZ	d,e
eef eed	 dd
ddZeed	 ddddZeeeeee ed  dddZeeeeddddZd-eddddZeeef dddZee dddZedddZee dd d!Zeeeee  d"d#d$Zd	ee dd%d&Zd	ee dd'd(Zd	dd)d*ZdS ).r'   a  
    Parse QAPI schema source.

    Parse a JSON-esque schema file and process directives.  See
    qapi-code-gen.rst section "Schema Syntax" for the exact syntax.
    Grammatical validation is handled later by `expr.check_exprs()`.

    :param fname: Source file name.
    :param previously_included:
        The absolute names of previously included source files,
        if being invoked from another parser.
    :param incl_info:
       `QAPISourceInfo` belonging to the parent module.
       ``None`` implies this is the root module.

    :ivar exprs: Resulting parsed expressions.
    :ivar docs: Resulting parsed documentation blocks.

    :raise OSError: For problems reading the root schema document.
    :raise QAPIError: For errors in the schema source.
    N)fnamepreviously_included	incl_infoc                 C   sr   || _ |pt | _| jtj| j  d| _t| j || _	d | _
d| _d| _d | _d| _g | _g | _|   d S )N r   )_fnameset	_includedaddospathabspathr-   r   r   tokr/   cursorvalr.   exprsdocs_parse)r   r3   r4   r5   r   r   r   r   \   s    zQAPISchemaParser.__init__returnc                 C   s  d}t | jddd}| | _W d   n1 s40    Y  | jdksV| jd dkrd|  jd7  _|   | jdur
| j}| jdkr| | |  }| j	
| ql|  }t|tst|d	d
|v rn| | t|dkrt|d|d
 }t|tst|dtjtj| j|}| td
|i| | |||| j}|r| j|j | j	|j	 nd|v r| | t|dkrt|d|d }t|tst|d| D ]\}	}
| |	|
| qn(|r|jst|jd| ||| d}ql| | dS )zz
        Parse the QAPI schema document.

        :return: None.  Results are stored in ``.exprs`` and ``.docs``.
        Nrzutf-8)encodingr6   
#z&top-level expression must be an objectincluder   zinvalid 'include' directivez#value of 'include' must be a stringpragmazinvalid 'pragma' directivez#value of 'pragma' must be an objectz!definition documentation required)openr7   readr-   acceptr>   r   reject_expr_docget_docrB   appendget_expr
isinstancedictr   lenr#   r;   r<   joindirname	_add_exprr   _includer9   rA   extenditems_pragmasymbol)r   Zcur_docfpr   exprrK   
incl_fnameZexprs_includerL   namevaluer   r   r   rC   t   sn    (









zQAPISchemaParser._parser   )r`   r   r   rE   c                 C   s   | j t||| d S r   )rA   rR   r   )r   r`   r   r   r   r   r   rY      s    zQAPISchemaParser._add_expr)r   rE   c                 C   s    | r| j rt| jd| j  d S )Nz8documentation for '%s' is not followed by the definition)r^   r   r   )r   r   r   r   rP      s    
z QAPISchemaParser.reject_expr_doc)rK   r   ra   r4   rE   c              
   C   s   t j|}|}|r<|t j|jkr4t|d|  |j}q||v rHd S zt|||W S  ty } z&t|d| d|j |W Y d }~n
d }~0 0 d S )Nzinclusion loop for %szcan't read include file 'z': )	r;   r<   r=   r3   r   parentr'   OSErrorstrerror)rK   r   ra   r4   Zincl_abs_fnameinferrr   r   r   rZ      s"    zQAPISchemaParser._include)rb   rc   r   rE   c                    s   t ttt  d fdd} j}| dkrDt|ts<t d||_nf| dkrZ|| ||_nP| dkrp|| ||_	n:| dkr|| ||_
n$| d	kr|| ||_nt d
|  d S )N)rb   rc   rE   c                    s.   t |trtdd |D r*t d|  |S )Nc                 s   s   | ]}t |t V  qd S r   )rT   r#   ).0eltr   r   r   	<genexpr>       zCQAPISchemaParser._pragma.<locals>.check_list_str.<locals>.<genexpr>z#pragma %s must be a list of strings)rT   listanyr   )rb   rc   r   r   r   check_list_str   s    
z0QAPISchemaParser._pragma.<locals>.check_list_strzdoc-requiredz%pragma 'doc-required' must be booleanzcommand-name-exceptionszcommand-returns-exceptionszdocumentation-exceptionszmember-name-exceptionszunknown pragma '%s')r#   r$   r   rL   rT   boolr   doc_requiredcommand_name_exceptionscommand_returns_exceptionsdocumentation_exceptionsmember_name_exceptions)rb   rc   r   rp   rL   r   ro   r   r]      s"    
zQAPISchemaParser._pragmaT)skip_commentrE   c                 C   s  | j | j | _| j| _|  jd7  _d| _| jdkrx| j | j dkrHd}| j d| j| _|sv| j | j| j | _dS q | jdv rdS | jdkr<d}d}| j | j }|  jd7  _|dkrt| d	|r|d
krt| d| d}n$|d
krd}qn|dkr
|| _dS t|dk s&t|dkr0t| d||7 }qq | j d| jrfd| _|  jd7  _dS | j d| jrd| _|  jd7  _dS | jdkr| jt	| j krd| _dS | j
 | _
| j| _q | j s td| j | jd d }t| d|d q dS )a{  
        Read and store the next token.

        :param skip_comment:
            When false, return COMMENT tokens ("#").
            This is used when reading documentation blocks.

        :return:
            None.  Several instance attributes are updated instead:

            - ``.tok`` represents the token type.  See below for values.
            - ``.info`` describes the token's source location.
            - ``.val`` is the token's value, if any.  See below.
            - ``.pos`` is the buffer index of the first character of
              the token.

        * Single-character tokens:

            These are "{", "}", ":", ",", "[", and "]".
            ``.tok`` holds the single character and ``.val`` is None.

        * Multi-character tokens:

          * COMMENT:

            This token is not normally returned by the lexer, but it can
            be when ``skip_comment`` is False.  ``.tok`` is "#", and
            ``.val`` is a string including all chars until end-of-line,
            including the "#" itself.

          * STRING:

            ``.tok`` is "'", the single quote.  ``.val`` contains the
            string, excluding the surrounding quotes.

          * TRUE and FALSE:

            ``.tok`` is either "t" or "f", ``.val`` will be the
            corresponding bool value.

          * EOF:

            ``.tok`` and ``.val`` will both be None at EOF.
        r   NrJ   FrI   z{}:,[]'r6   zmissing terminating "'"\zunknown escape \%sT       zfunny character in stringtrue   false   z[^[\]{}:,\s']+z
stray '%s'r   )r-   r?   r>   r/   r@   findr&   ord
startswithrV   r   	next_liner.   isspacer   group)r   rw   stringZescr1   matchr   r   r   rO      sp    .





zQAPISchemaParser.acceptc                 C   s   t  }| jdkr|   |S | jdkr0t| d| j}t|tsDJ |   | jdkr`t| d|   ||v r~t| d| |  ||< | jdkr|   |S | jdkrt| d|   | jdkr0t| d	q0d S )
N}rx   zexpected string or '}':zexpected ':'zduplicate key '%s',zexpected ',' or '}'zexpected string)r   r>   rO   r&   r@   rT   r#   rS   )r   r`   keyr   r   r   get_memberse  s.    








zQAPISchemaParser.get_membersc                 C   sx   g }| j dkr|   |S | j tdvr2t| d||   | j dkrV|   |S | j dkrjt| d|   q2d S )N]z{['tfz*expected '{', '[', ']', string, or booleanr   zexpected ',' or ']')r>   rO   tupler&   rR   rS   r   r`   r   r   r   
get_values  s    



zQAPISchemaParser.get_valuesc                 C   sx   | j dkr|   |  }nX| j dkr8|   |  }n<| j tdv rjt| jttfsZJ | j}|   n
t	| d|S )N{[z'tfz%expected '{', '[', string, or boolean)
r>   rO   r   r   r   rT   r@   r#   rq   r&   r   r   r   r   rS     s    




zQAPISchemaParser.get_exprc                 C   s   | j dkrt| dt| jts$J | jdrH| jdkrDt| dd S | jdkrVdS | jd dkrnt| d| jd	d   S )
NrJ   z(documentation comment must end with '##'##z/junk after '##' at end of documentation commentr6   r    zmissing space after #   )r>   r&   rT   r@   r#   r   rstrip)r   r   r   r   get_doc_line  s     



zQAPISchemaParser.get_doc_line)r   rE   c                 C   s   t d| S )Nz@([^:]*): *)rer   )r   r   r   r   _match_at_name_colon  s    z%QAPISchemaParser._match_at_name_colonc                 C   s   |  d |  }|dkr8|| |  d |  }q|d u rD|S td| }|sZ|S || d}|  d |  }|d u r|S | |r|S td| }|dkr||k r|r|S t| d| || d}qhd S )NFr6   z\s*z2unexpected de-indent (expected at least %d spaces)T)rO   r   append_liner   endr   r&   )r   r   lineindentZprev_line_blankZ
cur_indentr   r   r   get_doc_indented  s>    







z!QAPISchemaParser.get_doc_indentedc                 C   s:   |  d |  }|d u r|S |dkr*|S || q d S )NFr6   )rO   r   r   )r   r   r   r   r   r   get_doc_paragraph  s    
z"QAPISchemaParser.get_doc_paragraphc           
      C   s  | j dkrt| d| j}| d |  }|d ur|dr|dsVt| d|dd }|spt| d	t||}| d |  }d}|d ur||d
kr| d |  }q|d u rq||dkr|jrt| d| d |  }|d
kr| d |  }q|d urh| 	| }rh|
| j|d || d  }|rZ|| | |}q|jszt| dd}q| 	| }r|rt| d|d |d ur| 	| }r|| j|d || d  }|r|| | |}qd}qtd| }rd|dv rJd|d d}t| |d|dv rvd|d d}t| ||| j|d || d  }|r|| | |}d}q|drt| dq|| j || | |}qnt|}|| j d}	|d ur|| 	| }r<t| d|d |drX|	sXt| d|| | d |  }d}	q|   |  |S )Nr   z1junk after '##' at start of documentation commentF@r   zline should end with ':'r   rH   zname required after '@'r6   z	Features:zduplicated 'Features:' linezfeature descriptions expectedTz'description of '@%s:' follows a sectionz5(Returns|Errors|Since|Notes?|Examples?|TODO)(?!::): *ZNotezThe 'z' section is no longer supported. Please use rST's '.. note::' or '.. admonition:: notes' directives, or another suitable admonition instead.ZExamplezp' section is no longer supported. Please use the '.. qmp-example::' directive, or other suitable markup instead.=z1unexpected '=' markup in definition documentationz-'@%s:' not allowed in free-form documentationz.'=' heading must come first in a comment block)r@   r&   r   rO   r   r   endswithr   featuresr   new_featurer   r   r   r   new_argumentr   r   new_tagged_sectionensure_untagged_sectionr   )
r   r   r   r^   r   Zno_more_argsr   textZemsgfirstr   r   r   rQ     s    



























zQAPISchemaParser.get_doc)NN)N)T)r    r!   r"   r2   r#   r	   r
   r   r   rC   r   r$   rY   staticmethodrP   rZ   r]   rq   rO   r   r   r   r   
_ExprValuerS   r   r   r   r   r   rQ   r   r   r   r   r'   F   sF     
C l 
r'   c                   @   s  e Zd ZdZG dd dZG dd deZd+eee ddd	Z	dd
ddZ
eddddZeeddddZeeeeef ddddZeeddddZeeddddZeddddZdddd d!Zd"dd#d$d%Zedd&d'd(Zdd
d)d*ZdS ),r   a&  
    A documentation comment block, either definition or free-form

    Definition documentation blocks consist of

    * a body section: one line naming the definition, followed by an
      overview (any number of lines)

    * argument sections: a description of each argument (for commands
      and events) or member (for structs, unions and alternates)

    * features sections: a description of each feature flag

    * additional (non-argument) sections, possibly tagged

    Free-form documentation blocks consist only of a body section.
    c                   @   s2   e Zd Zdeee dddZeddddZdS )	zQAPIDoc.SectionNr   tagc                 C   s   || _ || _d| _d S )Nr6   )r   r   r   r   r   r   r   r   r   r     s    zQAPIDoc.Section.__init__r   rE   c                 C   s   |  j |d 7  _ d S )NrI   )r   r   r   r   r   r   r     s    zQAPIDoc.Section.append_line)N)r    r!   r"   r   r	   r#   r   r   r   r   r   r   Section~  s
    	r   c                       s4   e Zd Zeed fddZdddddZ  ZS )	zQAPIDoc.ArgSectionr   c                    s   t  || d | _d S r   )r   r   memberr   r   r   r   r     s    zQAPIDoc.ArgSection.__init__r   Nr   rE   c                 C   s
   || _ d S r   r   r   r   r   r   r   connect  s    zQAPIDoc.ArgSection.connect)r    r!   r"   r   r#   r   r   r%   r   r   r   r   
ArgSection  s   r   N)r   r^   c                 C   sN   || _ || _t|g| _| jd | _i | _i | _d | _d | _	d | _
g | _d S )Nr   )r   r^   r   r   all_sectionsbodyargsr   returnserrorssincesections)r   r   r^   r   r   r   r     s    zQAPIDoc.__init__rD   c                 C   sD   | j D ]8}|jd|_|jd ur|jdkrt|jd|j qd S )NrI   r6   ztext required after '%s:')r   r   stripr   r   r   )r   sectionr   r   r   r     s    
zQAPIDoc.end)r   rE   c                 C   sP   | j r*| j d js*| j d  jd7  _d S | |}| j| | j | d S )NrH   rI   )r   r   r   r   r   rR   )r   r   r   r   r   r   r     s    
zQAPIDoc.ensure_untagged_section)r   r   rE   c                 C   s   |  ||}|dkr0| jr(t|d| || _nF|dkrT| jrLt|d| || _n"|dkrv| jrpt|d| || _| j| | j| d S )NZReturnszduplicated '%s' sectionZErrorsZSince)r   r   r   r   r   r   rR   r   )r   r   r   r   r   r   r   r     s*    zQAPIDoc.new_tagged_section)r   rb   descrE   c                 C   sL   |st |d||v r$t |d| | |d| }| j| |||< d S )Nzinvalid parameter namez'%s' parameter name duplicatedr   )r   r   r   rR   )r   r   rb   r   r   r   r   r   _new_description  s    
zQAPIDoc._new_description)r   rb   rE   c                 C   s   |  ||| j d S r   )r   r   r   r   rb   r   r   r   r     s    zQAPIDoc.new_argumentc                 C   s   |  ||| j d S r   )r   r   r   r   r   r   r     s    zQAPIDoc.new_featurer   c                 C   s   | j d | d S )NrH   )r   r   r   r   r   r   r     s    zQAPIDoc.append_liner   r   c                 C   sp   |j | jvrZ|jsJ | j|jjjvr>t|jd|j|j f t	| jd|j  | j|j < | j|j  
| d S )Nz%s '%s' lacks documentationr   )rb   r   r   r^   rL   ru   r   roler   r   r   r   r   r   r   connect_member  s    

zQAPIDoc.connect_memberr   )featurerE   c                 C   s4   |j | jvrt|jd|j  | j|j  | d S )Nz feature '%s' lacks documentation)rb   r   r   r   r   )r   r   r   r   r   connect_feature  s    zQAPIDoc.connect_feature)r`   rE   c                 C   sR   d|v r&| j rNd|vrNt| j jdn(| j r:t| j jd| jrNt| jjdd S )Ncommandr   z6'Returns' section, but command doesn't return anythingz,'Returns' section is only valid for commandsz+'Errors' section is only valid for commands)r   r   r   r   r   r   r   r   
check_expr  s     zQAPIDoc.check_exprc                 C   s8   t ttjf td ddd}|| jd || jd d S )N)r   whatrE   c                 S   s`   dd |   D }|r\t| |d  jd|t|dkr8dndd|t|dkrRd	nd
f d S )Nc                 S   s   g | ]\}}|j s|qS r   r   )ri   rb   r   r   r   r   
<listcomp>  s   z=QAPIDoc.check.<locals>.check_args_section.<locals>.<listcomp>r   z!documented %s%s '%s' %s not existr   sr6   z', 'doZdoes)r\   r   r   rV   rW   )r   r   Zbogusr   r   r   check_args_section  s    z)QAPIDoc.check.<locals>.check_args_sectionr   r   )r   r#   r   r   r   r   )r   r   r   r   r   check  s
    zQAPIDoc.check)N)r    r!   r"   r2   r   r   r   r	   r#   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   k  s"   

r   ) collectionsr   r;   r   typingr   r   r   r   r   r   r	   r
   r   commonr   errorr   r   sourcer   schemar   r   r$   r#   rq   r   r   r&   r'   r   r   r   r   r   <module>   s"   ,    )