spiffyscore

Diff
Login

Differences From Artifact [4cca2f3d0c]:

To Artifact [0884d30f89]:


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
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







+
-
-
+
+
+
+





-
-
+
+

-
-

-
+

















-
+












-
+







#!/usr/bin/env python

import tree

from ply import lex, yacc
class Note():
    def __init__(self, value, duration=1, octave=8):
        self.duration = duration
        self.value = value
        self.duration = duration
        if value > 12:
            self.duration += 1
            value = value % 12
        self.value = value
        self.octave = octave
    def __repr__(self):
        return "Note %s %s %s" % (self.value, self.duration, self.octave)

class Chord():
    def __init__(self, value, duration=1, chord_type="major", octave=5):
        self.value = value
    def __init__(self, notes, duration=1):
        self.notes = notes
        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)
        return "Chord %s" % (self.notes)

class Rest():
    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",
        "BRACKET",
        "SYNCOPATE",
        "NODE",
    )

    t_ignore = " |"

    t_BASENOTE = r"[A-Ga-g]"
#    t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
    t_ACCIDENTAL = r"\^{1}|_{1}|="
    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_BRACKET = r"\[|\]"
    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("/"):
100
101
102
103
104
105
106
107
108


109
110
111
112
113
114







115
116
117
118
119
120
121
101
102
103
104
105
106
107


108
109
110





111
112
113
114
115
116
117
118
119
120
121
122
123
124







-
-
+
+

-
-
-
-
-
+
+
+
+
+
+
+







        '''
        new_note = p[1]
        new_note.duration = p[2]
        p[0] = new_note


    def p_chord(p):
        '''chord : PAREN note PAREN
                 | PAREN note CHORD_TYPE PAREN
        '''chord : BRACKET note BRACKET
                 | BRACKET note CHORD_TYPE BRACKET
        '''
        pitch = p[2].value
        pitch = pitch.upper()
        p[0] = Chord(value=pitch, octave=default_octave)
        if len(p) > 3:
            p[0].chord_type = p[3]
        root_note = p[2].value
        chorded_notes = []

        for offset in [0, 4, 7]:
            chorded_notes.append(Note(root_note+offset, octave=p[2].octave))

        p[0] = Chord(notes=chorded_notes)


    def p_note_syncopate(p):
        ''' note : note SYNCOPATE
        '''
        note.syncopate = p[2]