
    rh                       S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
  SSK	Jr  SSK	Jr  SSK	Jr  SSK	Jr  SS	K	Jr  SS
K	Jr  SSK	Jr  SSK	Jr  \R&                  (       a  SSKJr  \R,                  " S5      r " S S\R0                  5      r " S S5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S5      r " S S\5      r  " S S \5      r! " S! S"5      r" " S# S$\"5      r# " S% S&\"5      r$ " S' S(\$5      r% " S) S*\$5      r&S5S+ jr'SS,S-.r( " S. S/5      r) " S0 S1\RT                  5      r+ " S2 S3\RT                  5      r,\)\"\\/r-\.S4:X  a  SSK	r	\	R^                  " \+5        gg)6a"  
tinyNotation is a simple way of specifying single line melodies
that uses a notation somewhat similar to Lilypond but with WAY fewer
options.  It was originally developed to notate trecento (medieval Italian)
music, but it is pretty useful for a lot of short examples, so we have
made it a generally supported music21 format.


N.B.: TinyNotation is not meant to expand to cover every single case.  Instead,
it is meant to be subclassable to extend to the cases *your* project needs.

Here are the most important rules by default:

1. Note names are: a,b,c,d,e,f,g and r for rest
2. Flats, sharps, and naturals are notated as #,- (not b), and (if needed) n.
   If the accidental is above the staff (i.e., editorial), enclose it in
   parentheses: (#), etc.  Make sure that flats in the key signatures are
   explicitly specified.
3. Note octaves are specified as follows::

     CC to BB = from C below bass clef to second-line B in bass clef
     C to B = from bass clef C to B below middle C.
     c  to b = from middle C to the middle of treble clef
     c' to b' = from C in treble clef to B above treble clef

   Octaves below and above these are specified by further doublings of
   letter (CCC) or apostrophes (c'') -- this is one of the note name
   standards found in many music theory books.
4. After the note name, a number may be placed indicating the note
   length: 1 = whole note, 2 = half, 4 = quarter, 8 = eighth, 16 = sixteenth.
   etc.  If the number is omitted then it is assumed to be the same
   as the previous note.  I.e., c8 B c d  is a string of eighth notes.
5. After the number, a ~ can be placed to show a tie to the next note.
   A "." indicates a dotted note.  (If you are entering
   data via Excel or other spreadsheet, be sure that "capitalize the
   first letter of sentences" is turned off under "Tools->AutoCorrect,"
   otherwise the next letter will be capitalized, and the octave will
   be screwed up.)
6. For triplets use this notation:  `trip{c4 d8}`  indicating that these
   two notes both have "3s" over them.  For 4 in the place of 3,
   use `quad{c16 d e8}`.  No other tuplets are supported.

Here is an example of TinyNotation in action.

>>> stream1 = converter.parse("tinyNotation: 3/4 E4 r f# g=lastG trip{b-8 a g} c4~ c")
>>> stream1.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.TrebleClef>
    {0.0} <music21.meter.TimeSignature 3/4>
    {0.0} <music21.note.Note E>
    {1.0} <music21.note.Rest quarter>
    {2.0} <music21.note.Note F#>
{3.0} <music21.stream.Measure 2 offset=3.0>
    {0.0} <music21.note.Note G>
    {1.0} <music21.note.Note B->
    {1.3333} <music21.note.Note A>
    {1.6667} <music21.note.Note G>
    {2.0} <music21.note.Note C>
{6.0} <music21.stream.Measure 3 offset=6.0>
    {0.0} <music21.note.Note C>
    {1.0} <music21.bar.Barline type=final>
>>> stream1.recurse().getElementById('lastG').step
'G'
>>> stream1.flatten().notesAndRests[1].isRest
True
>>> stream1.flatten().notesAndRests[0].octave
3
>>> stream1.flatten().notes[-2].tie.type
'start'
>>> stream1.flatten().notes[-1].tie.type
'stop'

Changing time signatures are supported:

>>> s1 = converter.parse('tinynotation: 3/4 C4 D E 2/4 F G A B 1/4 c')
>>> s1.show('t')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 3/4>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
{3.0} <music21.stream.Measure 2 offset=3.0>
    {0.0} <music21.meter.TimeSignature 2/4>
    {0.0} <music21.note.Note F>
    {1.0} <music21.note.Note G>
{5.0} <music21.stream.Measure 3 offset=5.0>
    {0.0} <music21.note.Note A>
    {1.0} <music21.note.Note B>
{7.0} <music21.stream.Measure 4 offset=7.0>
    {0.0} <music21.meter.TimeSignature 1/4>
    {0.0} <music21.note.Note C>
    {1.0} <music21.bar.Barline type=final>



Here is an equivalent way of doing the example above, but using the lower level
:class:`music21.tinyNotation.Converter` object:

>>> tnc = tinyNotation.Converter('3/4 E4 r f# g=lastG trip{b-8 a g} c4~ c')
>>> stream2 = tnc.parse().stream
>>> len(stream1.recurse()) == len(stream2.recurse())
True

This lower level is needed in case you want to add additional features.  For instance,
here we will set the "modifierStar" to change the color of notes:

>>> class ColorModifier(tinyNotation.Modifier):
...     def postParse(self, m21Obj):
...         m21Obj.style.color = self.modifierData
...         return m21Obj

>>> tnc = tinyNotation.Converter('3/4 C4*pink* D4*green* E4*blue*')
>>> tnc.modifierStar = ColorModifier
>>> s = tnc.parse().stream
>>> for n in s.recurse().getElementsByClass(note.Note):
...     print(n.step, n.style.color)
C pink
D green
E blue

Or more usefully, and often desired:

>>> class HarmonyModifier(tinyNotation.Modifier):
...     def postParse(self, n):
...         cs = harmony.ChordSymbol(n.pitch.name + self.modifierData)
...         cs.duration = n.duration
...         return cs
>>> tnc = tinyNotation.Converter('4/4 C2_maj7 D4_m E-_sus4')
>>> tnc.modifierUnderscore = HarmonyModifier
>>> s = tnc.parse().stream
>>> s.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 4/4>
    {0.0} <music21.harmony.ChordSymbol Cmaj7>
    {2.0} <music21.harmony.ChordSymbol Dm>
    {3.0} <music21.harmony.ChordSymbol E-sus4>
    {4.0} <music21.bar.Barline type=final>
>>> for cs in s.recurse().getElementsByClass(harmony.ChordSymbol):
...     print([p.name for p in cs.pitches])
['C', 'E', 'G', 'B']
['D', 'F', 'A']
['E-', 'A-', 'B-']

The supported modifiers are:
    * `=data` (`modifierEquals`, default action is to set `.id`)
    * `_data` (`modifierUnderscore`, default action is to set `.lyric`)
    * `[data]` (`modifierSquare`, no default action)
    * `<data>` (`modifierAngle`, no default action)
    * `(data)` (`modifierParens`, no default action)
    * `*data*` (`modifierStar`, no default action)


Another example: TinyNotation does not support key signatures -- well, no problem! Let's
create a new Token type and add it to the tokenMap

>>> class KeyToken(tinyNotation.Token):
...     def parse(self, parent):
...         keyName = self.token
...         return key.Key(keyName)
>>> keyMapping = (r'k(.*)', KeyToken)
>>> tnc = tinyNotation.Converter('4/4 kE- G1 kf# A1')
>>> tnc.tokenMap.append(keyMapping)
>>> s = tnc.parse().stream
>>> s.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.key.Key of E- major>
    {0.0} <music21.meter.TimeSignature 4/4>
    {0.0} <music21.note.Note G>
{4.0} <music21.stream.Measure 2 offset=4.0>
    {0.0} <music21.key.Key of f# minor>
    {0.0} <music21.note.Note A>
    {4.0} <music21.bar.Barline type=final>


TokenMap should be passed a string, representing a regular expression with exactly one
group (which can be the entire expression), and a subclass of :class:`~music21.tinyNotation.Token`
which will handle the parsing of the string.

Tokens can take advantage of the `parent` variable, which is a reference to the `Converter`
object, to use the `.stateDict` dictionary to store information about state.  For instance,
the `NoteOrRestToken` uses `parent.stateDict['lastDuration']` to get access to the last
duration.

There is also the concept of "State" which affects multiple tokens.  The best way to create
a new State is to define a subclass of the :class:`~music21.tinyNotation.State`  and add it
to `bracketStateMapping` of the converter.  Here's one that a lot of people have asked for
over the years:

>>> class ChordState(tinyNotation.State):
...    def affectTokenAfterParse(self, n):
...        super().affectTokenAfterParse(n)
...        return None  # do not append Note object
...    def end(self):
...        ch = chord.Chord(self.affectedTokens)
...        ch.duration = self.affectedTokens[0].duration
...        return ch
>>> tnc = tinyNotation.Converter("2/4 C4 chord{C4 e g'} F.4 chord{D8 F# A}")
>>> tnc.bracketStateMapping['chord'] = ChordState
>>> s = tnc.parse().stream
>>> s.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 2/4>
    {0.0} <music21.note.Note C>
    {1.0} <music21.chord.Chord C3 E4 G5>
{2.0} <music21.stream.Measure 2 offset=2.0>
    {0.0} <music21.note.Note F>
    {1.5} <music21.chord.Chord D3 F#3 A3>
    {2.0} <music21.bar.Barline type=final>

If you want to create a very different dialect, you can subclass tinyNotation.Converter
and set it up once to use the mappings above.   See
:class:`~music21.alpha.trecento.notation.TrecentoTinyConverter` (especially the code)
for details on how to do that.
    )annotationsN)note)duration)environment)exceptions21)stream)tie)expressions)meter)pitch)Music21ObjecttinyNotationc                      \ rS rSrSrg)TinyNotationException    N)__name__
