o
    h݊                    @   s   d dl mZ d dlmZmZmZ d dlmZ d dlm	Z	 d dl
mZmZmZ d dlm  mZ d dlZd dlZd dlZeeZG dd deZG d	d
 d
eZdS )    )FeatureLibError)LexerIncludingLexerNonIncludingLexer)VariableScalar)getEncoding)bytechrtobytestostrNc                   @   sd  e Zd ZdZi ZeZdd eddD Zdd eddD Z	
dd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d Zdd  Zdd"d#Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Z d<d= Z!d>d? Z"d@dA Z#dBdC Z$dDdE Z%dFdG Z&dHdI Z'dJdK Z(dLdM Z)dNdO Z*dPdQ Z+dRdS Z,dTdU Z-dVdW Z.dXdY Z/dZd[ Z0d\d] Z1d^d_ Z2d`da Z3e4dbdc Z5e4ddde Z6dfdg Z7dhdi Z8djdk Z9dldm Z:dndo Z;dpdq Z<drds Z=dtdu Z>dvdw Z?dxdy Z@dzd{ ZAd|d} ZBd~d ZCdd ZDdd ZEdd ZFdd ZGdddZHdd ZIdd ZJdd ZKdd ZLdd ZMdd ZNdd ZO	
dddZPdd ZQdd ZRdd ZSdd ZTdd ZUdd ZVdd ZWdd ZXdd ZYdd ZZdd Z[dd Z\dd Z]dddZ^dd Z_dd Z`dd Zadd Zbdd Zcdd ZdddÄ Zeddń ZfdddǄZge4ddɄ Zhdd˄ Zidd̈́ Zjd
S )Parsera
  Initializes a Parser object.

    Example:

        .. code:: python

            from fontTools.feaLib.parser import Parser
            parser = Parser(file, font.getReverseGlyphMap())
            parsetree = parser.parse()

    Note: the ``glyphNames`` iterable serves a double role to help distinguish
    glyph names from ranges in the presence of hyphens and to ensure that glyph
    names referenced in a feature file are actually part of a font's glyph set.
    If the iterable is left empty, no glyph name in glyph set checking takes
    place, and all glyph tokens containing hyphens are treated as literal glyph
    names, not as ranges. (Adding a space around the hyphen can, in any case,
    help to disambiguate ranges from glyph names containing hyphens.)

    By default, the parser will follow ``include()`` statements in the feature
    file. To turn this off, pass ``followIncludes=False``. Pass a directory string as
    ``includeDir`` to explicitly declare a directory to search included feature files
    in.
    c                 C      h | ]}d | qS )zss%02d .0ir   r   k/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/fontTools/feaLib/parser.py	<setcomp>*       zParser.<setcomp>      c                 C   r   )zcv%02dr   r   r   r   r   r   +   r   d   r   TNc                 K   s   d|v rddl m} |dd |rtd|d}|r4tdt|dkr&dnd	d
dd |D f t|| _| j	 | _
t | _t | _t | _t | _| j| jh| _d\| _| _g | _d | _|rftnt}|||d| _i | _| jdd d S )NglyphMapr   )deprecateArgumentz#use 'glyphNames' (iterable) insteadz?'glyphNames' and (deprecated) 'glyphMap' are mutually exclusivez"unsupported keyword argument%s: %sr    sz, c                 s   s    | ]}t |V  qd S N)repr)r   kr   r   r   	<genexpr><   s    z"Parser.__init__.<locals>.<genexpr>NN)
includeDirTcomments)fontTools.misc.loggingToolsr   	TypeErrorpoplenjoinsetglyphNames_astFeatureFiledoc_SymbolTableanchors_glyphclasses_lookups_valuerecords_symbol_tables_next_token_type_next_token_cur_comments_next_token_location_r   r   lexer_missingadvance_lexer_)selffeaturefile
glyphNamesfollowIncludesr    kwargsr   
lexerClassr   r   r   __init__-   s8   

&
zParser.__init__c                 C   s:  | j j}| jdus| jr| jdd | jtju r'|| j	j
| j| jd n| dr4||   n| jtju rB||   n| drO||   n| dr\||   n| dri||   n| d	rx|| jd
d n| dr||   nu| dr||   nh| dr||   n[| dr|| jdd nL| dr||   n?| dr|| jd
d n0| jtju r| j| jv r|| j| j |  n| jtju r| jdkrqtd| j| j| j| jdus| js| jrdd | j  D }tdd!| d| j S )zParse the file, and return a :class:`fontTools.feaLib.ast.FeatureFile`
        object representing the root of the abstract syntax tree containing the
        parsed contents of the file.NTr!   locationincludeanon	anonymous	anchorDeflanguagesystemlookupFvertical	markClassfeatureconditionset	variation)rO   tablevalueRecordDef;zbExpected feature, languagesystem, lookup, markClass, table, or glyph class definition, got {} "{}"c                 S      g | ]
\}}d ||f qS )z %s (first found at %s)r   )r   namelocr   r   r   
<listcomp>   s    
z Parser.parse.<locals>.<listcomp>zMThe following glyph names are referenced but are missing from the glyph set:

)"r,   
statementsr3   r5   r9   cur_token_type_r   COMMENTappendr*   Comment
cur_token_cur_token_location_is_cur_keyword_parse_include_
GLYPHCLASSparse_glyphclass_definition_parse_anonymous_parse_anchordef_parse_languagesystem_parse_lookup_parse_markClass_parse_feature_block_parse_conditionset_parse_table_parse_valuerecord_definition_NAME
extensionsSYMBOLr   formatr8   itemsr'   )r:   rX   errorr   r   r   parseN   sn   










.zParser.parsec           	   	   C   s   |  d | d | j}| jdkr| d |  d d S | jtjkrO|  }| j	|}|d u r:t
d| | j|  d | jj|j|j||jd d |dS | jdd| jdd}}d }| jd	krl| d	 |  }| jdkrz|  }|  }nd
\}}|  d | jj||d ||||dS )N<anchorNULL>zUnknown anchor "%s")rT   contourpointxDeviceTableyDeviceTablerB   Tvariablerw   r   )expect_symbol_expect_keyword_r^   r4   r3   r   rl   expect_name_r.   resolver   r*   Anchorxyrw   expect_number_parse_device_)	r:   rB   rT   	anchordefr   r   rw   rx   ry   r   r   r   parse_anchor_   sV   












zParser.parse_anchor_c                 C   sX   g }| j dkr*|  }|d u r| j dkrq| d |  }|||f | j dks|S )Nrs   mark)r4   r   r}   expect_markClass_reference_r[   )r:   anchorMarksrt   rL   r   r   r   parse_anchor_marks_   s   


zParser.parse_anchor_marks_c                 C   s   |  dsJ | j}|  |  }}d }| jdkr#| d |  }|  }| d | jj|||||d}| j	
|| |S )NrG   rw   rR   )rw   rB   )r_   r^   r   r4   r}   r~   r|   r*   AnchorDefinitionr.   define)r:   rB   r   r   rw   rT   r   r   r   r   rd      s   



zParser.parse_anchordef_c                 C   sn   |  dsJ |  }| j|\}}}|   | d |  }||ks)J d| d | jj|||dS )NrD   }z-bad splitting in Lexer.scan_anonymous_block()rR   rA   )r_   expect_tag_r7   scan_anonymous_blockr9   r|   r*   AnonymousBlock)r:   tag_contentrB   end_tagr   r   r   rc      s   

zParser.parse_anonymous_c                 C   sh   |  dsJ | j}| jdd}|  h}| jdkr&||   | jdks| d | jj|||dS )NAttachTaccept_glyphnamerR   rA   )	r_   r^   parse_glyphclass_r   r4   addr|   r*   AttachStatement)r:   rB   glyphscontourPointsr   r   r   parse_attach_   s   



zParser.parse_attach_c                 C   s$   | j dv sJ |   | jd|dS )N>   enum	enumerateT
enumeratedrK   )r]   r9   parse_position_)r:   rK   r   r   r   parse_enumerate_   s   zParser.parse_enumerate_c                 C   s   |  dsJ | j}| jdkr| jdd}nd }| d | jdkr)| jdd}nd }| d | jdkr<| jdd}nd }| d | jdkrO| jdd}nd }| d | jj|||||dS )NGlyphClassDef,Fr   rR   rA   )r_   r^   r4   r   r|   r*   GlyphClassDefStatement)r:   rB   
baseGlyphsligatureGlyphs
markGlyphscomponentGlyphsr   r   r   parse_GlyphClassDef_   s*   








zParser.parse_GlyphClassDef_c                 C   sR   | j | j}}| d | jdd}| d | jj|||d}| j|| |S )N=Fr   rR   rA   )r^   r]   r|   r   r*   GlyphClassDefinitionr/   r   )r:   rB   rT   r   
glyphclassr   r   r   rb     s   

z#Parser.parse_glyphclass_definition_c           	      C   s   | d}g }tt|D ]&}d|d| d||d  }}|| jv r3|| jv r3|||f qt|dkrD|d \}}||fS t|dkrQtd| |ddd |D }td||f |)	N-r   r   zU"%s" is not a glyph in the font, and it can not be split into a range of known glyphsz or c                 S   rS   )z	"%s - %s"r   )r   r   lr   r   r   rV   F  s    z-Parser.split_glyph_range_.<locals>.<listcomp>zBAmbiguous glyph range "%s"; please use %s to clarify what you mean)splitranger&   r'   r)   r[   r   )	r:   rT   rB   parts	solutionsr   startlimitrangesr   r   r   split_glyph_range_#  s0   
&zParser.split_glyph_range_Fc              	   C   s,  |r0| j tjtjfv r0|r| jdkr|   | jj| jdS | 	 }| 
| | jj|| jdS | j tju rg|   | j| j}|d u rNtd| j | jt|| jjr^| jj|| jdS | jj|| jdS | d | j}| jj|d}| jdkr| j tju r| 	 }| j}d|v r| jr|| jvr| ||\}}| 
|| |||| ||| n| jdkr|}| d | 	 }| 
|| |||| ||| nd|v r| jstttd|| | 
| || n| j tju r?| 	 }| jdkr-| j}	| j}
| d |  }| 
d|
d	d|d	 | |
|| !|	|
| n]d| jd	}| 
| || nK| j tju r|   | j| j}|d u r_td| j | jt|| jjrq| jj|| jd}n	| jj|| jd}|"| n
td
| j| j#| jdks|| d |S )Nru   rA   zUnknown glyph class @%s[]r   z.Ambiguous glyph name that looks like a range: cid05dzBExpected glyph name, glyph range, or glyph class reference, found )$r3   r   rl   CIDr4   r9   r*   	NullGlyphr^   expect_glyph_check_glyph_name_in_glyph_set	GlyphNamera   r/   r   r]   r   
isinstance	MarkClassMarkClassNameGlyphClassNamer|   
GlyphClassr)   r   	add_rangemake_glyph_range_logwarningstrr[   expect_cid_add_cid_rangemake_cid_range_	add_classr6   )r:   r   accept_nullglyphgcrB   r   r   r   range_locationrange_start	range_end
glyph_namer   r   r   r   M  s   











EzParser.parse_glyphclass_c                 C   sL  g g g g g f\}}}}}d}| j dvr| jdd}d}	| j dkr)| d d }}	|	r9|r3td| j|| n|rA|| n|| |  rS|| | n|d  d }
| j dkr|
d u reg }
| d |	srtd| j| 	 }| j
|}|d u rtd	| | j|
| | j dks_|	r||
 | j dvs|s|s|g ksJ g |d gt| |g |fS t|d t| rtd
| j|t|t|t|  }t|rt|t|t| d  rtd| j|}n0|r|d rt|dkst|d d rtd| j|dd  }nt|rtd| j||||||fS )NF>   byfromr   rR   Tr   'z_Unsupported contextual target sequence: at most one run of marked (') glyph/class names allowedrI   z%Lookups can only follow marked glyphsUnknown lookup "%s"z_Positioning cannot be applied in the bactrack glyph sequence, before the marked glyph sequence.zPositioning values are allowed only in the marked glyph sequence, or after the final glyph node when only one glyph node is marked.r   )r4   r   r|   r   r^   r[   is_next_value_parse_valuerecord_r}   r~   r0   r   r&   any)r:   rK   prefixr   lookupsvaluessuffixhasMarksr   marked
lookuplistlookup_namerI   marked_valuesr   r   r   parse_glyph_pattern_  s   











/ 
zParser.parse_glyph_pattern_c                 C   s   | j }| jdd\}}}}}}t|rtd| d||s;td| d|}	tt|	 |dd  |dd }}|||f}
|
S )	NFrJ   z(No lookups can be specified for "ignore "zAmbiguous "ignore z)", there should be least one marked glyphr   r   )r^   r   r   r   r   r   r   )r:   subrB   r   r   r   r   r   r   rq   chainContextr   r   r   parse_ignore_glyph_pattern_  s"   

z"Parser.parse_ignore_glyph_pattern_c                 C   sN   | j }| |g}| jdkr | d || | | jdks| d |S )Nr   rR   )r^   r   r4   r|   r[   )r:   r   rB   r   r   r   r   parse_ignore_context_!  s   



zParser.parse_ignore_context_c                 C   sp   |  dsJ | j}|   | jdv r | d}| jj||dS | jdv r2| d}| jj||dS td| j)Nignore)
substituter   r   rA   )positionposr   z#Expected "substitute" or "position")	r_   r^   r9   r]   r   r*   IgnoreSubstStatementIgnorePosStatementr   )r:   rB   r   r   r   r   parse_ignore_*  s   



zParser.parse_ignore_c                 C   s*   | j dksJ | j}|  }tj||dS )NrC   rA   )r]   r^   expect_filename_r*   IncludeStatement)r:   rB   filenamer   r   r   r`   9  s   zParser.parse_include_c                 C   sp   |  dsJ | j}|  }d\}}| jdv r|  dk}| jdkr)| d d}| d | jj||||dS )	Nlanguage)TF>   exclude_dfltinclude_dfltr   requiredTrR   rA   )	r_   r^   expect_language_tag_r4   r~   r}   r|   r*   LanguageStatement)r:   rB   r   include_defaultr   r   r   r   parse_language_@  s   



