brevity 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.rdoc +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +27 -0
- data/Rakefile +67 -0
- data/bin/debrief +56 -0
- data/brevity.gemspec +28 -0
- data/examples/alley_cat.br +50 -0
- data/examples/hip.br +15 -0
- data/examples/missed_connection.br +6 -0
- data/examples/song1.br +11 -0
- data/examples/song2.br +10 -0
- data/examples/twinkle.br +18 -0
- data/lib/brevity/commands/constants.rb +18 -0
- data/lib/brevity/commands/expr.rb +17 -0
- data/lib/brevity/commands/meter.rb +20 -0
- data/lib/brevity/commands/part.rb +47 -0
- data/lib/brevity/commands/tempo.rb +13 -0
- data/lib/brevity/itemization.rb +73 -0
- data/lib/brevity/parsing/expression/dynamic.rb +280 -0
- data/lib/brevity/parsing/expression/dynamic.treetop +41 -0
- data/lib/brevity/parsing/expression/dynamic_nodes.rb +55 -0
- data/lib/brevity/parsing/expression/expression.rb +429 -0
- data/lib/brevity/parsing/expression/expression.treetop +39 -0
- data/lib/brevity/parsing/expression/expression_nodes.rb +26 -0
- data/lib/brevity/parsing/expression/gradual.rb +44 -0
- data/lib/brevity/parsing/expression/gradual.treetop +9 -0
- data/lib/brevity/parsing/expression/gradual_node.rb +11 -0
- data/lib/brevity/parsing/expression/label.rb +75 -0
- data/lib/brevity/parsing/expression/label.treetop +9 -0
- data/lib/brevity/parsing/expression/label_node.rb +15 -0
- data/lib/brevity/parsing/expression/sequence.rb +130 -0
- data/lib/brevity/parsing/expression/sequence.treetop +12 -0
- data/lib/brevity/parsing/expression/sequence_node.rb +14 -0
- data/lib/brevity/parsing/file/command.rb +216 -0
- data/lib/brevity/parsing/file/command.treetop +17 -0
- data/lib/brevity/parsing/file/command_node.rb +11 -0
- data/lib/brevity/parsing/file/comment.rb +178 -0
- data/lib/brevity/parsing/file/comment.treetop +21 -0
- data/lib/brevity/parsing/file/comment_node.rb +3 -0
- data/lib/brevity/parsing/file/file.rb +152 -0
- data/lib/brevity/parsing/file/file.treetop +16 -0
- data/lib/brevity/parsing/file/file_node.rb +7 -0
- data/lib/brevity/parsing/file/path.rb +235 -0
- data/lib/brevity/parsing/file/path.treetop +12 -0
- data/lib/brevity/parsing/modifiers/duplicate_modifier.rb +65 -0
- data/lib/brevity/parsing/modifiers/duplicate_modifier.treetop +11 -0
- data/lib/brevity/parsing/modifiers/duplicate_modifier_node.rb +8 -0
- data/lib/brevity/parsing/modifiers/modifier.rb +64 -0
- data/lib/brevity/parsing/modifiers/modifier.treetop +13 -0
- data/lib/brevity/parsing/modifiers/stretch_modifier.rb +69 -0
- data/lib/brevity/parsing/modifiers/stretch_modifier.treetop +11 -0
- data/lib/brevity/parsing/modifiers/stretch_modifier_node.rb +21 -0
- data/lib/brevity/parsing/modifiers/transpose_modifier.rb +69 -0
- data/lib/brevity/parsing/modifiers/transpose_modifier.treetop +11 -0
- data/lib/brevity/parsing/modifiers/transpose_modifier_node.rb +13 -0
- data/lib/brevity/parsing/note/accent.rb +44 -0
- data/lib/brevity/parsing/note/accent.treetop +9 -0
- data/lib/brevity/parsing/note/duration.rb +203 -0
- data/lib/brevity/parsing/note/duration.treetop +23 -0
- data/lib/brevity/parsing/note/duration_nodes.rb +19 -0
- data/lib/brevity/parsing/note/link.rb +69 -0
- data/lib/brevity/parsing/note/link.treetop +11 -0
- data/lib/brevity/parsing/note/link_node.rb +19 -0
- data/lib/brevity/parsing/note/note.rb +300 -0
- data/lib/brevity/parsing/note/note.treetop +30 -0
- data/lib/brevity/parsing/note/note_nodes.rb +77 -0
- data/lib/brevity/parsing/note/pitch.rb +81 -0
- data/lib/brevity/parsing/note/pitch.treetop +9 -0
- data/lib/brevity/parsing/note/pitch_node.rb +50 -0
- data/lib/brevity/parsing/numbers/nonnegative_integer.rb +53 -0
- data/lib/brevity/parsing/numbers/nonnegative_integer.treetop +9 -0
- data/lib/brevity/parsing/numbers/positive_integer.rb +91 -0
- data/lib/brevity/parsing/numbers/positive_integer.treetop +15 -0
- data/lib/brevity/read_file.rb +18 -0
- data/lib/brevity/score_maker.rb +64 -0
- data/lib/brevity/version.rb +4 -0
- data/lib/brevity.rb +53 -0
- data/manuals/brevity.pdf +0 -0
- data/manuals/brevity.tex +273 -0
- data/spec/brevity_spec.rb +8 -0
- data/spec/commands/expr_spec.rb +15 -0
- data/spec/commands/meter_spec.rb +21 -0
- data/spec/commands/part_spec.rb +16 -0
- data/spec/commands/tempo_spec.rb +20 -0
- data/spec/itemization_spec.rb +46 -0
- data/spec/parsing/expression/dynamic_nodes_spec.rb +32 -0
- data/spec/parsing/expression/dynamic_spec.rb +23 -0
- data/spec/parsing/expression/expression_nodes_spec.rb +87 -0
- data/spec/parsing/expression/expression_spec.rb +85 -0
- data/spec/parsing/expression/gradual_spec.rb +10 -0
- data/spec/parsing/expression/label_node_spec.rb +13 -0
- data/spec/parsing/expression/label_spec.rb +35 -0
- data/spec/parsing/file/command_node_spec.rb +29 -0
- data/spec/parsing/file/command_spec.rb +18 -0
- data/spec/parsing/file/comment_spec.rb +14 -0
- data/spec/parsing/file/file_node_spec.rb +19 -0
- data/spec/parsing/file/file_spec.rb +30 -0
- data/spec/parsing/modifiers/modifier_nodes_spec.rb +25 -0
- data/spec/parsing/modifiers/modifier_parsers_spec.rb +20 -0
- data/spec/parsing/note/accent_spec.rb +27 -0
- data/spec/parsing/note/duration_nodes_spec.rb +79 -0
- data/spec/parsing/note/duration_spec.rb +69 -0
- data/spec/parsing/note/link_node_spec.rb +30 -0
- data/spec/parsing/note/link_spec.rb +23 -0
- data/spec/parsing/note/note_nodes_spec.rb +82 -0
- data/spec/parsing/note/note_spec.rb +188 -0
- data/spec/parsing/note/pitch_node_spec.rb +48 -0
- data/spec/parsing/note/pitch_spec.rb +23 -0
- data/spec/parsing/numbers/nonnegative_integer_spec.rb +11 -0
- data/spec/parsing/numbers/positive_integer_spec.rb +17 -0
- data/spec/spec_helper.rb +112 -0
- metadata +293 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe RestNoteNode do
|
4
|
+
{
|
5
|
+
'/2' => Note.new(Rational(1,2)),
|
6
|
+
'4/2' => Note.new(Rational(4,2)),
|
7
|
+
'28' => Note.new(Rational(28,1)),
|
8
|
+
'56/33' => Note.new(Rational(56,33)),
|
9
|
+
}.each do |str,tgt|
|
10
|
+
res = NOTE_PARSER.parse(str)
|
11
|
+
context str do
|
12
|
+
it 'should parse as RestNoteNode' do
|
13
|
+
res.should be_a RestNoteNode
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#to_note' do
|
17
|
+
n = res.to_note
|
18
|
+
it 'should produce a Note' do
|
19
|
+
n.should be_a Note
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should produce value matching input str' do
|
23
|
+
n.should eq tgt
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe MonophonicNoteNode do
|
31
|
+
{
|
32
|
+
'/2C2=C2' => Note.new(Rational(1,2),[C2],links:{C2=>Link::Slur.new(C2)}),
|
33
|
+
'4/2D#6^' => Note.new(Rational(4,2),[Eb6],accent:Accent::Martellato.new),
|
34
|
+
'28Eb7>' => Note.new(Rational(28,1),[Eb7],accent:Accent::Marcato.new),
|
35
|
+
'56/33B1.' => Note.new(Rational(56,33),[B1],accent:Accent::Staccato.new),
|
36
|
+
}.each do |str,tgt|
|
37
|
+
res = NOTE_PARSER.parse(str)
|
38
|
+
context str do
|
39
|
+
it 'should parse as MonophonicNoteNode' do
|
40
|
+
res.should be_a MonophonicNoteNode
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#to_note' do
|
44
|
+
n = res.to_note
|
45
|
+
it 'should produce a Note' do
|
46
|
+
n.should be_a Note
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should produce value matching input str' do
|
50
|
+
n.should eq tgt
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe PolyphonicNoteNode do
|
58
|
+
{
|
59
|
+
'/2C2,D2,E2-F2' => Note.new(Rational(1,2),[C2,D2,E2],links:{E2=>Link::Legato.new(F2)}),
|
60
|
+
'4/2D#6,G4' => Note.new(Rational(4,2),[Eb6,G4]),
|
61
|
+
'28Eb7,D7,G7_' => Note.new(Rational(28,1),[Eb7,D7,G7],accent:Accent::Tenuto.new),
|
62
|
+
'56/33B1,B2,B3,B4,B5' => Note.new(Rational(56,33),[B1,B2,B3,B4,B5]),
|
63
|
+
}.each do |str,tgt|
|
64
|
+
res = NOTE_PARSER.parse(str)
|
65
|
+
context str do
|
66
|
+
it 'should parse as PolyphonicNoteNode' do
|
67
|
+
res.should be_a PolyphonicNoteNode
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#to_note' do
|
71
|
+
n = res.to_note
|
72
|
+
it 'should produce a Note' do
|
73
|
+
n.should be_a Note
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should produce value matching input str' do
|
77
|
+
n.should eq tgt
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe NoteParser do
|
4
|
+
before :all do
|
5
|
+
@parser = NoteParser.new
|
6
|
+
@valid = {
|
7
|
+
:numbers => [1,5,50,3999,01,0010,0000005050],
|
8
|
+
:links => ["=","-","~","/"],
|
9
|
+
:accents => [".","'",">","^","_",""],
|
10
|
+
:pitch_classes => ["A","B","C","D","E","F","G"],
|
11
|
+
:accidentals => ["\#","b",""],
|
12
|
+
:octaves => [0,1,2,3,4,5,6,7,8,9],
|
13
|
+
}
|
14
|
+
|
15
|
+
@invalid = {
|
16
|
+
:numbers => [0,00],
|
17
|
+
:links => ["{",";"],
|
18
|
+
:accents => ["*","&"],
|
19
|
+
:pitch_classes => ["H","Z"],
|
20
|
+
:accidentals => ["$"],
|
21
|
+
:octaves => [-1,10],
|
22
|
+
}
|
23
|
+
|
24
|
+
@valid[:pitches] = []
|
25
|
+
@valid[:pitch_classes].each do |pc|
|
26
|
+
@valid[:accidentals].each do |a|
|
27
|
+
@valid[:octaves].each do |o|
|
28
|
+
@valid[:pitches].push "#{pc}#{a}#{o}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@invalid[:pitches] = []
|
34
|
+
@invalid[:pitch_classes].each do |pc|
|
35
|
+
@valid[:accidentals].each do |a|
|
36
|
+
@valid[:octaves].each do |o|
|
37
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@valid[:pitch_classes].each do |pc|
|
42
|
+
@invalid[:accidentals].each do |a|
|
43
|
+
@valid[:octaves].each do |o|
|
44
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@valid[:pitch_classes].each do |pc|
|
49
|
+
@valid[:accidentals].each do |a|
|
50
|
+
@invalid[:octaves].each do |o|
|
51
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@invalid[:pitch_classes].each do |pc|
|
56
|
+
@invalid[:accidentals].each do |a|
|
57
|
+
@valid[:octaves].each do |o|
|
58
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@invalid[:pitch_classes].each do |pc|
|
63
|
+
@valid[:accidentals].each do |a|
|
64
|
+
@invalid[:octaves].each do |o|
|
65
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
@valid[:pitch_classes].each do |pc|
|
70
|
+
@invalid[:accidentals].each do |a|
|
71
|
+
@invalid[:octaves].each do |o|
|
72
|
+
@invalid[:pitches].push "#{pc}#{a}#{o}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
#puts @valid[:pitches]
|
77
|
+
end
|
78
|
+
|
79
|
+
context "note duration only" do
|
80
|
+
it 'should parse' do
|
81
|
+
@parser.parse("1/4").should_not be nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'duration and one pitch' do
|
86
|
+
context 'valid pitch' do
|
87
|
+
context 'without link marker' do
|
88
|
+
it 'should parse' do
|
89
|
+
@valid[:pitches].each do |pitch|
|
90
|
+
str = "1/4#{pitch}"
|
91
|
+
@parser.parse(str).should_not be nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'with link marker' do
|
97
|
+
context 'link marker is valid' do
|
98
|
+
it 'should parse' do
|
99
|
+
@valid[:pitches].each do |pitch|
|
100
|
+
@valid[:links].each do |link|
|
101
|
+
str = "1/4#{pitch}#{link}#{pitch}"
|
102
|
+
@parser.parse(str).should_not be nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'link marker is not valid' do
|
109
|
+
it 'should not parse' do
|
110
|
+
@valid[:pitches].each do |pitch|
|
111
|
+
@invalid[:links].each do |link|
|
112
|
+
str = "1/4#{pitch}#{link}#{pitch}"
|
113
|
+
@parser.parse(str).should be nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'invalid pitch' do
|
122
|
+
context 'without link marker' do
|
123
|
+
it 'should parse' do
|
124
|
+
@invalid[:pitches].each do |pitch|
|
125
|
+
str = "1/4#{pitch}"
|
126
|
+
@parser.parse(str).should be nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'with link marker' do
|
132
|
+
it 'should not parse' do
|
133
|
+
@invalid[:pitches].each do |pitch|
|
134
|
+
@valid[:links].each do |link|
|
135
|
+
str = "1/4#{pitch}#{link}#{pitch}"
|
136
|
+
@parser.parse(str).should be nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'duration and multiple pitches' do
|
145
|
+
context 'all valid pitches' do
|
146
|
+
context 'without links' do
|
147
|
+
it 'should parse' do
|
148
|
+
str = "4/" + @valid[:pitches].join(",")
|
149
|
+
@parser.parse(str).should_not be nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'with link marker' do
|
154
|
+
context 'link marker is valid' do
|
155
|
+
it 'should parse' do
|
156
|
+
@valid[:links].each do |link|
|
157
|
+
str = "4/" + @valid[:pitches].join("#{link}C4,")
|
158
|
+
@parser.parse(str).should_not be nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'link marker is not valid' do
|
164
|
+
it 'should not parse' do
|
165
|
+
@invalid[:links].each do |link|
|
166
|
+
str = "4/" + @valid[:pitches].join("#{link}C4,")
|
167
|
+
@parser.parse(str).should be nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'one invalid pitch' do
|
175
|
+
it 'should not parse' do
|
176
|
+
str = "4/" + ([@invalid[:pitches][0]] + @valid[:pitches]).join(",")
|
177
|
+
@parser.parse(str).should be nil
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context 'all invalid pitches' do
|
182
|
+
it 'should not parse' do
|
183
|
+
str = "4/" + @invalid[:pitches].join(",")
|
184
|
+
@parser.parse(str).should be nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe 'String#to_pitch' do
|
4
|
+
it 'should create a Pitch object that matches the musical note' do
|
5
|
+
{
|
6
|
+
"Ab2" => Pitch.new(octave: 2, semitone: 8),
|
7
|
+
"C0" => Pitch.new(octave: 0, semitone: 0),
|
8
|
+
"db4" => Pitch.new(octave: 4, semitone: 1),
|
9
|
+
"F#12" => Pitch.new(octave: 12, semitone: 6),
|
10
|
+
"E#7" => Pitch.new(octave: 7, semitone: 5),
|
11
|
+
"G9" => Pitch.new(octave: 9, semitone: 7),
|
12
|
+
"Bb10" => Pitch.new(octave: 10, semitone: 10),
|
13
|
+
}.each do |str, expected_pitch|
|
14
|
+
str.to_pitch.should eq(expected_pitch)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe PitchNode do
|
20
|
+
parser = PitchParser.new
|
21
|
+
|
22
|
+
{
|
23
|
+
'C4' => C4,
|
24
|
+
'Db2' => Db2,
|
25
|
+
'C#2' => Db2,
|
26
|
+
'Db2' => Db2,
|
27
|
+
'F7' => F7,
|
28
|
+
'B1' => B1,
|
29
|
+
}.each do |str,tgt|
|
30
|
+
res = parser.parse(str)
|
31
|
+
context str do
|
32
|
+
it 'should parse as PitchNode' do
|
33
|
+
res.should be_a PitchNode
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#to_pitch' do
|
37
|
+
p = res.to_pitch
|
38
|
+
it 'should produce a Pitch object' do
|
39
|
+
p.should be_a Pitch
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should produce pitch matching input str' do
|
43
|
+
p.should eq tgt
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe PitchParser do
|
4
|
+
before :all do
|
5
|
+
@parser = PitchParser.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should parse "C4"' do
|
9
|
+
@parser.parse("C4").should_not be nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should parse "C#9"' do
|
13
|
+
@parser.parse("C#9").should_not be nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should parse "Ab0"' do
|
17
|
+
@parser.parse("Ab0").should_not be nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should parse "G#2"' do
|
21
|
+
@parser.parse("G#2").should_not be nil
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe NonnegativeIntegerParser do
|
4
|
+
parser = NonnegativeIntegerParser.new
|
5
|
+
|
6
|
+
["1","50","05","502530","0"].each do |str|
|
7
|
+
it "should parse '#{str}'" do
|
8
|
+
parser.parse(str).should_not be nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe PositiveIntegerParser do
|
4
|
+
parser = PositiveIntegerParser.new
|
5
|
+
|
6
|
+
["1","50","05","502530"].each do |str|
|
7
|
+
it "should parse '#{str}'" do
|
8
|
+
parser.parse(str).should_not be nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
["0"].each do |str|
|
13
|
+
it "should not parse '#{str}'" do
|
14
|
+
parser.parse(str).should be nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'brevity'
|
3
|
+
|
4
|
+
include Brevity
|
5
|
+
include Music::Transcription
|
6
|
+
include Pitches
|
7
|
+
|
8
|
+
RSpec::Matchers.define :parse do |str|
|
9
|
+
match do |parser|
|
10
|
+
!parser.parse(str).nil?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec::Matchers.define :parse_as do |str,nodeclass|
|
15
|
+
match do |parser|
|
16
|
+
parser.parse(str).is_a?(nodeclass)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
LABELS = ["riff","GUITAR2","_my_part_"]
|
21
|
+
NOTES = {
|
22
|
+
'/2A7' => Note::Half.new([A7]),
|
23
|
+
'/4A3.' => Note::Quarter.new([A3],accent: Accent::Staccato.new),
|
24
|
+
'/2Bb2' => Note::Half.new([Bb2]),
|
25
|
+
'/2G2,C2-Eb3' => Note::Half.new([G2,C2],links: {C2=>Link::Legato.new(Eb3)}),
|
26
|
+
'1Eb3' => Note::Whole.new([Eb3]),
|
27
|
+
}
|
28
|
+
sequences = {}
|
29
|
+
[2,3].each do |n|
|
30
|
+
NOTES.entries.permutation(n).each do |perm|
|
31
|
+
strs, notes = perm.transpose
|
32
|
+
sequences[strs.join(" ")] = notes
|
33
|
+
end
|
34
|
+
end
|
35
|
+
SEQUENCES = sequences
|
36
|
+
|
37
|
+
MODIFIERS = {
|
38
|
+
:duplicate => {
|
39
|
+
':1' => lambda {|primitives| primitives.clone },
|
40
|
+
':2' => lambda {|primitives| primitives.clone + primitives.clone },
|
41
|
+
':3' => lambda {|primitives| primitives.clone + primitives.clone + primitives.clone }
|
42
|
+
},
|
43
|
+
:stretch => {
|
44
|
+
'*1' => lambda {|primitives| primitives.clone },
|
45
|
+
'*3/2' => lambda do |primitives|
|
46
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch('3/2'.to_r) : p }
|
47
|
+
end,
|
48
|
+
'*/4' => lambda do |primitives|
|
49
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch('1/4'.to_r) : p }
|
50
|
+
end,
|
51
|
+
'=1' => lambda do |primitives|
|
52
|
+
duration = primitives.map do |p|
|
53
|
+
p.respond_to?(:duration) ? p.duration : 0
|
54
|
+
end.inject(0,:+)
|
55
|
+
ratio = 1 / duration
|
56
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch(ratio) : p }
|
57
|
+
end,
|
58
|
+
'=/2' => lambda do |primitives|
|
59
|
+
duration = primitives.map do |p|
|
60
|
+
p.respond_to?(:duration) ? p.duration : 0
|
61
|
+
end.inject(0,:+)
|
62
|
+
ratio = Rational(1,2) / duration
|
63
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch(ratio) : p }
|
64
|
+
end,
|
65
|
+
'=2/3' => lambda do |primitives|
|
66
|
+
duration = primitives.map do |p|
|
67
|
+
p.respond_to?(:duration) ? p.duration : 0
|
68
|
+
end.inject(0,:+)
|
69
|
+
ratio = Rational(2,3) / duration
|
70
|
+
primitives.map {|p| p.respond_to?(:stretch) ? p.stretch(ratio) : p }
|
71
|
+
end,
|
72
|
+
},
|
73
|
+
:transpose => {
|
74
|
+
'+0' => lambda {|primitives| primitives.clone },
|
75
|
+
'-0' => lambda {|primitives| primitives.clone },
|
76
|
+
'+4' => lambda do |primitives|
|
77
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(4) : p }
|
78
|
+
end,
|
79
|
+
'-4' => lambda do |primitives|
|
80
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(-4) : p }
|
81
|
+
end,
|
82
|
+
'+10' => lambda do |primitives|
|
83
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(10) : p }
|
84
|
+
end,
|
85
|
+
'-99' => lambda do |primitives|
|
86
|
+
primitives.map {|p| p.respond_to?(:transpose) ? p.transpose(-99) : p }
|
87
|
+
end
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
EXPR_PARSER = ExpressionParser.new
|
92
|
+
DUR_PARSER = DurationParser.new
|
93
|
+
NOTE_PARSER = NoteParser.new
|
94
|
+
LABEL_PARSER = LabelParser.new
|
95
|
+
COMMENT_PARSER = CommentParser.new
|
96
|
+
COMMAND_PARSER = CommandParser.new
|
97
|
+
FILE_PARSER = FileParser.new
|
98
|
+
|
99
|
+
class CommandTester
|
100
|
+
include Commands
|
101
|
+
|
102
|
+
attr_reader :env
|
103
|
+
def initialize
|
104
|
+
@env = {}
|
105
|
+
@env[ENV_START_TEMPO] = nil
|
106
|
+
@env[ENV_START_METER] = nil
|
107
|
+
@env[ENV_TEMPO_CHANGES] = {}
|
108
|
+
@env[ENV_METER_CHANGES] = {}
|
109
|
+
@env[ENV_EXPRS] = {}
|
110
|
+
@env[ENV_PARTS] = {}
|
111
|
+
end
|
112
|
+
end
|