__module____qualname____firstlineno____static_attributes__r       N/home/james-whalen/.local/lib/python3.13/site-packages/music21/tinyNotation.pyr   r      s    r   r   c                  t    \ rS rSr% SrSrS\S'   SSS jjrS rSS	 jr	SS
 jr
    SS jr    SS jrSrg)Statei  am  
State tokens apply something to
every note found within it.

State objects can have "autoExpires" set, which is False if it does not expire
or an integer if it expires after a certain number of tokens have been processed.

>>> tnc = tinyNotation.Converter()
>>> ts = tinyNotation.TieState(tnc, '~')
>>> isinstance(ts, tinyNotation.State)
True
>>> ts.autoExpires
2
Fztyping.Literal[False] | intautoExpiresNc                *    / U l         Xl        X l        g NaffectedTokensparent	stateInfo)selfr!   r"   s      r   __init__State.__init__  s    35&,#,r   c                    g)z$
called when the state is initiated
Nr   r#   s    r   startState.start  s     	r   c                    g)z"
called just after removing state
Nr   r'   s    r   end	State.end"  s     r   c                    U$ )z)
called to modify the string of a token.
r   )r#   tokenStrs     r   affectTokenBeforeParseState.affectTokenBeforeParse(  s	     r   c                    U$ )zS
called after the object has been acquired but before modifiers have been applied.
r   r#   m21Objs     r   $affectTokenAfterParseBeforeModifiers*State.affectTokenAfterParseBeforeModifiers.  	     r   c                   U R                   R                  U5        U R                  SLa  [        U R                   5      U R                  :X  a~  U R	                  5         U R
                  nUc  U$ [        [        UR                  5      5       H;  nSUS-   -  nUR                  U   U L d  M  UR                  R                  U5          U$    U$ )zd
called to modify the tokenObj after parsing

tokenObj may be None if another
state has deleted it.
F   )	r    appendr   lenr+   r!   rangeactiveStatespop)r#   r3   pi	backCounts        r   affectTokenAfterParseState.affectTokenAfterParse7  s     	""6*5(4&&'4+;+;;
KK9!M s1>>23A "a!eI~~i0D8**95 4
 r   r   )NN)r!   Converter | Noner"   z
str | None)returnzMusic21Object | None)r.   strrE   rF   )r3   r   rE   r   )r   r   r   r   __doc__r   __annotations__r$   r(   r+   r/   r4   rB   r   r   r   r   r   r     sV     .3K*2- 
 
r   r   c                  "    \ rS rSrSrSrS rSrg)TieStateiV  zm
A TieState is an auto-expiring state that applies a tie start to this note and a
tie stop to the next note.
   c                J   U R                   S   R                  c)  [        R                  " S5      U R                   S   l        OSU R                   S   R                  l        [	        U R                   5      S:  a)  [        R                  " S5      U R                   S   l        gg)zA
end the tie state by applying tie ties to the appropriate notes
r   Nr(   continuer9   stop)r    r	   Tietyper;   r'   s    r   r+   TieState.end]  s     q!%%-),)9D"&.8D"&&+t""#a'),D"& (r   r   N)r   r   r   r   rG   r   r+   r   r   r   r   rJ   rJ   V  s     K	9r   rJ   c                  :   ^  \ rS rSrSrSrSrS rU 4S jrSr	U =r
$ )TupletStateii  z
a tuplet state applies tuplets to notes while parsing and sets 'start' and 'stop'
on the first and last note when end is called.
   rK   c                    U R                   (       d  gSU R                   S   R                  R                  S   l        SU R                   S   R                  R                  S   l        g)zG
end a tuplet by putting start on the first note and stop on the last.
Nr(   r   rN   r8   )r    r   tupletsrP   r'   s    r   r+   TupletState.endq  s[     "":AA''//27;AB((0038r   c                  > [         TU ]  U5        [        R                  " 5       n[        R                  " UR                  R
                  S5      Ul        [        R                  " UR                  R
                  S5      Ul        U R                  Ul	        U R                  Ul        UR                  R                  U5        U$ )z