zParser.parse_language_c                 C   sh   |  dsJ | j}| jdd}|  g}| jdkr&||   | jdks| d | jj|||dS )NLigatureCaretByIndexTr   rR   rA   )	r_   r^   r   r   r4   r[   r|   r*   LigatureCaretByIndexStatementr:   rB   r   caretsr   r   r   parse_ligatureCaretByIndex_O  s   



z"Parser.parse_ligatureCaretByIndex_c                 C   sp   |  dsJ | j}| jdd}| jddg}| jdkr*|| jdd | jdks| d | jj|||dS )NLigatureCaretByPosTr   rz   rR   rA   )	r_   r^   r   r   r4   r[   r|   r*   LigatureCaretByPosStatementr  r   r   r   parse_ligatureCaretByPos_Y  s   


z Parser.parse_ligatureCaretByPos_c                 C   s   |  dsJ | j|  }}| jdkr3| j|}|d u r&td| | j| d | jj	||dS d}| jdkrA| 
d d}| jj|||d}| || | j|| |S )NrI   rR   r   rA   FuseExtensionT)r_   r^   r~   r4   r0   r   r   r|   r*   LookupReferenceStatementr}   LookupBlockparse_block_r   )r:   rK   rB   rT   rI   use_extensionblockr   r   r   rf   c  s$   




