Differences From Artifact [9c47a4ff248a3fe2]:
- Executable file
parse.py
- 2010-11-29 07:15:15 - part of checkin [4ab39b23ec] on branch master - Chords now respect octaves (user: spiffytech@gmail.com) [annotate]
To Artifact [3ec57c3fbe75652c]:
- Executable file
parse.py
- 2011-02-10 22:34:39 - part of checkin [702d933446] on branch master - Added lexical support for parens instead of quotes for chords, cleaned up the yacc parser, added lex tokens for syncopation (user: brian@linux-85dd.site) [annotate]
15 self.value = value 15 self.value = value
16 self.duration = duration 16 self.duration = duration
17 self.chord_type = chord_type 17 self.chord_type = chord_type
18 self.octave = octave 18 self.octave = octave
19 def __repr__(self): 19 def __repr__(self):
20 return "Chord %s %s %s" % (self.value, self.duration, self.chord_type, s 20 return "Chord %s %s %s" % (self.value, self.duration, self.chord_type, s
21 21
22 <
23 class Rest(): 22 class Rest():
24 def __init__(self, duration=.25): 23 def __init__(self, duration=.25):
25 self.duration = duration 24 self.duration = duration
26 def __repr__(self): 25 def __repr__(self):
27 return "Rest node %s" % self.duration 26 return "Rest node %s" % self.duration
28 27
29 28
................................................................................................................................................................................
32 tokens = ( 31 tokens = (
33 "NOTE_LENGTH", 32 "NOTE_LENGTH",
34 "BASENOTE", 33 "BASENOTE",
35 "ACCIDENTAL", 34 "ACCIDENTAL",
36 "REST", 35 "REST",
37 "OCTAVE", 36 "OCTAVE",
38 "CHORD_TYPE", 37 "CHORD_TYPE",
> 38 "PAREN",
39 "QUOTE", | 39 "SYNCOPATE",
40 ) 40 )
41 41
42 t_ignore = " |" 42 t_ignore = " |"
43 43
44 #t_BASENOTE = r"[A-Ga-g]" 44 #t_BASENOTE = r"[A-Ga-g]"
45 t_BASENOTE = r"I+V?|VI*|i+v?|vi*" 45 t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
46 t_ACCIDENTAL = r"\^{1,2}|_{1,2}|=" 46 t_ACCIDENTAL = r"\^{1,2}|_{1,2}|="
47 t_REST = r"z" 47 t_REST = r"z"
48 t_OCTAVE = r"'+|,+" 48 t_OCTAVE = r"'+|,+"
49 t_CHORD_TYPE = r"m|7|m7|0|o|\+|mb5|sus|sus4|maj7|mmaj7|7sus4|dim|dim7|7b5|m7 49 t_CHORD_TYPE = r"m|7|m7|0|o|\+|mb5|sus|sus4|maj7|mmaj7|7sus4|dim|dim7|7b5|m7
50 t_QUOTE = '"' | 50 t_PAREN = "\(|\)"
> 51 t_SYNCOPATE = "\+|-"
51 52
52 def t_NOTE_LENGTH(t): 53 def t_NOTE_LENGTH(t):
53 r"/?\d+" 54 r"/?\d+"
54 multiplier = float(t.value.strip("/")) 55 multiplier = float(t.value.strip("/"))
55 if t.value.startswith("/"): 56 if t.value.startswith("/"):
56 multiplier = 1/multiplier 57 multiplier = 1/multiplier
57 t.value = multiplier 58 t.value = multiplier
58 return t 59 return t
59 60
60 def t_error(t): 61 def t_error(t):
61 raise TypeError("Unknown text '%s'" % (t.value,)) 62 raise TypeError("Unknown text '%s'" % (t.value,))
62 63
63 lex.lex() 64 lex.lex()
64 <
65 #lex.input("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD") <
66 #s = "GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD" <
67 #s = '''I IV V VI I "I" "ii"/2''' <
68 #s = "GF_G,/2" <
69 lex.input(score) 65 lex.input(score)
70 #for tok in iter(lex.token, None): <
71 # print repr(tok.type), repr(tok.value) <
72 66
73 67
74 # Parse (yacc) 68 # Parse (yacc)
75 69
76 <
77 def p_pitch_list(p): | 70 def p_note_list(p):
78 '''score : score note 71 '''score : score note
79 | score chord | 72 | score chord
80 | score rest | 73 | score rest
81 ''' 74 '''
82 p[0] = p[1] + [p[2]] 75 p[0] = p[1] + [p[2]]
83 76
84 def p_score(p): 77 def p_score(p):
85 '''score : note 78 '''score : note
86 | chord | 79 | chord
87 | rest | 80 | rest
88 ''' 81 '''
89 p[0] = [p[1]] 82 p[0] = [p[1]]
90 83
91 84
92 def p_note(p): | 85 def p_chord_length(p):
93 '''note : pitch | 86 ''' chord : chord NOTE_LENGTH
94 ''' 87 '''
95 p[0] = p[1] | 88 new_note = p[1]
> 89 new_note.duration = p[2]
> 90 p[0] = new_note
96 91
97 92
98 def p_note_length(p): 93 def p_note_length(p):
99 ''' note : note NOTE_LENGTH 94 ''' note : note NOTE_LENGTH
100 ''' 95 '''
101 new_note = p[1] 96 new_note = p[1]
102 new_note.duration = p[2] 97 new_note.duration = p[2]
103 p[0] = new_note 98 p[0] = new_note
104 99
105 def p_chord_length(p): <
106 ''' chord : chord NOTE_LENGTH <
107 ''' <
108 new_note = p[1] <
109 new_note.duration = p[2] <
110 p[0] = new_note <
111 100
112 <
113 def p_chord(p): 101 def p_chord(p):
114 '''chord : QUOTE pitch QUOTE | 102 '''chord : PAREN note PAREN
115 | QUOTE pitch CHORD_TYPE QUOTE | 103 | PAREN note CHORD_TYPE PAREN
116 ''' 104 '''
117 pitch = p[2].value 105 pitch = p[2].value
118 pitch = pitch.upper() 106 pitch = pitch.upper()
119 p[0] = Chord(value=pitch, octave=default_octave) 107 p[0] = Chord(value=pitch, octave=default_octave)
120 if len(p) > 3: 108 if len(p) > 3:
121 p[0].chord_type = p[3] 109 p[0].chord_type = p[3]
122 110
123 111
> 112 def p_note_syncopate(p):
> 113 ''' note : note SYNCOPATE
> 114 '''
> 115 note.syncopate = p[2]
> 116
> 117
124 def p_accidental(p): 118 def p_accidental(p):
125 '''pitch : ACCIDENTAL pitch | 119 '''note : ACCIDENTAL note
126 ''' 120 '''
127 p[2].accidental = p[1] 121 p[2].accidental = p[1]
128 p[0] = p[2] 122 p[0] = p[2]
129 123
130 def p_pitch_octave(p): | 124 def p_octave(p):
131 '''pitch : pitch OCTAVE | 125 '''note : note OCTAVE
132 ''' 126 '''
133 count = len(p[2]) 127 count = len(p[2])
134 increment_or_decrement = 1 if p[2].startswith("'") else -1 128 increment_or_decrement = 1 if p[2].startswith("'") else -1
135 p[1].octave += (count * increment_or_decrement) 129 p[1].octave += (count * increment_or_decrement)
136 p[0] = p[1] 130 p[0] = p[1]
137 131
138 def p_pitch(p): | 132 def p_note(p):
139 '''pitch : BASENOTE | 133 '''note : BASENOTE
140 ''' 134 '''
141 p[0] = Note(p[1], octave=default_octave) 135 p[0] = Note(p[1], octave=default_octave)
142 136
143 def p_rest(p): 137 def p_rest(p):
144 ''' rest : REST 138 ''' rest : REST
145 | REST NOTE_LENGTH | 139 | REST NOTE_LENGTH
146 ''' 140 '''
147 p[0] = Rest() 141 p[0] = Rest()
148 if len(p) > 2: 142 if len(p) > 2:
149 p[0].duration = p[2] 143 p[0].duration = p[2]
150 144
151 def p_error(p): 145 def p_error(p):
152 raise Exception("Syntax error at '%s' of element type %s" % (p.value, p. 146 raise Exception("Syntax error at '%s' of element type %s" % (p.value, p.
153 147
154 yacc.yacc() 148 yacc.yacc()
155 149
156 #print yacc.parse("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD") <
157 return yacc.parse(score) 150 return yacc.parse(score)