puts a tuplet on the note
r   )superrB   r   TupletdurationTupleFromTypeDotsrP   durationActualdurationNormalactualnumberNotesActualnormalnumberNotesNormalappendTuplet)r#   nnewTup	__class__s      r   rB   !TupletState.affectTokenAfterParse{  s     	%a(" ( B B1::??TU V ( B B1::??TU V#';; #';; 	

'r   r   )r   r   r   r   rG   r^   r`   r+   rB   r   __classcell__re   s   @r   rS   rS   i  s#     FF r   rS   c                       \ rS rSrSrSrSrSrg)TripletStatei  z
a 3:2 tuplet
rT   rK   r   Nr   r   r   r   rG   r^   r`   r   r   r   r   rj   rj          FFr   rj   c                       \ rS rSrSrSrSrSrg)QuadrupletStatei  z
a 4:3 tuplet
   rT   r   Nrk   r   r   r   rn   rn     rl   r   rn   c                  *    \ rS rSrSrS rS rS rSrg)Modifieri  zZ
a modifier is something that changes the current
token, like setting the `.id` or Lyric.
c                (    Xl         X l        X0l        g r   modifierDatamodifierStringr!   )r#   rt   ru   r!   s       r   r$   Modifier.__init__  s    (,r   c                    g)z>
called before the tokenString has been
turned into an object
Nr   )r#   tokenStrings     r   preParseModifier.preParse  s    
 	r   c                    U$ )z
called after the tokenString has been
turned into an m21Obj.  m21Obj may be None

Important: must return the m21Obj, or a different object!
r   r2   s     r   	postParseModifier.postParse  r6   r   rs   N)	r   r   r   r   rG   r$   ry   r|   r   r   r   r   rq   rq     s    

r   rq   c                      \ rS rSrSrS rSrg)
IdModifieri  z6
sets the .id of the m21Obj, called with = by default
c                J    [        US5      (       a  U R                  Ul        U$ )Nid)hasattrrt   r   r2   s     r   r|   IdModifier.postParse  s!    64  ))FIr   r   Nr   r   r   r   rG   r|   r   r   r   r   r   r         r   r   c                      \ rS rSrSrS rSrg)LyricModifieri  z9
sets the .lyric of the m21Obj, called with _ by default
c                J    [        US5      (       a  U R                  Ul        U$ )Nlyric)r   rt   r   r2   s     r   r|   LyricModifier.postParse  s!    67##,,FLr   r   Nr   r   r   r   r   r     r   r   r   c                  (    \ rS rSrSrSS jrS rSrg)Tokeni  zL
A single token made from the parser.

Call .parse(parent) to make it work.
c                    Xl         g r   token)r#   r   s     r   r$   Token.__init__  s    
r   c                    g)z*
do NOT store parent -- probably
too slow
Nr   )r#   r!   s     r   parseToken.parse  s    
 r   r   N )r   r   r   r   rG   r$   r   r   r   r   r   r   r     s    r   r   c                      \ rS rSrSrS rSrg)TimeSignatureTokeni  z.
Represents a single time signature, like 1/4
c                b    [         R                  " U R                  5      nX!R                  S'   U$ )NcurrentTimeSignature)r   TimeSignaturer   	stateDict)r#   r!   tsObjs      r   r   TimeSignatureToken.parse  s*    ##DJJ/38/0r   r   Nr   r   r   r   rG   r   r   r   r   r   r   r     s    r   r   c                  B   ^  \ rS rSrSrSU 4S jjrS rS rS rSr	U =r
$ )	NoteOrRestTokeni  zD
represents a Note or Rest.  Chords are represented by Note objects
c                D   > [         TU ]  U5        SS/U l        SU l        g )N)z(\d+)durationType)z(\.+)dotsF)rY   r$   durationMapdurationFoundr#   r   re   s     r   r$   NoteOrRestToken.__init__  s*    &
 #r   c                |   U R                    H9  u  pE[        R                  " XB5      nU(       d  M$  [        X5      nU" XXBU5      nM;     U R                  SL a/  [        US5      (       a  UR                  S   UR                  l        [        US5      (       a#  UR                  R                  UR                  S'   U$ )za
takes the information in the string `t` and creates a Duration object for the
note or rest `n`.
Fr   lastDuration)	r   researchgetattrr   r   r   r   quarterLength)r#   rc   tr!   pmmethodsearchSuccesscallFuncs           r   applyDurationNoteOrRestToken.applyDuration  s    
 **JBIIb,M}"40Qrf=	 + &76;+G+G'-'7'7'GAJJ$ 6;''/0zz/G/GF^,r   c                   SU l         [        UR                  S5      5      nUS:X  aq  UR                  S   b`  [        R
                  " UR                  S   R                  5      Ul        UR                  R                  [        R                  " 5       5        O# [        R                  U   UR                  l        [        R                   " USU5      nU$ ! [         a  n[        SU 35      UeSnAff = f)z\
The result of a successful search for a duration type: puts a Duration in the right place.
Tr9   r   r   Nz!Cannot parse token with duration r   )r   intgroupr   copydeepcopybarDurationr   r
   r:   FermatatypeFromNumDictrP   KeyErrorr   r   sub)r#   elementr   r   r   r!   typeNumkes           r   r   NoteOrRestToken.durationType  s     "fll1o&a< 67C#'==$$%;<HH$  ##**;+>+>+@A(0(@(@(I  %
 FF2r1  +7yAs   "C 
C4 C//C4c                    [        UR                  S5      5      UR                  l        [        R
                  " USU5      nU$ )z
adds the appropriate number of dots to the right place.

Subclassed in TrecentoNotation where two dots has a different meaning.
r9   r   )r;   r   r   r   r   r   )r#   r   r   r   r   r!   s         r   r   NoteOrRestToken.dots  s6     !$FLLO 4FF2r1r   )r   r   r   )r   r   r   r   rG   r$   r   r   r   r   rg   rh   s   @r   r   r     s!    #(, r   r   c                  &    \ rS rSrSrSSS jjrSrg)	RestTokeni(  z1
A token starting with 'r', representing a rest.
Nc                h    [         R                  " 5       nU R                  X R                  U5        U$ r   )r   Restr   r   )r#   r!   rs      r   r   RestToken.parse,  s&    IIK1jj&1r   r   r   r!   rD   r   r   r   r   r   r   (  s     r   r   c                     ^  \ rS rSrSr\R                  " / SQ5      rSU 4S jjrSSS jjr	S r
S rS rS	 rS
 rS rS rS rSrU =r$ )	NoteTokeni2  a  
A NoteToken represents a single Note with pitch

>>> c3 = tinyNotation.NoteToken('C')
>>> c3
<music21.tinyNotation.NoteToken object at 0x10b07bf98>
>>> n = c3.parse()
>>> n
<music21.note.Note C>
>>> n.nameWithOctave
'C3'