zParser.parse_lookup_c                 C   sN  |  dsJ | j}| jtjkr!|  }| d | jj||dS d}d\}}}dddd	d
}t	 }| j
dkr| j
|v rEtd| j
 | j|| j
 | j
dkr\| d | jdd}n*| j
dkrm| d | jdd}n| j
|v r}d}|||   B }n	td| j
 | j| j
dks7| d t|||gstd| j| jj||||dS )N
lookupflagrR   rA   F)r   NNr            )RightToLeftIgnoreBaseGlyphsIgnoreLigaturesIgnoreMarksz%s can be specified only onceMarkAttachmentTyper   UseMarkFilteringSetTz#"%s" is not a recognized lookupflagzlookupflag must have a value)markAttachmentmarkFilteringSetrB   )r_   r^   r3   r   NUMBERr   r|   r*   LookupFlagStatementr(   r4   r   r6   r   r}   r   r~   r   )r:   rB   value
value_seenr  r  flagsseenr   r   r   parse_lookupflag_|  s\   










zParser.parse_lookupflag_c                 C   s   |  dsJ | j}| jdd}| std||  }|  }| d | jj	
|}|d u rD| j|}|| jj	|< | j|| | jj||||d}|| |S )NrL   Tr   z*Empty glyph class in mark class definitionrR   rA   )r_   r^   r   glyphSetr   r   expect_class_name_r|   r,   markClassesgetr*   r   r/   r   MarkClassDefinitionaddDefinition)r:   rB   r   rt   rT   rL   mcdefr   r   r   rg     s(   

zParser.parse_markClass_c           
      C   s>  | j dv sJ | jdkr| ||S | jdkr| ||S | jdkr(| ||S | jdkr3| ||S | j}| |\}}}}}}	| d t	|r^t	|rSt
d|| jj|||||dS |s|st|d	kr|	s|d
 d u rt|  | jj|d
 |d
 |d |d ||dS |rt
d|| jjtt|||||	|dS )N>   r   r   cursivebaseligaturer   rR   z3If "lookup" is present, no values must be specifiedrA   r  r   r   )r   rB   z2"enumerate" is only allowed with pair positionings
forceChainrB   )r]   r4   parse_position_cursive_parse_position_base_parse_position_ligature_parse_position_mark_r^   r   r|   r   r   r*   ChainContextPosStatementr&   reversePairPosStatementSinglePosStatementlistzip)
r:   r   rK   rB   r   r   r   r   r   r   r   r   r   r     sX   





	zParser.parse_position_c                 C   sX   | j }| d |rtd|| jdd}|  }|  }| d | jj||||dS )Nr(  z>"enumerate" is not allowed with cursive attachment positioningTr   rR   rA   )r^   r}   r   r   r   r|   r*   CursivePosStatement)r:   r   rK   rB   r   entryAnchor
exitAnchorr   r   r   r-     s   

zParser.parse_position_cursive_c                 C   N   | j }| d |rtd|| jdd}|  }| d | jj|||dS )Nr)  zC"enumerate" is not allowed with mark-to-base attachment positioningTr   rR   rA   )r^   r}   r   r   r   r|   r*   MarkBasePosStatement)r:   r   rK   rB   r)  marksr   r   r   r.       

zParser.parse_position_base_c                 C   s|   | j }| d |rtd|| jdd}|  g}| jdkr0| d ||   | jdks| d | jj	|||dS )Nr*  zG"enumerate" is not allowed with mark-to-ligature attachment positioningTr   ligComponentrR   rA   )
r^   r}   r   r   r   r4   r[   r|   r*   MarkLigPosStatement)r:   r   rK   rB   	ligaturesr<  r   r   r   r/    s   





