Differences From Artifact [17628fda61371dc5]:
- Executable file
parse.py
- 2010-11-13 08:28:35 - part of checkin [ff84293301] on branch ply - Added basic ABC tokenizing via the PLY module (user: spiffytech@gmail.com) [annotate]
To Artifact [b5bfbaf68dca2f5d]:
- Executable file
parse.py
- 2010-11-16 08:29:29 - part of checkin [bd456efa03] on branch ply - Now parses notes, accidentals, and octaves (user: spiffytech@gmail.com) [annotate]
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 from ply import lex, yacc 3 from ply import lex, yacc
4 4
> 5 # Tokenize (lex)
5 tokens = ( 6 tokens = (
> 7 "NOTE_LENGTH",
6 "NOTE", | 8 "BASENOTE",
> 9 "ACCIDENTAL",
7 "REST", 10 "REST",
8 "SHARP", <
9 "FLAT", <
10 "OCTAVE", 11 "OCTAVE",
11 "NATURAL", <
12 "LENGTH", | 12 "CHORD_TYPE",
13 ) 13 )
14 14
15 t_NOTE = r"[A-Ga-g]" | 15 t_BASENOTE = r"[A-Ga-g]"
> 16 t_ACCIDENTAL = r"\^{1,2}|_{1,2}|="
16 t_REST = r"z" 17 t_REST = r"z"
17 t_SHARP = r"\^" <
18 t_FLAT = r"_" <
19 t_NATURAL = r"=" <
20 t_OCTAVE = r"'+|,+" 18 t_OCTAVE = r"'+|,+"
> 19 t_CHORD_TYPE = r"m|7|m7|0|o|\+|mb5|sus|sus4|maj7|mmaj7|7sus4|dim|dim7|7b5|m7b5|6
21 20
22 def t_LENGTH(t): | 21 def t_NOTE_LENGTH(t):
23 r"/?\d+" 22 r"/?\d+"
24 multiplier = float(t.value.strip("/")) 23 multiplier = float(t.value.strip("/"))
25 if t.value.startswith("/"): 24 if t.value.startswith("/"):
26 multiplier = 1/multiplier 25 multiplier = 1/multiplier
27 t.value = multiplier 26 t.value = multiplier
28 return t 27 return t
29 28
................................................................................................................................................................................
30 def t_error(t): 29 def t_error(t):
31 raise TypeError("Unknown text '%s'" % (t.value,)) 30 raise TypeError("Unknown text '%s'" % (t.value,))
32 31
33 t_ignore = " |" 32 t_ignore = " |"
34 33
35 lex.lex() 34 lex.lex()
36 35
37 lex.input("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD") | 36 #lex.input("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
> 37 #s = "GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD"
> 38 s = "GF_G,"
> 39 lex.input(s)
38 for tok in iter(lex.token, None): 40 for tok in iter(lex.token, None):
39 print repr(tok.type), repr(tok.value) 41 print repr(tok.type), repr(tok.value)
> 42
> 43
> 44 # Parse (yacc)
> 45
> 46 class Note(object):
> 47 def __init__(self, value, duration=.25, octave=8):
> 48 self.value = value
> 49 self.duration = duration
> 50 self.octave = octave
> 51 def __repr__(self):
> 52 return "Note %s %s %s" % (self.value, self.duration, self.octave)
> 53
> 54 #def p_element(p):
> 55 # "element : note_element"
> 56 # p[0] = p[1]
> 57 #
> 58 #def p_note_element(p):
> 59 # '''note_element : note_element note_stem
> 60 # | note_stem
> 61 # '''
> 62 # p[0] = p[1]
> 63 #
> 64 #def p_note_stem(p):
> 65 # '''note_stem : note'''
> 66 # p[0] = p[1]
> 67 #
> 68 #def p_note(p):
> 69 # '''note : note_or_rest
> 70 # | note_or_rest NOTE_LENGTH
> 71 # '''
> 72 # p[0] = p[1]
> 73 #
> 74 #def p_note_or_rest(p):
> 75 # '''note_or_rest : pitch
> 76 # | REST
> 77 # '''
> 78 # p[0] = p[1]
> 79 #
> 80 #def p_pitch(p):
> 81
> 82 def p_pitch_list(p):
> 83 '''score : score pitch
> 84 '''
> 85 p[0] = p[1] + [p[2]]
> 86
> 87 def p_sore(p):
> 88 '''score : pitch
> 89 '''
> 90 p[0] = [p[1]]
> 91
> 92
> 93 def p_pitch_more(p):
> 94 ''' score : pitch NOTE_LENGTH
> 95 '''
> 96 print "stuff"
> 97 new_note = p[1]
> 98 new_note.duration = p[2]
> 99 p[0] = new_note
> 100
> 101 def p_pitch(p):
> 102 '''pitch : BASENOTE
> 103 '''
> 104 p[0] = Note(p[1])
> 105
> 106 def p_accidental(p):
> 107 '''pitch : ACCIDENTAL pitch
> 108 '''
> 109 p[2].accidental = p[1]
> 110 p[0] = p[2]
> 111
> 112 def p_octave(p):
> 113 '''pitch : pitch OCTAVE
> 114 '''
> 115 count = len(p[2])
> 116 increment_or_decrement = 1 if p[2][0] == "," else -1
> 117 octave = 8 + (count * increment_or_decrement)
> 118 p[1].octave = octave
> 119 p[0] = p[1]
> 120
> 121 def p_error(p):
> 122 print "Syntax error at '%s' of element type %s" % (p.value, p.type)
> 123
> 124 yacc.yacc()
> 125
> 126 #print yacc.parse("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
> 127 print yacc.parse(s)