>>> bFlat6 = tinyNotation.NoteToken("b''-")
>>> bFlat6
<music21.tinyNotation.NoteToken object at 0x10b07bf98>
>>> n = bFlat6.parse()
>>> n
<music21.note.Note B->
>>> n.nameWithOctave
'B-6'
))	lowOctavez([A-G]+))
highOctavez([a-g])(\'*))editorialAccidentalz\(([\#\-n]+)\)(.*))sharpsz(\#+))flatsz(\-+))naturalz(n)c                2   > [         TU ]  U5        SU l        g )NF)rY   r$   isEditorialr   s     r   r$   NoteToken.__init__Q  s     r   c                    U R                   n[        R                  " 5       nU R                  X25      nU(       a  U R	                  X2U5        U$ )z<
Extract the pitch from the note and then returns the Note.
)r   r   NoteprocessPitchMapr   )r#   r!   r   rc   s       r   r   NoteToken.parseU  s@     JJIIK  &qV,r   c                    U R                   R                  5        H8  u  p4[        R                  " XB5      nU(       d  M$  [	        X5      nU" XXB5      nM:     U$ )z'
processes the pitchMap on the object.
)pitchMapitemsr   r   r   )r#   rc   r   r   r   r   r   s          r   r   NoteToken.processPitchMapa  sM     ----/JFIIb,M}"40Qr5	 0
 r   c                Z    SU l         UR                  S5      UR                  S5      -   nU$ )zV
indicates that the accidental is in parentheses, so set it up to be stored in ficta.
Tr9   rK   )r   r   r#   rc   r   r   r   s        r   r   NoteToken.editorialAccidentall  s+      LLOfll1o-r   c                    [         R                  " U5      nU R                  (       a  XQR                  l        OXQR                   l        [        R                  " USU5      nU$ )a  
helper function for all accidental types.

>>> nToken = tinyNotation.NoteToken('BB--')
>>> n = note.Note('B')
>>> n.octave = 2
>>> tPost = nToken._addAccidental(n, -2, r'(\-+)', 'BB--')
>>> tPost
'BB'
>>> n.pitch.accidental
<music21.pitch.Accidental double-flat>

>>> nToken = tinyNotation.NoteToken('BB(--)')
>>> nToken.isEditorial = True
>>> n = note.Note('B')
>>> n.octave = 2
>>> tPost = nToken._addAccidental(n, -2, r'(\-+)', 'BB--')
>>> tPost
'BB'
>>> n.editorial.ficta
<music21.pitch.Accidental double-flat>
r   )r   
Accidentalr   	editorialficta
accidentalr   r   )r#   rc   alterr   r   accs         r   _addAccidentalNoteToken._addAccidentalt  sH    0 u% #KK!$GGFF2r1r   c                Z    [        UR                  S5      5      nU R                  XX45      $ )a  
called when one or more sharps have been found and adds the appropriate accidental to it.

>>> import re
>>> tStr = 'C##'
>>> nToken = tinyNotation.NoteToken(tStr)
>>> n = note.Note('C')
>>> n.octave = 3
>>> searchResult = re.search(nToken.pitchMap['sharps'], tStr)
>>> tPost = nToken.sharps(n, searchResult, nToken.pitchMap['sharps'], tStr)
>>> tPost
'C'
>>> n.pitch.accidental
<music21.pitch.Accidental double-sharp>
r9   r;   r   r   r#   rc   r   r   r   r   s         r   r   NoteToken.sharps  s)    " FLLO$""1R33r   c                `    S[        UR                  S5      5      -  nU R                  XX45      $ )a  
called when one or more flats have been found and calls adds
the appropriate accidental to it.

>>> import re
>>> tStr = 'BB--'
>>> nToken = tinyNotation.NoteToken(tStr)
>>> n = note.Note('B')
>>> n.octave = 2
>>> searchResult = re.search(nToken.pitchMap['flats'], tStr)
>>> tPost = nToken.flats(n, searchResult, nToken.pitchMap['flats'], tStr)
>>> tPost
'BB'
>>> n.pitch.accidental
<music21.pitch.Accidental double-flat>
r8   r9   r   r   s         r   r   NoteToken.flats  s.    $ Sa))""1R33r   c                (    U R                  USX45      $ )a  
called when an explicit natural has been found.  All pitches are natural without
being specified, so not needed. Adds a natural accidental to it.