zParser.parse_position_ligature_c                 C   r:  )Nr   zC"enumerate" is not allowed with mark-to-mark attachment positioningTr   rR   rA   )r^   r}   r   r   r   r|   r*   MarkMarkPosStatement)r:   r   rK   rB   	baseMarksr<  r   r   r   r0  /  r=  zParser.parse_position_mark_c                 C   s8   |  dsJ | j|  }}| d | jj||dS )NscriptrR   rA   )r_   r^   expect_script_tag_r|   r*   ScriptStatement)r:   rB   rC  r   r   r   parse_script_=  s   
zParser.parse_script_c                 C   s  | j dv sJ | j}| j dv }| jdd\}}}}}}t|r$td|g }	| jdkrG| d}
| jdkrF| jddd	}|	| | jdks5n| jd
krY| d
}
| jddg}	nd }
| 	d t
|	dkrpt|sptd| j|
d
kr|r{td|t
|dkst
|d  dkrtd|t
|	dkrtd|| jj||d ||	d |dS t
dd |D }d}t
|	dkrt|	d tjrg }	d}|st
|dkrt
|	dkr|dkrt|d  }t|	d  }t
|dkr|t
| }t
|t
|krtdt
|t
|f || jj||	||||dS |r8t
|dkr8|dkr8| jj||d |d||dS |st
|dkrt
|	dkr|dkrt
|d  }|	D ]1}t| sftd|t
| dkrt
| |krtd| dt
|  d|qX| jj||d ||	||dS |st
|dkrt
|	dkrt
|	d  dkr|dkr| jj|||t|	d  d ||dS |r4t
|dkrtd|t
|	dkrtd||dkrtd|tt|d  }tt|	d  }t
|dkr|t
| }t
|t
|kr)tdt
|t
|f || jj||||	|dS t
|dkrGt
|	dkrGtd|t
|	dksQ|rVtd || jj|||||d}|S )!N>   r   rsub
reversesubr   >   rG  rH  FrJ   z-Substitution statements cannot contain valuesr   rR   T)r   r   r   r   r   z3Expected "by", "from" or explicit lookup referencesz4Reverse chaining substitutions do not support "from"r   z%Expected a single glyph before "from"z)Expected a single glyphclass after "from"rA   c                 S   s   g | ]}|d ur|qS r   r   )r   r   r   r   r   rV   v  s    z,Parser.parse_substitute_.<locals>.<listcomp>z\Expected a glyph class with %d elements after "by", but found a glyph class with %d elementsr+  r   zEmpty class in replacementz!Expected a glyph class with 1 or z3 elements after "by", but found a glyph class with z	 elementsz\In reverse chaining single substitutions, only a single glyph or glyph class can be replacedzlIn reverse chaining single substitutions, the replacement (after "by") must be a single glyph or glyph classz8Reverse chaining substitutions cannot call named lookupszJDirect substitution of multiple glyphs by multiple glyphs is not supportedzInvalid substitution statement)r]   r^   r   r   r   r4   r}   r   r[   r|   r&   r!  r*   AlternateSubstStatementr   r   r5  SingleSubstStatementMultipleSubstStatementLigatureSubstStatementsorted ReverseChainSingleSubstStatementChainContextSubstStatement)r:   rB   r2  
old_prefixoldr   r   
old_suffixr   newkeywordr   num_lookupsis_deletionr   replacementscountnruler   r   r   parse_substitute_C  s.  









 
,,
$






zParser.parse_substitute_c                 C   s,   |  dsJ | j}| d | jj|dS )NsubtablerR   rA   )r_   r^   r|   r*   SubtableStatement)r:   rB   r   r   r   parse_subtable_  s   
zParser.parse_subtable_c                 C   sv   |  dsJ | j}|  }|  }d}d}| jtjtjfv s#|dkr+|  }|  }| d | j	j
|||||dS )N
parametersg        r   rR   rA   )r_   r^   expect_decipoint_r   r3   r   r  FLOATr|   r*   SizeParameters)r:   rB   
DesignSizeSubfamilyID
RangeStartRangeEndr   r   r   parse_size_parameters_  s   

zParser.parse_size_parameters_c                 C   s<   |  dsJ | j}|  \}}}}| jjd|||||dS )NsizemenunamesizerA   )r_   r^   parse_name_r*   FeatureNameStatement)r:   rB   
platformID	platEncIDlangIDstringr   r   r   parse_size_menuname_  s   zParser.parse_size_menuname_c              	   C   s   |  dsJ | j|  }}| jj||d}| d | j| j| j| j	| j
| j| j| jd|}|r9|| n	td|  || d |  }||krYtd|  | j| d |S )	NrP   rA   {)GDEFheadhheavhearT   BASEzOS/2STATz"table %s" is not supportedr   Expected "%s"rR   )r_   r^   r   r*   
TableBlockr|   parse_table_GDEF_parse_table_head_parse_table_hhea_parse_table_vhea_parse_table_name_parse_table_BASE_parse_table_OS_2_parse_table_STAT_r$  r   strip)r:   rB   rT   rP   handlerr   r   r   r   rj     s8   
	



zParser.parse_table_c                 C   s   |j }| jdks| jro| jdd | jtju r%|| jj	| j
| jd n@| dr2||   n3| dr?||   n&| drL||   n| drY||   n| j
d	kr_qtd
| j| jdks| jsd S d S )Nr   Tr!   rA   r   r   r   r  rR   z<Expected Attach, LigatureCaretByIndex, or LigatureCaretByPos)rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   r_   r   r   r  r  r   r:   rP   rX   r   r   r   rz  ;  s,   




zParser.parse_table_GDEF_c                 C   s   |j }| jdks| jrH| jdd | jtju r%|| jj	| j
| jd n| dr2||   n| j
dkr8qtd| j| jdks| jsd S d S )Nr   Tr!   rA   FontRevisionrR   zExpected FontRevision)rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   r_   parse_FontRevision_r   r  r   r   r   r{  S  s   

zParser.parse_table_head_c                 C      |j }d}| jdks| jrj| jdd | jtju r'|| jj	| j
| jd n9| jtju rT| j
|v rT| j
 }|  }|| jj||| jd | jdkrStd| jn| j
dkrZqtd| j| jdks| jsd S d S )	N)CaretOffsetAscender	DescenderLineGapr   Tr!   rA   rR   Incomplete statementz4Expected CaretOffset, Ascender, Descender or LineGap)rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   rl   lowerr   	HheaFieldr   r6   r:   rP   rX   fieldskeyr  r   r   r   r|  b  s4   


zParser.parse_table_hhea_c                 C   r  )	N)VertTypoAscenderVertTypoDescenderVertTypoLineGapr   Tr!   rA   rR   r  z?Expected VertTypoAscender, VertTypoDescender or VertTypoLineGap)rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   rl   r  r   	VheaFieldr   r6   r  r   r   r   r}  }  s4   


zParser.parse_table_vhea_c                 C   s   |j }| jdks| jrL| jdd | jtju r%|| jj	| j
| jd n| dr6|  }|r5|| n| j
dkr<qtd| j| jdks| jsd S d S )Nr   Tr!   rA   nameidrR   zExpected nameid)rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   r_   parse_nameid_r   )r:   rP   rX   	statementr   r   r   r~    s    


zParser.parse_table_name_c                 C   s   d}d}| j tjv r)|  }| j}|dvrtd|| j tjv r(|  }|  }nd}| j}|dkr;|p5d}|p9d}n|p>d}|pBd}|  }| d t|||}|du r[td	|| 	||}||||fS )
z~Parses a name record. See `section 9.e <https://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#9.e>`_.Nr      Expected platform id 1 or 3r  r   r   	  rR   Unsupported encoding)
r3   r   NUMBERSexpect_any_number_r^   r   expect_string_r|   r   unescape_string_r:   rm  rn  rl  rB   ro  encoding	unescapedr   r   r   rj    s2   



