spiffyscore

Diff
Login

Differences From Artifact [3ec57c3fbe]:

To Artifact [2afbfc4534]:


1


2
3
4
5

6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45


46
47
48
49
50
51

52
53
54
55
56
57
58
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

+
+



-
+








-
+








-
+
















+




-
-
+
+






+







#!/usr/bin/env python

import tree

from ply import lex, yacc
class Note():
    def __init__(self, value, duration=.25, octave=8):
    def __init__(self, value, duration=1, octave=8):
        self.value = value
        self.duration = duration
        self.octave = octave
        self.accidental = None
    def __repr__(self):
        return "Note %s %s %s" % (self.value, self.duration, self.octave)

class Chord():
    def __init__(self, value, duration=.5, chord_type="major", octave=5):
    def __init__(self, value, duration=1, chord_type="major", octave=5):
        self.value = value
        self.duration = duration
        self.chord_type = chord_type
        self.octave = octave
    def __repr__(self):
        return "Chord %s %s %s" % (self.value, self.duration, self.chord_type, self.octave)

class Rest():
    def __init__(self, duration=.25):
    def __init__(self, duration=1):
        self.duration = duration
    def __repr__(self):
        return "Rest node %s" % self.duration


def parse(score, default_octave=8):
    # Tokenize (lex)
    tokens = (
        "NOTE_LENGTH",
        "BASENOTE",
        "ACCIDENTAL",
        "REST",
        "OCTAVE",
        "CHORD_TYPE",
        "PAREN",
        "SYNCOPATE",
        "NODE",
    )

    t_ignore = " |"

    #t_BASENOTE = r"[A-Ga-g]"
    t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
    t_BASENOTE = r"[A-Ga-g]"
#    t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
    t_ACCIDENTAL = r"\^{1,2}|_{1,2}|="
    t_REST = r"z"
    t_OCTAVE = r"'+|,+"
    t_CHORD_TYPE = r"m|7|m7|0|o|\+|mb5|sus|sus4|maj7|mmaj7|7sus4|dim|dim7|7b5|m7b5|6|b6|m6|mb6|46|maj9|9|add9|7b9|m9"
    t_PAREN = "\(|\)"
    t_SYNCOPATE = "\+|-"
    t_NODE = r"\([a-zA-Z0-9_-]+\)"

    def t_NOTE_LENGTH(t):
        r"/?\d+"
        multiplier = float(t.value.strip("/"))
        if t.value.startswith("/"):
            multiplier = 1/multiplier
        t.value = multiplier
67
68
69
70
71
72
73

74
75
76
77
78
79
80

81
82
83
84
85
86
87
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93







+







+








    # Parse (yacc)

    def p_note_list(p):
        '''score : score note
                 | score chord
                 | score rest
            | score node
        '''
        p[0] = p[1] + [p[2]]

    def p_score(p):
        '''score : note
                 | chord
                 | rest
            | node
        '''
        p[0] = [p[1]]


    def p_chord_length(p):
        ''' chord : chord NOTE_LENGTH
        '''
137
138
139
140
141
142
143
144






145

146
147
148
149
150
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163








+
+
+
+
+
+

+





    def p_rest(p):
        ''' rest : REST
                 | REST NOTE_LENGTH
        '''
        p[0] = Rest()
        if len(p) > 2:
            p[0].duration = p[2]

    def p_node(p):
        '''node : NODE
        '''
        p[0] = tree.Tree(p[1].strip("(").strip(")"))


    def p_error(p):
        print p
        raise Exception("Syntax error at '%s' of element type %s" % (p.value, p.type))
        
    yacc.yacc()

    return yacc.parse(score)