>>> import re
>>> tStr = 'En'
>>> nToken = tinyNotation.NoteToken(tStr)
>>> n = note.Note('E')
>>> n.octave = 3
>>> searchResult = re.search(nToken.pitchMap['natural'], tStr)
>>> tPost = nToken.natural(n, searchResult, nToken.pitchMap['natural'], tStr)
>>> tPost
'E'
>>> n.pitch.accidental
<music21.pitch.Accidental natural>
r   )r   r   s        r   r   NoteToken.natural  s    $ ""1a//r   c                    UR                  S5      S   R                  5       nS[        UR                  S5      5      -
  nXQl        Xal        [
        R                  " USU5      nU$ )aI  
Called when a note of octave 3 or below is encountered.

>>> import re
>>> tStr = 'BBB'
>>> nToken = tinyNotation.NoteToken(tStr)
>>> n = note.Note('B')
>>> searchResult = re.search(nToken.pitchMap['lowOctave'], tStr)
>>> tPost = nToken.lowOctave(n, searchResult, nToken.pitchMap['lowOctave'], tStr)
>>> tPost
''
>>> n.octave
1
r9   r   ro   r   r   upperr;   stepoctaver   r   r#   rc   r   r   r   stepName	octaveNums          r   r   NoteToken.lowOctave  W      <<?1%++-FLLO,,	FF2r1r   c                    UR                  S5      S   R                  5       nS[        UR                  S5      5      -   nXQl        Xal        [
        R                  " USU5      nU$ )aM  
Called when a note of octave 4 or higher is encountered.

>>> import re
>>> tStr = "e''"
>>> nToken = tinyNotation.NoteToken(tStr)
>>> n = note.Note('E')
>>> searchResult = re.search(nToken.pitchMap['highOctave'], tStr)
>>> tPost = nToken.highOctave(n, searchResult, nToken.pitchMap['highOctave'], tStr)
>>> tPost
''
>>> n.octave
6
r9   r   ro   rK   r   r   r   s          r   r   NoteToken.highOctave  r   r   )r   r   r   r   )r   r   r   r   rG   collectionsOrderedDictr   r$   r   r   r   r   r   r   r   r   r   r   rg   rh   s   @r   r   r   2  sW    * && ( H!
	@4(4*0(. r   r   c                     Sn SU  S3nU SU  S3nSU S3nSS	U S
U S3-   nU SU 3nSnSnSnSn	Sn
SnSnSnU SU	 SU
 S3U SU SU 3-   nS[         4SU SU S3[        4SU SU S3SU SU S3-   [        4/$ )a	  
Returns the default tokenMap for TinyNotation.

Based on the following grammar (in Extended Backus-Naur form)
(https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form)

(* Items in parentheses are grouped *)
(* Items in curly braces appear zero or more times *)
(* Items in square brackets may appear exactly zero or one time *)
(* Items in double quotes are literal strings *)
(* Items between question marks should be interpreted as English *)
(* Each rule is ended by a semicolon *)

TINY-NOTATION = TOKEN, { WHITESPACE, TOKEN } ;
WHITESPACE = ( " " | ? Carriage return ? ) , { " " | ? Carriage return ? } ;
TOKEN = ( TIME-SIGNATURE | TUPLET | REST | NOTE );
TIME-SIGNATURE = INTEGER, "/", INTEGER ;
INTEGER = DIGIT, { DIGIT } ;
DIGIT = ( "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ) ;
TUPLET = ( "trip" | "quad" | ALPHANUMERIC ), "{",
    [ WHITESPACE ],
    ( REST | NOTE ),
    { WHITESPACE, ( REST | NOTE ) },
    [ WHITESPACE ],
"}" ;
REST = "r", [ DURATION ], [ MODIFIER ] ;
DURATION = ( EVEN-NUMBER, { "." } | { "." }, EVEN-NUMBER | ".", { "." } ) ;
EVEN-NUMBER = { INTEGER }, ( "0" | "2" | "4" | "6" | "8" ) ;
NOTE = PITCH, [ DURATION ], [ TIE ], { MODIFIER } ;
PITCH = (
    ( LOW-A | LOW-B | LOW-C | LOW-D | LOW-E | LOW-F | LOW-G ), [ ACCIDENTAL ] |
    ( "a" | "b" | "c" | "d" | "e" | "f" | "g" ), [ ACCIDENTAL ], { "'" } |
    ( "a" | "b" | "c" | "d" | "e" | "f" | "g" ), { "'" }, [ ACCIDENTAL ]
) ;
LOW-A = "A", { "A" } ;
LOW-B = "B", { "B" } ;
LOW-C = "C", { "C" } ;
LOW-D = "D", { "D" } ;
LOW-E = "E", { "E" } ;
LOW-F = "F", { "F" } ;
LOW-G = "G", { "G" } ;
ACCIDENTAL = ( EDITORIAL | SHARPS | FLATS | NATURAL ) ;
EDITORIAL = "(", ( SHARPS | FLATS | NATURAL ), ")" ;
SHARPS = "#", { "#" } ;
FLATS = "-", { "-" } ;
NATURAL = "n" ;
TIE = "~" ;
MODIFIER = (
    EQUALS-MODIFIER |
    UNDERSCORE-MODIFIER |
    SQUARE-MODIFIER |
    ANGLE-MODIFIER |
    PARENS-MODIFIER |
    STAR-MODIFIER
) ;
EQUALS-MODIFIER = "=", EQUALS-DATA ;
UNDERSCORE-MODIFIER = "_", UNDERSCORE-DATA ;
SQUARE-MODIFIER = "[", ALPHANUMERIC, "]" ;
ANGLE-MODIFIER = "<", ALPHANUMERIC, ">" ;
PARENS-MODIFIER = "(", ALPHANUMERIC, ")" ;
STAR-MODIFIER = "*", ALPHANUMERIC, "*" ;
(* The following is just shorthand. *)
ALPHANUMERIC = ? At least one alphanumeric character. So "a-z", "A-Z", or "0-9" ? ;
EQUALS-DATA = ? At least one non-whitespace, non-"_" character. ? ;
UNDERSCORE-DATA = ? At least one non-whitespace, non-"=" character. ? ;
z#+|-+|nz\((?:z)\)z|(?:)z(?:A+|B+|C+|D+|E+|F+|G+)(?:z)?z(?:a|b|c|d|e|f|g)z(?:(?:z
)?'*|'*(?:z)?)|z\d+\.*|\.*\d+|\.+~z=[^\s_]*z\*.*?\*z<.*?>z\(.*?\)z\[.*?]z_[^\s=]z^(\d+\/\d+)$z^r((?:z)?(?:z)*)$z^((?:z)(?:z(?:)r   r   r   )sharpsFlatsOrNaturalRegexeditorialRegexaccidentalRegexlowNoteRegexhighNoteRegexnoteNameRegexdurationRegextieStateRegexequalsRegex	starRegex
angleRegexparensRegexsquareRegexunderscoreRegexmodifierRegexs                  r   _getDefaultTokenMapr     s5   F !+78<N().G-HJO1/1B"ELO$J.?s
C	D  %~Q}o6M(MMKIJKK O=)Aj\3]!K=/):
;	<  
,-m_E-=	
 tM?"=u]O4@A 	
 r         ?)r   r   c                  d   \ rS rSrSr\\S.r\R                  " S5      r
\R                  " S5      r\R                  " S5      r\R                  " S5      r\R                  " S5      r\R                  " S	5      r SS
SS.     SS jjjrSS jrS rS rS rSS jrSS jrSS jrS rS rSrg)	Converterir  a_  
Main conversion object for TinyNotation.

Accepts keywords:

* `makeNotation=False` to get "classic" TinyNotation formats without
   measures, Clefs, etc.
* `raiseExceptions=True` to make errors become exceptions.

Generally, users should just use the general music21 converter (lowercase c) parse
function and do not need to be in this module at all:

>>> part = converter.parse('4/4 C4 D4 E2 F1', format='tinyNotation')
>>> part.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 4/4>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
{4.0} <music21.stream.Measure 2 offset=4.0>
    {0.0} <music21.note.Note F>
    {4.0} <music21.bar.Barline type=final>

But for advanced work, create a tinyNotation.Converter object as shown:

>>> tnc = tinyNotation.Converter('4/4 C##4 D e-8 f~ f f# g4 trip{f8 e d} C2=hello')

Run the parsing routine with `.parse()`

>>> tnc.parse()
<music21.tinyNotation.Converter object at 0x10aeefbe0>

And now the `.stream` attribute of the converter object
has the Stream (generally Part) ready to send out:

>>> tnc.stream
<music21.stream.Part 0x10acee860>

And all normal Stream methods are available on it:

>>> tnc.stream.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.TrebleClef>
    {0.0} <music21.meter.TimeSignature 4/4>
    {0.0} <music21.note.Note C##>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E->
    {2.5} <music21.note.Note F>
    {3.0} <music21.note.Note F>
    {3.5} <music21.note.Note F#>
{4.0} <music21.stream.Measure 2 offset=4.0>
    {0.0} <music21.note.Note G>
    {1.0} <music21.note.Note F>
    {1.3333} <music21.note.Note E>
    {1.6667} <music21.note.Note D>
    {2.0} <music21.note.Note C>
    {4.0} <music21.bar.Barline type=final>


Or, breaking down what Parse does bit by bit:

>>> tnc = tinyNotation.Converter('4/4 C##4 D e-8 f~ f f# g4 trip{f8 e d} C2=hello')
>>> tnc.stream
<music21.stream.Part 0x10acee860>
>>> tnc.makeNotation
True
>>> tnc.stringRep
'4/4 C##4 D e-8 f~ f f# g4 trip{f8 e d} C2=hello'
>>> tnc.activeStates
[]
>>> tnc.preTokens
[]
>>> tnc.splitPreTokens()
>>> tnc.preTokens
['4/4', 'C##4', 'D', 'e-8', 'f~', 'f', 'f#', 'g4', 'trip{f8', 'e', 'd}', 'C2=hello']
>>> tnc.setupRegularExpressions()