zParser.parse_name_c                 C   s   d }d }| j tjv r)|  }| j}|dvrtd|| j tjv r(|  }|  }nd}| j}|dkr;|p5d}|p9d}n|p>d}|pBd}|  }t|||}|d u rVtd|| ||}||||fS )Nr  r  r  r   r   r  r  )	r3   r   r  r  r^   r   r  r   r  r  r   r   r   parse_stat_name_  s0   


zParser.parse_stat_name_c                 C   s`   | j dks
J | j | j|  }}|dkrtd| j|  \}}}}| jj||||||dS )Nr  i  z*Name id value cannot be greater than 32767rA   )r]   r^   r  r   rj  r*   
NameRecord)r:   rB   nameIDrl  rm  rn  ro  r   r   r   r    s   zParser.parse_nameid_c                    sL    dkrt dj|}n fdd}t d||}t|dd}t|dS )N	utf_16_bez\\[0-9a-fA-F]{4}c                    s    |  S r   )unescape_byte_)mr  r:   r   r   <lambda>  s    z)Parser.unescape_string_.<locals>.<lambda>z\\[0-9a-fA-F]{2}surrogatepass)rer   unescape_unichr_r	   r
   )r:   ro  r  r   unescapeutf16r   r  r   r    s   
zParser.unescape_string_c                 C   s    |  ddd  }tt|dS Nr   r      )groupchrint)matchrY  r   r   r   r    s   zParser.unescape_unichr_c                 C   s&   |  ddd  }tt|d|S r  )r  r   r  decode)r  r  rY  r   r   r   r    s   zParser.unescape_byte_c                 C   s8   t |D ]}t|| jjrqt||r|  S  d S d S r   )reversedr   r*   r\   )r:   rX   class_previousr   r   r   find_previous	  s   
zParser.find_previousc                 C   s  |j }| jdks| jr| jdd | jtju r%|| jj	| j
| jd n| dr/|  }n| drJ| t|}|| jj||d| jd n{| drr| |tj}|d u r`td	| j|jritd
| j|j|   nS| dr||  }nI| dr| t|}|| jj||d| jd n.| dr| |tj}|d u rtd	| j|jstd| j|j|   n| j
dkrq| jdks| jsd S d S )Nr   Tr!   rA   HorizAxis.BaseTagListHorizAxis.BaseScriptListFzHorizAxis.MinMaxz)MinMax must be preceded by BaseScriptListz9HorizAxis.MinMax must be preceded by HorizAxis statementsVertAxis.BaseTagListVertAxis.BaseScriptListzVertAxis.MinMaxz7VertAxis.MinMax must be preceded by VertAxis statementsrR   )rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   r_   parse_base_tag_list_parse_base_script_list_r&   BaseAxisr  r   rK   minmaxparse_base_minmax_)r:   rP   rX   horiz_baseshoriz_scriptsbase_script_list
vert_basesvert_scriptsr   r   r   r    sx   








zParser.parse_table_BASE_c                 C   s0  |j }d}d}| jdks| jr| jdd | jtju r)|| jj	| j
| jd nc| jtju r| j
 }d }| j
|v r@|  }n8| drVg }tdD ]	}||   qKn"| j
|v rog }| jd	krn||   | jd	ksbn	| d
rx|  }|| jj||| jd n| j
d	krq| jdks| jsd S d S )N)FSTypeTypoAscenderTypoDescenderTypoLineGap	winAscent
winDescentXHeight	CapHeightWeightClass
WidthClassLowerOpSizeUpperOpSize)UnicodeRangeCodePageRanger   Tr!   rA   Panose
   rR   Vendor)rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   rl   r  r   r_   r   r  OS2Field)r:   rP   rX   numbersr   r  r  r   r   r   r   r  S  sB   








zParser.parse_table_OS_2_c                 C   s   |  dsJ | d g }| jdks| jrR|   |  dr:|  \}}}}| jjd||||| jd}|	| n| j
dkrJtd| j
 d	| j| jdks| js| d |s_td
| j|S )NElidedFallbackNamerq  r   rT   statrA   rR   Unexpected token z in ElidedFallbackNameExpected "name")r_   r|   r4   r5   r9   r  r*   STATNameStatementr^   r[   r]   r   )r:   namesrl  rm  rn  ro  
nameRecordr   r   r   parse_STAT_ElidedFallbackName  s4   



z$Parser.parse_STAT_ElidedFallbackNamec           
      C   s  |  dsJ g }|  }|dvr| std| d |  }| d | jdks/| jrt| 	  | j
tju r:q'|  dr\| j}|  \}}}}| jjd|||||d	}	||	 n| jd
krbq'td| j | j| jdks/| js/| d | j|||| jS )N
DesignAxis)italopszslntwdthwghtzUnregistered axis tag z should be uppercase.rq  r   rT   r  rA   rR   zExpected "name", got )r_   r   isupperr   r   r   r|   r4   r5   r9   rY   r   rZ   r^   r  r*   r  r[   r]   r   STATDesignAxisStatement)
r:   r  axisTag	axisOrderrB   rl  rm  rn  ro  rT   r   r   r   parse_STAT_design_axis  s<   




zParser.parse_STAT_design_axisc                 C   s  |  dsJ | d g }g }d}| jdks| jr{| jdd | jtju r'q|  drI| j}| 	 \}}}}| j
jd|||||d	}	||	 n*|  d
rX|  }|| n|  drb|  }n| jdkrhqtd| j d| j| jdks| js| d |std| j|std| jt|dkr|D ]}t|jdkrtdt|j d| jqg }
|D ]}|j}||
v rtd| d| j|
| q| j
|||| jS )N	AxisValuerq  r   r   Tr!   rT   r  rA   rB   flagrR   r  z in AxisValuezExpected "Axis Name"zExpected "Axis location"r   z?Only one value is allowed in a Format 4 Axis Value Record, but z were found.	Axis tag z already defined.)r_   r|   r4   r5   r9   rY   r   rZ   r^   r  r*   r  r[   parse_STAT_locationexpect_stat_flagsr]   r   r&   r   r   STATAxisValueStatement)r:   	locationsr  r  rB   rl  rm  rn  ro  rT   format4_tagsr   r   r   r   parse_STAT_axis_value_  sl   







zParser.parse_STAT_axis_value_c                 C   s   g }|   }t| dkrtd| j d| j| jdkrN| jtj	u r.| 
 }|| n| jtju r>|  }|| ntd| j d| j| jdkst|dkrq|\}}}||k sa||krqtd| d	| d
| d| j| j||S )Nr  r  z must be 4 charactersrR   zUnexpected value "z". Expected integer or float.r  zDefault value z is outside of specified range r   .)r   r&   r  r   r]   r^   r4   r3   r   ra  expect_float_r[   r  r   r6   r*   AxisValueLocationStatement)r:   r   r   r  nominalmin_valmax_valr   r   r   r    s>   


zParser.parse_STAT_locationc           	      C   sp  |j }g }| jdks| jr| jdd | jtju r'|| jj	| j
| jd n| jtju r| dr@|  }|| j| nl| drX|  }|| j| | d nT| drr|  }||j || | d n:| d	r|  }|jD ]}|j|vrtd
|j d| jq~|| | d ntd| j
 | j| j
dkrq| jdks| jsd S d S )Nr   Tr!   rA   r  ElidedFallbackNameIDrR   r  r  zDesignAxis not defined for r  r  )rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   rl   r_   r  r  r   r   r|   r  r   r  r  r   )	r:   rP   rX   design_axesr  r  
designAxisaxisValueRecordrB   r   r   r   r    sL   








zParser.parse_table_STAT_c                 C   sH   | j dv s
J | j g }| jdkr||   | jdks| d |S )N)r  r  rR   )r]   r4   r[   rD  r|   )r:   basesr   r   r   r  ?  s   


zParser.parse_base_tag_list_c                 C   s\   | j dv s
J | j | |g}| jdkr'| d || | | jdks| d |S )N)r  r  r   rR   )r]   parse_base_script_record_r4   r|   r[   )r:   rX  scriptsr   r   r   r  K  s   



zParser.parse_base_script_list_c                    s0      }   } fddt|D }|||fS )Nc                    s   g | ]}   qS r   )r   r   r:   r   r   rV   Z  r   z4Parser.parse_base_script_record_.<locals>.<listcomp>)rD  r   )r:   rX  
script_tagbase_tagcoordsr   r  r   r  W  s   
z Parser.parse_base_script_record_c                 C   sl   |   }|  }|  }|   | jtju r| jdks!td| j	|  }| j
dkr0td| j	||||fS )Nr   z0Expected a comma between min and max coordinatesz0Feature tags are not yet supported in BASE table)rD  r   r   r9   rY   r   rn   r]   r   r^   r4   )r:   r  r   	min_coord	max_coordr   r   r   r  ]  s    
zParser.parse_base_minmax_c                 C   s   d }|  d | d | jdkr| d n'|  |  fg}| jdkr:|  d ||  |  f | jdks%t|}|  d |S )Nrs   deviceru   r   rv   )r|   r}   r4   r   r[   tuple)r:   resultr   r   r   r   p  s   






zParser.parse_device_c                 C   s    | j tju p| jdkp| jdkS )Nrs   ()r3   r   r  r4   r  r   r   r   r     s
   zParser.is_next_value_c                 C   s  | j tju r| jdks| j tju r3| jdd| j}}|r(| jj|||d}|S | jj|||d}|S | 	d | j}| j tj
u rw|  }|dkrS| 	d | j S | j|}|d u retd	| | j|j}|j|j}}	|j|j}
}n| jdd| jdd| jdd| jddf\}}	}
}| jdkr|  |  |  |  f\}}}}td
d |r|nd|r|nd |r|nd |r|nd D }|d dk s|d dkrtd| jnd\}}}}| 	d | jj||	|
|||||||d
S )Nr  Trz   )yAdvancerK   rB   )xAdvancerK   rB   rs   ru   rv   zUnknown valueRecordDef "%s"c                 S   s   g | ]\}}|qS r   r   )r   ri  deltar   r   r   rV     s    z-Parser.parse_valuerecord_.<locals>.<listcomp>r   r   ir      z+Device value out of valid range (-128..127))NNNN)rK   rB   )r3   r   rn   r4   r  r   r^   r*   ValueRecordr|   rl   r~   r1   r   r   r  
xPlacement
yPlacementr  r  r   rM  )r:   rK   numberrB   valrT   vrdr  r  r  r  r  
xPlaDevice
yPlaDevice
xAdvDevice
yAdvDevice	allDeltasr   r   r   r     s   













	
zParser.parse_valuerecord_c                 C   sT   |  dsJ | j}| |}|  }| d | jj|||d}| j|| |S )NrQ   rR   rA   )	r_   r^   r   r~   r|   r*   ValueRecordDefinitionr1   r   )r:   rK   rB   r  rT   r  r   r   r   rk     s   

z$Parser.parse_valuerecord_definition_c                 C   s@   | j dksJ | j}|  }|  }| d | jj|||dS )NrH   rR   rA   )r]   r^   rD  r   r|   r*   LanguageSystemStatement)r:   rB   rC  r   r   r   r   re     s   
zParser.parse_languagesystem_c                 C   s   |r
| j dks	J n| j dksJ | j}|  }|dv }d }d }d}|| jv r*|}n|| jv r2|}n|dkr8d}|r>|  }d}	| jdkrL| d d}	|rY| jj	|||	|d}
n	| jj
||	|d}
| |
|||| |
S )	NrO   rM   >   valtvhalvkrnvpalFri  Tr  )r  rB   )r]   r^   r   SS_FEATURE_TAGSCV_FEATURE_TAGSr~   r4   r}   r*   VariationBlockFeatureBlockr  )r:   rO   rB   r   rK   stylisticset
cv_featuresize_featurerN   r  r  r   r   r   rh     s<   



zParser.parse_feature_block_c                 C   s<   | j dks
J | j | j}|  }| d | jj||dS )NrM   rR   rA   )r]   r^   r   r|   r*   FeatureReferenceStatement)r:   rB   featureNamer   r   r   parse_feature_reference_  s
   
zParser.parse_feature_reference_c           	   
   C   s$  | j dks
J | j | jj|| j | jd}| d | jD ]}|  q| jdks,| jr|| j	dd | j
tju rG|j| jj| j | jd n-| drh| j}|  \}}}}|j| jj||||||d n| j dkrnq$td	| j| jdks,| js,| d | jD ]}|  q| d |S )
zParses a ``featureNames`` statement found in stylistic set features.
        See section `8.c <https://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#8.c>`_.
        featureNamesrA   rq  r   Tr!   rT   rR   r  )r]   r*   NestedBlockr^   r|   r2   enter_scoper4   r5   r9   rY   r   rZ   rX   r[   r\   r_   rj  rk  r   
exit_scope)	r:   r   r  symtabrB   rl  rm  rn  ro  r   r   r   parse_featureNames_  s<   









zParser.parse_featureNames_c                 C   s2  | j dks
J | j | jj|| j | jd}| d | jD ]}|  q|j}| jdks/| j	r| j
dd | jtju rI|| jj| j | jd n2| h dr[|| || j  n | dri|| | n| j d	kroq'td
| j| j | j| jdks/| j	s/| d | jD ]}|  q| d	 |S )NcvParametersrA   rq  r   Tr!   >   SampleTextNameIDFeatUILabelNameIDParamUILabelNameIDFeatUITooltipTextNameID	CharacterrR   zExpected statement: got {} {})r]   r*   r1  r^   r|   r2   r2  rX   r4   r5   r9   rY   r   rZ   r[   r\   r_   parse_cvNameIDs_parse_cvCharacter_r   ro   r3  )r:   r   r  r4  rX   r   r   r   parse_cvParameters_7  sD   