Then we parse the time signature.
>>> tnc.parseOne(0, tnc.preTokens[0])
>>> tnc.stream.coreElementsChanged()
>>> tnc.stream.show('text')
{0.0} <music21.meter.TimeSignature 4/4>

(Note that because we are calling
`show()` after each note in these docs, but TinyNotation
uses high efficiency `stream.core` routines, we need to set the stream
to a stable-state by calling `coreElementsChanged` after each call.
You would not need to do this in your own subclasses, since that would
lose the `O(n)` efficiency when parsing)

Then parse the first actual note:

>>> tnc.parseOne(1, tnc.preTokens[1])
>>> tnc.stream.coreElementsChanged()
>>> tnc.stream.show('text')
{0.0} <music21.meter.TimeSignature 4/4>
{0.0} <music21.note.Note C##>

The next notes to 'g4' are pretty similar:

>>> for i in range(2, 8):
...     tnc.parseOne(i, tnc.preTokens[i])
>>> tnc.stream.coreElementsChanged()
>>> tnc.stream.show('text')
{0.0} <music21.meter.TimeSignature 4/4>
{0.0} <music21.note.Note C##>
{1.0} <music21.note.Note D>
{2.0} <music21.note.Note E->
{2.5} <music21.note.Note F>
{3.0} <music21.note.Note F>
{3.5} <music21.note.Note F#>
{4.0} <music21.note.Note G>

The next note starts a "State" since it has a triplet:

>>> tnc.preTokens[8]
'trip{f8'
>>> tnc.parseOne(8, tnc.preTokens[8])
>>> tnc.activeStates
[<music21.tinyNotation.TripletState object at 0x10ae9dba8>]
>>> tnc.activeStates[0].affectedTokens
[<music21.note.Note F>]

The state is still active for the next token:

>>> tnc.preTokens[9]
'e'
>>> tnc.parseOne(9, tnc.preTokens[9])
>>> tnc.activeStates
[<music21.tinyNotation.TripletState object at 0x10ae9dba8>]
>>> tnc.activeStates[0].affectedTokens
[<music21.note.Note F>, <music21.note.Note E>]

The :class:`~music21.tinyNotation.TripletState` state adds
tuplets along the way, but does not set their type.

>>> f_starts_tuplet = tnc.activeStates[0].affectedTokens[0]
>>> f_starts_tuplet.duration.tuplets
(<music21.duration.Tuplet 3/2/eighth>,)
>>> f_starts_tuplet.duration.tuplets[0].type is None
True

But the next token closes the state:

>>> tnc.preTokens[10]
'd}'
>>> tnc.parseOne(10, tnc.preTokens[10])
>>> tnc.activeStates
[]

And this sets the tupet types for the F and D properly:

>>> f_starts_tuplet.duration.tuplets[0].type
'start'

>>> tnc.stream.coreElementsChanged()
>>> tnc.stream.show('text')
{0.0} <music21.meter.TimeSignature 4/4>
...
{4.0} <music21.note.Note G>
{5.0} <music21.note.Note F>
{5.3333} <music21.note.Note E>
{5.6667} <music21.note.Note D>

The last token has a modifier, which is an IdModifier:

>>> tnc.preTokens[11]
'C2=hello'
>>> tnc.parseOne(11, tnc.preTokens[11])
>>> tnc.stream.coreElementsChanged()
>>> tnc.stream.show('text')
{0.0} <music21.meter.TimeSignature 4/4>
...
{5.6667} <music21.note.Note D>
{6.0} <music21.note.Note C>
>>> tnc.stream[-1].id
'hello'

At this point the flattened stream is ready, if Converter.makeNotation
is False, then not much more needs to happen, but it is True by default.

So, then calling tnc.postParse() runs the makeNotation:

>>> tnc.postParse()
>>> tnc.stream.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.TrebleClef>
    {0.0} <music21.meter.TimeSignature 4/4>
    {0.0} <music21.note.Note C##>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E->
    {2.5} <music21.note.Note F>
    {3.0} <music21.note.Note F>
    {3.5} <music21.note.Note F#>
{4.0} <music21.stream.Measure 2 offset=4.0>
    {0.0} <music21.note.Note G>
    {1.0} <music21.note.Note F>
    {1.3333} <music21.note.Note E>
    {1.6667} <music21.note.Note D>
    {2.0} <music21.note.Note C>
    {4.0} <music21.bar.Barline type=final>

Let's look at edge cases. Normally, invalid notes or
other bad tokens pass freely by dropping the unparseable token.
Here `3` is not a valid duration, so `d3` will be dropped.

>>> x = converter.parse('tinyNotation: 4/4 c2 d3 e2')
>>> x.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.TrebleClef>
    {0.0} <music21.meter.TimeSignature 4/4>
    {0.0} <music21.note.Note C>
    {2.0} <music21.note.Note E>
    {4.0} <music21.bar.Barline type=final>

But with the keyword 'raiseExceptions=True' a `TinyNotationException`
is raised if any token cannot be parsed.

>>> x = converter.parse('tinyNotation: 4/4 c2 d3 e2', raiseExceptions=True)
Traceback (most recent call last):
music21.tinyNotation.TinyNotationException: Could not parse token: 'd3'
)tripquadz=([A-Za-z0-9]*)z	\*(.*?)\*z<(.*?)>z	\((.*?)\)z\[(.*?)]z_(.*)TF)makeNotationraiseExceptionsc                  [         R                  " 5       U l         [        R                  " [        5      U l        Xl        / U l        / U l        [        R                  " S5      U l
        [        R                  " S5      U l        [        5       U l        [        U l        S U l        S U l        S U l        S U l        [(        U l        X l        X0l        / U l        g )Nz(\w+){r  )r   Partr   _stateDictDefaultr   	stringRepr=   	preTokensr   compilegeneralBracketStateRe
tieStateRer  tokenMapr   modifierEqualsmodifierStarmodifierAnglemodifierParensmodifierSquarer   modifierUnderscorer  r  _tokenMapRe)r#   r  r  r  	_keywordss        r   r$   Converter.__init__^  s     kkm#45")+$&%'ZZ	%:"**T*+-( !"""/(.>@r   c                    [         R                  " 5       U l         [        R                  " [        5      U l        / U l        / U l        Xl        g)a}  
Loads a stringRepresentation into `.stringRep`
and resets the parsing state.

>>> tnc = tinyNotation.Converter()
>>> tnc.load('4/4 c2 d e f')
>>> s = tnc.parse().stream
>>> tnc.load('4/4 f e d c')
>>> s2 = tnc.parse().stream
>>> ns2 = s2.flatten().notes

Check that the duration of 2.0 from the first load did not carry over.

>>> ns2[0].duration.quarterLength
1.0
>>> len(ns2)
4
N)r   r  r   r  r   r=   r   r  )r#   r  s     r   loadConverter.load|  s6    * kkm#45"r   c                B    U R                   R                  5       U l        g)z
splits the string into textual preTokens.

Right now just splits on spaces, but might be smarter to ignore spaces in
quotes, etc. later.
N)r  splitr   r'   s    r   splitPreTokensConverter.splitPreTokens  s     --/r   c                    / U l         U R                   H7  u  p U R                   R                  [        R                  " U5      U45        M9     g! [        R
                   a  n[        SU SU 35      UeSnAff = f)a  
Regular expressions get compiled for faster
usage.  This is called automatically by .parse(), but can be
called separately for testing.  It is also important that it
is not called in __init__ since subclasses should override the
tokenMap, etc. for a class.
zError in compiling token, z: N)r+  r$  r:   r   r!  errorr   )r#   rePre	classCalles       r   setupRegularExpressions!Converter.setupRegularExpressions  sz      $E  ''E):I(FG !. 88 +0r!=s   1AA;$A66A;c                (   U R                   (       d   U R                  S:w  a  U R                  5         U R                  (       d  U R	                  5         [        U R                   5       H  u  pU R                  X5        M     U R                  5         U $ )z_
splitPreTokens, setupRegularExpressions, then runs
through each preToken, and runs postParse.
r   )r   r  r3  r+  r:  	enumerateparseOner|   )r#   r@   r   s      r   r   Converter.parse  sg    
 ~~$..B"6!((*dnn-DAMM! .r   c                   UnU R                  U5      nU R                  U5      u  p$U R                  U5      u  p%U R                  SS  H  nUR	                  U5      nM     SnSnSn	U R
                   HM  u  pU
R                  U5      nUc  M  Sn	UR                  S5      nU" U5      n UR                  U 5      nUb    OMO     U	(       d   U R                  (       a  [        SU< 35      eUb'  U R                  SS  H  nUR                  U5      nM     Ub  U H  nUR                  U5      nM     Ub'  U R                  SS  H  nUR                  U5      nM     Ub  U R                  R                  U5        U[!        U R                  5      :  a6  U R                  (       a  [        SU< S35      e[!        U R                  5      n[#        U5       HM  nU R                  R%                  5       nUR'                  5       nUc  M2  U R                  R                  U5        MO     g! [         a-  nU R                  (       a  [        SU< 35      Ue SnAGM  SnAff = f)z
parse a single token at position i, with
text t, possibly adding it to the stream.

Checks for state changes, modifiers, tokens, and end-state brackets.
NFTr9   zCould not parse token: zToken z" closes more states than are open.)parseStartStatesparseEndStatesparseModifiersr=   r/   r+  matchr   r   r   r  r4   r|   rB   r   
coreAppendr;   r<   r>   r+   )r#   r@   r   t_orignumberOfStatesToEndactiveModifiersstateObjr3   tokenObjhasMatchtokenRe
tokenClassmatchSuccess	tokenDataexcepmodObjstateToRemovepossibleObjs                     r   r>  Converter.parseOne  s\    !!!$!%!4!4Q!7!003 ))!,H//2A -  #'#3#3G"==+L#H$**1-I!),Ha!-% & $4  D00'*A&(LMM --a0!FFvN 1 )))&1 *  --a0!77? 1 KK""6*T%6%6!77##+fVJ>`,abb"%d&7&7"8*+A --113M'++-K&&&{3	 ,7 ) a''/2I&0TU[`` (as   *H&&
I0!IIc                &   U R                   R                  U5      nU(       a  UR                  S5      nUR                  S5      nU R                   R                  SUSS9nU R                   R                  U5      nX@R                  ;  a9  SU< 3nU R
                  (       a  [        U5      e[        R                  U5        M  U R                  U   " X5      nUR                  5         U R                  R                  U5        U(       a  M  U R                  R                  U5      nU(       ac  UR                  S5      nU R                  R                  SU5      n[        X5      nUR                  5         U R                  R                  U5        U$ )av  
Changes the states in self.activeStates, and starts the state given the current data.
Returns a newly processed token.

A contrived example:

>>> tnc = tinyNotation.Converter()
>>> tnc.setupRegularExpressions()
>>> len(tnc.activeStates)
0
>>> tIn = 'trip{quad{f8~'
>>> tOut = tnc.parseStartStates(tIn)
>>> tOut
'f8'
>>> len(tnc.activeStates)
3
>>> tripState = tnc.activeStates[0]
>>> tripState
<music21.tinyNotation.TripletState object at 0x10afaa630>

>>> quadState = tnc.activeStates[1]
>>> quadState
<music21.tinyNotation.QuadrupletState object at 0x10adcb0b8>

>>> tieState = tnc.activeStates[2]
>>> tieState
<music21.tinyNotation.TieState object at 0x10afab048>

>>> tieState.parent is tnc
True
>>> tieState.stateInfo
'~'
>>> quadState.stateInfo
'quad{'


Note that the affected tokens haven't yet been added:

>>> tripState.affectedTokens
[]

Unknown state gives a warning or if `.raisesException=True` raises a
TinyNotationException

>>> tnc.raiseExceptions = True
>>> tIn = 'blah{f8~'
>>> tOut = tnc.parseStartStates(tIn)
Traceback (most recent call last):
music21.tinyNotation.TinyNotationException: Incorrect bracket state: 'blah'
r   r9   r   )countzIncorrect bracket state: )r"  r   r   r   bracketStateMappingr  r   environLocalwarnr(   r=   r:   r#  rJ   )	r#   r   bracketMatchSuccess	stateDatabracketTypemsgrI  tieMatchSuccesstieStates	            r   rA  Converter.parseStartStates  sY   h #88??B!+11!4I-33A6K**..r1A.>A"&"<"<"C"CA"F":"::1+A''/44 !!#&//<TMHNN$$X.! "!& //003'--a0I##B*A0HNN$$X.r   c                N    UR                  S5      nUR                  SS5      nX4$ )z
Trims the endState token (`}`) from the t string
and then returns a two-tuple of the new token and number
of states to remove:

>>> tnc = tinyNotation.Converter()
>>> tnc.parseEndStates('C4')
('C4', 0)
>>> tnc.parseEndStates('C4}}')
('C4', 2)
}r   )rV  replace)r#   r   endBracketss      r   rB  Converter.parseEndStatesX  s)     ggclIIc2~r   c                H   / nS H~  n[        U SU-   S5      nUc  M  [        U SU-   S-   S5      nUR                  U5      nUc  MA  UR                  S5      nUR                  SU5      nU" XqU 5      nUR	                  U5        M     U H  n	U	R                  U5        M     X4$ )a  
Parses `modifierEquals`, `modifierUnderscore`, `modifierStar`, etc.
for a given token and returns the modified token and a
(possibly empty) list of activeModifiers.