zParser.parse_cvParameters_c           
      C   s$  | j |ks
J | j | jj||| jd}| d | jD ]}|  q| jdks+| jr|| j	dd | j
tju rF|j| jj| j | jd n.| drh| j}|  \}}}}	|j| jj|||||	||d n| j dkrnq#td| j| jdks+| js+| d | jD ]}|  q| d |S )	NrA   rq  r   Tr!   rT   rR   r  )r]   r*   r1  r^   r|   r2   r2  r4   r5   r9   rY   r   rZ   rX   r[   r\   r_   rj  CVParametersNameStatementr   r3  )
r:   r   
block_namer  r4  rB   rl  rm  rn  ro  r   r   r   r<  d  sD   








zParser.parse_cvNameIDs_c                 C   sh   | j dks
J | j | j|  }}| d d|  kr!dks+n tddd|| jj|||dS )Nr;  rR   i r   z/Character value must be between {:#x} and {:#x}rA   )r]   r^   r  r|   r   ro   r*   CharacterStatement)r:   r   rB   	characterr   r   r   r=    s   
zParser.parse_cvCharacter_c                 C   sP   | j dks
J | j | j|  }}| d |dkr td|| jj||dS )Nr  rR   r   z&Font revision numbers must be positiverA   )r]   r^   r  r|   r   r*   FontRevisionStatement)r:   rB   versionr   r   r   r    s   

zParser.parse_FontRevision_c                 C   s  |   }i }| d | jdkrn|   | jtjur td| j| j	}||v r0td| | j| j
tju r;|  }n| j
tju rG| jdd}| j
tju rR|  }n| j
tju r^| jdd}| d ||f||< | jdks| d |   }||krtd| | j| j||S )	Nrq  r   Expected an axis namezRepeated condition for axis Frz   rR   rx  )r~   r|   r4   r9   rY   r   rl   r   r^   r]   r3   ra  r  r  r   r*   ConditionsetStatement)r:   rT   
conditionsaxis	min_value	max_value	finalnamer   r   r   ri     s8   






zParser.parse_conditionset_c                 C   sp  |  d | jD ]}|  q|j}| jdks| jrx| jdd | jtj	u r6|
| jj| j| jd n:| jtju rE|
|   n+| drS|
|   n| ddhre|
| j|d	 n| d
rr|
|   n| dr|
|   n| dr|
|   n| dr|
| | n| dr|
|   n| dr|
|   n| ddhr|
| jd|d n| dr|
|   n| h dr|
|   n| dr|
|   n| dr|
| | ns|r| dr|
| | na|r!| dr!|
|  | nO|r2| dr2|
| !  n>|rC| drC|
| "  n-| jtj#u r]| j| j$v r]|
| j$| j |  n| jdkrdqt%d&| j| j| j| jdks| js|  d | jD ]}|'  q| ( }||j)* krt%d|j)*  | j|  d d}	d}
|D ]+}t+|| jj,rt-|j.|j/|j0g }	qt+|| jj1rt-|j.|j/|j0g }
q|	r4|
r6g }|jD ]M}t+|| jj,r(|j2d 3 }|j4d 3 }t5|d kr|t5|9 }t6|D ]\}}|
| jj1|j.||j/|| g|j0|j7d q
q|
| q||_d S d S d S )!Nrq  r   Tr!   rA   rG   r   r   rJ   rM   r   r   rI   r  rL   r   r   Fr   rC  >   r   rG  rH  r   r\  rQ   r0  r6  r_  rh  rR   z7Expected glyph class definition or statement: got {} {}rx  r   r   )8r|   r2   r2  rX   r4   r5   r9   rY   r   rZ   r[   r*   r\   r]   r^   ra   rb   r_   rd   r   r/  r   r   rf   r   rg   r   rF  r[  r^  rk   r5  r>  rg  rp  rl   rm   r   ro   r3  r~   rT   r  r   rJ  r   r   r   r,  rK  r   r!  rW  r&   r   rB   )r:   r  rK   r*  r,  r+  r4  rX   rT   
has_singlehas_multipler   r   rW  r   r   r   r   r   r    s   













;



zParser.parse_block_c                 C   s2   | j tju rt|tdr| j|kS | j|v S dS )Nr   F)rY   r   rl   r   typer]   )r:   r   r   r   r   r_   7  s
   

zParser.is_cur_keyword_c                 C   &   |    | jtjurtd| j| jS )NzExpected @NAME)r9   rY   r   ra   r   r^   r]   r  r   r   r   r"  ?     zParser.expect_class_name_c                 C   &   |    | jtju r| jS td| j)NzExpected a CID)r9   rY   r   r   r]   r   r^   r  r   r   r   r   E     zParser.expect_cid_c                 C   rO  )NzExpected file name)r9   rY   r   FILENAMEr   r^   r]   r  r   r   r   r   K  rP  zParser.expect_filename_c                 C   sB   |    | jtju r| jdS | jtju rd| j S td| j)N\cid%05dzExpected a glyph name or CID)	r9   rY   r   rl   r]   lstripr   r   r^   r  r   r   r   r   Q  s   
zParser.expect_glyph_c                 G   s:   | j r|D ]}|| j v rq|| jvr| j| j|< qdS dS )zAdds a glyph name (just `start`) or glyph names of a
        range (`start` and `end`) which are not in the glyph set
        to the "missing list" for future error reporting.

        If no glyph set is present, does nothing.
        N)r)   r8   r^   )r:   r  rT   r   r   r   r   Y  s   

z$Parser.check_glyph_name_in_glyph_setc                 C   sN   |   }| j|}|d u rtd| | jt|| jjs%td| | j|S )NzUnknown markClass @%sz@%s is not a markClass)r"  r/   r   r   r^   r   r*   r   )r:   rT   mcr   r   r   r   g  s   

z"Parser.expect_markClass_reference_c                 C   sL   |    | jtjurtd| jt| jdkrtd| j| jd d d S )NzExpected a tagr  z'Tags cannot be longer than 4 charactersz    )r9   rY   r   rl   r   r^   r&   r]   r  r   r   r   r   t  s   zParser.expect_tag_c                 C       |   }|dkrtd| j|S )Ndfltz4"dflt" is not a valid script tag; use "DFLT" insteadr   r   r^   r:   r   r   r   r   rD  ~     zParser.expect_script_tag_c                 C   rX  )NDFLTz6"DFLT" is not a valid language tag; use "dflt" insteadrZ  r[  r   r   r   r     r\  zParser.expect_language_tag_c                 C   s2   |    | jtju r| j|kr|S td| | j)NzExpected '%s')r9   rY   r   rn   r]   r   r^   )r:   symbolr   r   r   r|     s   zParser.expect_symbol_c                 C   s4   |    | jtju r| j|kr| jS td| | j)Nrx  r9   rY   r   rl   r]   r   r^   )r:   rT  r   r   r   r}     s   zParser.expect_keyword_c                 C   rQ  )NzExpected a namer_  r  r   r   r   r~     rR  zParser.expect_name_c                 C   sH   |    | jtju r| jS |r| jtju r| jdkr|  S td| j)Nr  zExpected a number)	r9   rY   r   r  r]   rn   expect_variable_scalar_r   r^   )r:   r{   r   r   r   r     s   zParser.expect_number_c                 C   sF   |    t }	 | jtjkr| jdkr	 |S |  \}}||| q)NT))r9   r   rY   r   rn   r]   expect_master_	add_value)r:   scalarrB   r  r   r   r   r`    s   zParser.expect_variable_scalar_c                 C   s   i }	 | j tjurtd| j| j}|   | j tju r!| jdks'td| j|  }|||< | j	tju r=| j
d dkr=n|   | j tju rL| jdksRtd| j|   q|   t| jd	d  }|   ||fS )
NTrE  r   zExpected an equals signr   :r   z#Expected an comma or an equals signr   )rY   r   rl   r   r^   r]   r9   rn   r   r3   r4   r  )r:   rB   rH  r  r   r   r   rb    s2   zParser.expect_master_c                 C   s&   |    | jtjv r| jS td| j)Nz/Expected a decimal, hexadecimal or octal number)r9   rY   r   r  r]   r   r^   r  r   r   r   r       zParser.expect_any_number_c                 C   rQ  )Nz Expected a floating-point number)r9   rY   r   ra  r]   r   r^   r  r   r   r   r    rf  zParser.expect_float_c                 C   s8   | j tjkr
|  S | j tju r|  d S td| j)Nr  ,Expected an integer or floating-point numberr3   r   ra  r  r  r   r   r^   r  r   r   r   r`    s   zParser.expect_decipoint_c                 C   sZ   d}ddd}| j dkr+| j |v r|  }||| B }n
td| j | j| j dks|S )Nr   r   r  )OlderSiblingFontAttributeElidableAxisValueNamerR   zUnexpected STAT flag )r4   r~   r   r]   r^   )r:   r  r  rT   r   r   r   r    s   


zParser.expect_stat_flagsc                 C   s4   | j tjkr
|  S | j tju r|  S td| j)Nrg  rh  r  r   r   r   expect_stat_values_  s   zParser.expect_stat_values_c                 C   rQ  )NzExpected a string)r9   rY   r   STRINGr]   r   r^   r  r   r   r   r  	  rR  zParser.expect_string_c                 C   s   |r| j rtj| _| j d\| _| _d S | j| j| j	| _| _| _	 zt
| j\| _| _| _	W n ty@   d\| _| _Y nw | jtjkrId S | j | j| j	f q$)Nr   Tr   )r5   r   rZ   rY   r%   r]   r^   r3   r4   r6   nextr7   StopIterationr[   )r:   r"   r   r   r   r9   		  s,   
zParser.advance_lexer_c                 C   s   d tt| S )z'abc' --> 'cba'r   )r'   r  r5  )r   r   r   r   reverse_string_!	  s   zParser.reverse_string_c                 C   s>   t  }||krtd|t||d D ]	}|d|  q|S )z>(location, 999, 1001) --> ["cid00999", "cid01000", "cid01001"]z*Bad range: start should be less than limitr   rU  )r5  r   r   r[   )r:   rB   r   r   r  r   r   r   r   r   &	  s   zParser.make_cid_range_c                 C   s  t  }t|t|krtd||f || j}tj||g}|tj||||g}t|dkrJ|t|t|  }|t|t|  }	n|t|d }|t|d }	||	krctd|td}
|
	|r|
	|	rt
t|t|	d D ]}|d|||f  q}|S td}|	|r|	|	rt
t|t|	d D ]}|d|||f  q|S td	}|	|r|	|	rt
t|d
t|	d
d D ]}dt| t| d }|d|||f  q|S td||f |)z?(location, "a.sc", "d.sc") --> ["a.sc", "b.sc", "c.sc", "d.sc"]z4Bad range: "%s" and "%s" should have the same lengthr   Nz+Start of range must be smaller than its endz^[A-Z]$r   z%s%c%sz^[a-z]$z^[0-9]{1,3}$r  000z%s%s%szBad range: "%s-%s")r5  r&   r   ro  ospathcommonprefixr  compiler  r   ordr[   r  r   )r:   rB   r   r   r  revr   r   start_rangelimit_range	uppercasec	lowercasedigitsr   r  r   r   r   r   1	  sF   



zParser.make_glyph_range_)r   TN)F)NFN)k__name__
__module____qualname____doc__rm   r*   r   r&  r'  r@   rr   r   r   rd   rc   r   r   r   rb   r   r   r   r   r   r   r`   r   r  r  rf   r   rg   r   r-  r.  r/  r0  rF  r[  r^  rg  rp  rj   rz  r{  r|  r}  r~  rj  r  r  r  staticmethodr  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r   rk   re   rh   r/  r5  r>  r<  r=  r  ri   r  r_   r"  r   r   r   r   r   r   rD  r   r|   r}   r~   r   r`  rb  r  r  r`  r  rk  r  r9   ro  r   r   r   r   r   r   r      s    
!?6

*d]	

95 ; 

=,"8!)N
&#-$
&
t
		





r   c                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )r-   c                 C   s   i g| _ d S r   scopes_r  r   r   r   r@   `	  s   zSymbolTable.__init__c                 C   s   | j i  d S r   )r  r[   r  r   r   r   r2  c	  s   zSymbolTable.enter_scopec                 C   s   | j   d S r   )r  r%   r  r   r   r   r3  f	  s   zSymbolTable.exit_scopec                 C   s   || j d |< d S )Nr   r  )r:   rT   itemr   r   r   r   i	  s   zSymbolTable.definec                 C   s*   t | jD ]}||}|r|  S qd S r   )r  r  r$  )r:   rT   scoper  r   r   r   r   l	  s   
zSymbolTable.resolveN)r}  r~  r  r@   r2  r3  r   r   r   r   r   r   r-   _	  s    r-   )fontTools.feaLib.errorr   fontTools.feaLib.lexerr   r   r   fontTools.feaLib.variableScalarr   fontTools.misc.encodingToolsr   fontTools.misc.textToolsr   r	   r
   fontTools.feaLib.astfeaLibr*   loggingrq  r  	getLoggerr}  r   objectr   r-   r   r   r   r   <module>   s<    
                  b