Modifiers affect only the current token.  To affect
multiple tokens, use a :class:`~music21.tinyNotation.State` object.
)EqualsStarAngleParensSquare
UnderscoremodifierN	_modifierRer9   r   )r   r   r   r   r:   ry   )
r#   r   rH  modifierNamemodifierClass
modifierRefoundItrt   modifierObjectrQ  s
             r   rC  Converter.parseModifiersi  s     YL#D*|*CTJM$ {\'AD'H$OJ ''*G"&}}Q/NN2q)!.|!E&&~6 Z &FOOA & !!r   c                V    U R                   SLa  U R                  R                  SS9  gg)z
Called after all the tokens have been run.

It currently runs `.makeMeasures()` on `.stream` unless `.makeNotation` is `False`.
FT)inPlaceN)r  r   makeMeasuresr'   s    r   r|   Converter.postParse  s,     E)KK$$T$2 *r   )r+  r=   r"  r  r'  r%  r(  r)  r&  r*  r   r  r   r   r  r#  r$  Nr   )r  rF   r  boolr  rz  )r  rF   rE   None)r@   r   r   rF   )r   rF   rE   rF   )r   rF   rE   ztuple[str, int])r   r   r   r   rG   rj   rn   rW  r   r!  _modifierEqualsRe_modifierStarRe_modifierAngleRe_modifierParensRe_modifierSquareRe_modifierUnderscoreRer$   r/  r3  r:  r   r>  rA  rB  rC  r|   r   r   r   r   r  r  r  s    ^@  

#56jj.Ozz*-

<0

;/JJx0 A " %AA 	A
 A<#60$ A4HPd""83r   r  c                  <    \ rS rSrSrS	S jrS	S jrS	S jrS rSr	g)
Testi  zL1/4 trip{C8~ C~_hello C=mine} F~ F~ 2/8 F F# quad{g--16 a## FF(n) g#} g16 F0c                   [        U R                  5      nUR                  5         UR                  nUR	                  5       R                  [        R                  5      nUS   R                  nUS   R                  nUS   R                  n[        R                  (       a  Uc   eUc   eUc   eU R                  U[        R                  5        U R                  U[        R                  5        U R                  U[        R                  5        U R                  UR                  S5        U R                  UR                  S5        U R                  UR                  S5        U R                  US   R                  S5        U R                  US   R                   S5        U R                  US   R"                  S	5        U R                  US   R$                  S
5        US   R&                  R(                  nUS   R&                  R(                  n[        R                  (       a
  Uc   eUc   eU R                  UR*                  S5        U R                  UR*                  S5        U R                  US   R,                  R.                  R*                  S5        U R                  US   R0                  R2                  S5        U R                  US   R4                  S   R6                  [4        R8                  " 5       R6                  5        g )Nr   r9   rK   r(   rM   rN   CrT   hellomine      	      r  )r  	parseTestr   r   flattengetElementsByClassr   r   r	   typingTYPE_CHECKINGassertIsInstancerO   assertEqualrP   r   r   r   r   r   r   r   r   r   r   r   r
   classesr   )	r#   cssfnt0t1t2acc6acc7s	            r   testOneTest.testOne  sK   dnn%		HHiik,,TYY7VZZVZZVZZ>!>>!>>!>b#''*b#''*b#''*'**-&)Qc*Q*Qw/QF+1v||&&1v||&&######Q'R(Q))//55q9R))77=R,,Q/779L9L9N9V9VWr   c           
        SSS.SSS.SSS.SSS.SS	S.S
SS./nU HM  nU R                  [        SSUS    SUS    S3-   S9   [        US   SS9nUR                  5         S S S 5        MO     g ! , (       d  f       Ma  = f)Nhzh is not a valid note)stringreasonza;z0a semicolon is not a valid character or modifierzr;z4/4;ABCzJonly the same upper-cased letter may be repeated to indicate lower octavesaaazdthe same lower-cased letter may not be repeated to indicate higher octaves. Instead use apostrophes.z5Should have raised a TinyNotationException for input 'r  z
' because r  .)r]  T)r  )assertRaisesr   r  r   )r#   error_stateserror_state	converters       r   testRaiseExceptionsTest.testRaiseExceptions  s     1
 L
 L
 !L
  /  J1
B (K""#8K+h/0
;x;P:QQRST #  &k(&;TR	!  ( s   A//
A>	c                   [        5       nU R                  [        U5      SS5        [        S[        S[
        S0nU Ht  u  p4U R                  UUSUR                  R                   S3-   5        X$==   S-  ss'   U R                  [        U5      SSUR                  R                   S3-   5        Mv     U H  nU R                  X$   SS5        M     g )	NrT   zUThere should be three valid token types by default: Time signatures, Notes, and Restsr   z1Found unexpected token type in default token map:r  r9   ziShould provide a non-empty string for the regular expression in the default token map for tokens of type zNShould have found each valid token type exactly once in the default token map.)
r  r  r;   r   r   r   assertInre   r   assertGreater)r#   defaultTokenMapvalidTokenTypeCountsregex	tokenTypes        r   testGetDefaultTokenMapTest.testGetDefaultTokenMap  s    -/ 1		
 qq 
 !0EMM$G",,556a89	 !+q0+E
P",,556a89	 !0, .I$//	 .r   c                   [        SSS9nUR                  5         UR                  nU R                  UR                  S   R
                  R                  [        R                  " SS5      5        U R                  UR                  R                  5       R
                  R                  S5        [        SSS9nSUl
        U R                  [        S	5         UR                  5         S S S 5        g ! , (       d  f       g = f)
Nz2/4 trip{c8 d e}} f4F)r  r  r9   rT   r  Tz,Token 'e}}' closes more states than are open)r  r   r   r  notesr   r   	fractionsFractionlastr  assertRaisesRegexr   )r#   r  r  s      r   test_too_many_statesTest.test_too_many_states  s    ,5A		HH--;;Y=O=OPQST=UV00>>D,5A ##!:
 GGI	
 
 
s   C..
C<r   N)rE   r{  )
r   r   r   r   r  r  r  r  r  r   r   r   r   r  r    s    ^I!XF("T0dr   r  c                      \ rS rSrSrS rSrg)TestExternali!  Tc                    [        [        R                  5      nUR                  5         U R                  (       a  UR
                  R	                  S5        g g )Nzmusicxml.png)r  r  r  r   showr   )r#   r  s     r   r  TestExternal.testOne$  s5    dnn%		99HHMM.) r   r   N)r   r   r   r   r  r  r   r   r   r   r  r  !  s    D*r   r  __main__)rE   zlist[tuple[str, type[Token]]])0rG   
__future__r   r   r   r  r   r  unittestmusic21r   r   r   r   r   r	   r
   r   r   r  music21.baser   EnvironmentrX  Music21Exceptionr   r   rJ   rS   rj   rn   rq   r   r   r   r   r   r   r   r  r  r  TestCaser  r  
_DOC_ORDERr   mainTestr   r   r   <module>r     s  Yt #    	             
* &&~6	L99 	O Od9u 9&% @; k  8 H  $ >e >B K K\j\ ! 
Z3 Z3zO8 Od*8$$ * x0
zT r   