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,87 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe ExpressionNode do
|
|
4
|
+
describe '#primitives' do
|
|
5
|
+
context 'simple sequence' do
|
|
6
|
+
it 'should be converted to array of notes' do
|
|
7
|
+
str = SEQUENCES.keys.last
|
|
8
|
+
node = EXPR_PARSER.parse(str)
|
|
9
|
+
|
|
10
|
+
tgt = SEQUENCES[str]
|
|
11
|
+
node.primitives({}).should eq tgt
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'composed sequences' do
|
|
16
|
+
it 'should combine them into a single array' do
|
|
17
|
+
strA, strB = SEQUENCES.keys[-2..-1]
|
|
18
|
+
tgt = SEQUENCES[strA].clone + SEQUENCES[strB].clone
|
|
19
|
+
str = strA + " (#{strB})"
|
|
20
|
+
EXPR_PARSER.parse(str).primitives({}).should eq tgt
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'chained modifications' do
|
|
25
|
+
it 'should produce a single part, applying all modifications in sequence' do
|
|
26
|
+
str = SEQUENCES.keys.last
|
|
27
|
+
notes = SEQUENCES[str]
|
|
28
|
+
str = "(#{str})"
|
|
29
|
+
MODIFIERS.each do |modtype,modcases|
|
|
30
|
+
modstrs, modlambdas = modcases.entries.transpose
|
|
31
|
+
modstr = modstrs.join
|
|
32
|
+
tgt = notes.clone
|
|
33
|
+
modlambdas.each {|l| tgt = l.call(tgt) }
|
|
34
|
+
node = EXPR_PARSER.parse(str + modstr)
|
|
35
|
+
node.primitives({}).should eq(tgt)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'with dynamic changes' do
|
|
41
|
+
it 'should convert dynamic changes to dynamic values and gradual nodes' do
|
|
42
|
+
{
|
|
43
|
+
"mp /2 > /2A2 f < /4C4 mp" => [
|
|
44
|
+
Dynamics::MP, Note::Half.new, GradualParser.new.parse(">"),
|
|
45
|
+
Note::Half.new([A2]), Dynamics::F, GradualParser.new.parse("<"),
|
|
46
|
+
Note::Quarter.new([C4]), Dynamics::MP
|
|
47
|
+
]
|
|
48
|
+
}.each do |str,tgt|
|
|
49
|
+
node = EXPR_PARSER.parse(str)
|
|
50
|
+
primitives = node.primitives({})
|
|
51
|
+
primitives.should eq tgt
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe GroupNode do
|
|
59
|
+
describe '#primitives' do
|
|
60
|
+
it 'should produce same array as the string that is in parenthesis' do
|
|
61
|
+
SEQUENCES.each do |str,tgt|
|
|
62
|
+
node = EXPR_PARSER.parse(str)
|
|
63
|
+
node2 = EXPR_PARSER.parse("(#{str})")
|
|
64
|
+
node.primitives({}).should eq(node2.primitives({}))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe ModifiableNode do
|
|
71
|
+
describe '#primitives' do
|
|
72
|
+
it 'should produce a modified array' do
|
|
73
|
+
SEQUENCES.each do |seqstr,tgt|
|
|
74
|
+
MODIFIERS.each do |modtype,modcases|
|
|
75
|
+
modcases.each do |modstr,modlambda|
|
|
76
|
+
str = "(#{seqstr})#{modstr}"
|
|
77
|
+
tgtmod = modlambda.call(tgt)
|
|
78
|
+
|
|
79
|
+
node = EXPR_PARSER.parse str
|
|
80
|
+
res = node.primitives({})
|
|
81
|
+
res.should eq tgtmod
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe ExpressionParser do
|
|
4
|
+
context 'single note' do
|
|
5
|
+
it 'should parse as ExpressionNode' do
|
|
6
|
+
NOTES.keys.each {|str| EXPR_PARSER.should parse_as(str,ExpressionNode) }
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context 'note sequence only' do
|
|
11
|
+
it 'should parse as ExpressionNode' do
|
|
12
|
+
SEQUENCES.keys.each {|str| EXPR_PARSER.should parse_as(str,ExpressionNode) }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context 'grouped note sequence' do
|
|
17
|
+
it 'should parse as ExpressionNode' do
|
|
18
|
+
SEQUENCES.keys.each {|str| EXPR_PARSER.should parse_as("(#{str})",ExpressionNode) }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context 'composed sequences' do
|
|
23
|
+
it 'should parse as ExpressionNode' do
|
|
24
|
+
strs = SEQUENCES.keys[0..2]
|
|
25
|
+
str = "#{strs[0]} (#{strs[1]}) #{strs[2]}"
|
|
26
|
+
EXPR_PARSER.should parse_as(str,ExpressionNode)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'modified sequence' do
|
|
31
|
+
context 'labeled sequence' do
|
|
32
|
+
it 'should parse as ExpressionNode' do
|
|
33
|
+
MODIFIERS.each do |modtype,cases|
|
|
34
|
+
cases.keys.each do |modstr,modlambda|
|
|
35
|
+
str = "#{LABELS[0]}#{modstr}"
|
|
36
|
+
EXPR_PARSER.should parse_as(str,ExpressionNode)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'grouped sequence' do
|
|
43
|
+
it 'should parse as ExpressionNode' do
|
|
44
|
+
MODIFIERS.each do |modtype,cases|
|
|
45
|
+
cases.keys.each do |modstr,modlambda|
|
|
46
|
+
str = "(#{SEQUENCES.keys.last})#{modstr}"
|
|
47
|
+
EXPR_PARSER.should parse_as(str,ExpressionNode)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'single note' do
|
|
54
|
+
it 'should parse as ExpressionNode' do
|
|
55
|
+
MODIFIERS.each do |modtype,cases|
|
|
56
|
+
cases.keys.each do |modstr,modlambda|
|
|
57
|
+
str = "#{NOTES.keys[0]}#{modstr}"
|
|
58
|
+
EXPR_PARSER.should parse_as(str,ExpressionNode)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context 'chained modification' do
|
|
66
|
+
it 'should parse as ExpressionNode' do
|
|
67
|
+
str = "(#{SEQUENCES.keys.last}):1+2-2=/2*3/2"
|
|
68
|
+
EXPR_PARSER.should parse_as(str,ExpressionNode)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'with dynamic changes' do
|
|
73
|
+
it 'should parse as ExpressionNode' do
|
|
74
|
+
str = "mp /2 > /2A2 f < /4C4 mp"
|
|
75
|
+
EXPR_PARSER.should parse_as(str,ExpressionNode)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context 'separated by spaces, tabs, carriage returns, and newlines' do
|
|
80
|
+
it 'should parse as ExpressionNode' do
|
|
81
|
+
str = "(mp /2 ppp \n /2) /4 /4 \r\n /4"
|
|
82
|
+
EXPR_PARSER.should parse_as(str,ExpressionNode)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe GradualParser do
|
|
4
|
+
context '> or <' do
|
|
5
|
+
it 'should parse as GradualNode' do
|
|
6
|
+
GradualParser.new.should parse_as('>',GradualNode)
|
|
7
|
+
GradualParser.new.should parse_as('<',GradualNode)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe LabelNode do
|
|
4
|
+
describe '#primitives' do
|
|
5
|
+
it 'should fetch whatever is in given Hash' do
|
|
6
|
+
LABELS.each do |str|
|
|
7
|
+
node = LABEL_PARSER.parse(str)
|
|
8
|
+
tgt = [Note::Quarter.new]
|
|
9
|
+
node.primitives({ node.to_key => tgt }).should eq tgt
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe LabelParser do
|
|
4
|
+
context 'alphabetic only' do
|
|
5
|
+
it 'should parse' do
|
|
6
|
+
["abc","HiThere","Yeah","oKAY"].each do |str|
|
|
7
|
+
LABEL_PARSER.parse(str).should_not be nil
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context 'alphabetic plus numbers (after first char)' do
|
|
13
|
+
it 'should parse' do
|
|
14
|
+
["abc123","HiThere1","C00kieCrisp"].each do |str|
|
|
15
|
+
LABEL_PARSER.parse(str).should_not be nil
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'alphabetic with underscores' do
|
|
21
|
+
it 'should parse' do
|
|
22
|
+
["_okaydokee","looks_good","Hey_There555"].each do |str|
|
|
23
|
+
LABEL_PARSER.parse(str).should_not be nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'non-alphabetic chars' do
|
|
29
|
+
it 'should not parse' do
|
|
30
|
+
["Hey there","what?","yeah."].each do |str|
|
|
31
|
+
LABEL_PARSER.parse(str).should be nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe CommandNode do
|
|
4
|
+
describe '#name' do
|
|
5
|
+
it 'should return the given command name' do
|
|
6
|
+
{
|
|
7
|
+
'\bake' => 'bake',
|
|
8
|
+
'\once{}' => 'once',
|
|
9
|
+
'\dosomething{123}{456}' => 'dosomething'
|
|
10
|
+
}.each do |str,tgt|
|
|
11
|
+
node = COMMAND_PARSER.parse(str)
|
|
12
|
+
node.name.should eq tgt
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe '#args' do
|
|
18
|
+
it 'should return the strings in braces' do
|
|
19
|
+
{
|
|
20
|
+
'\bake' => [],
|
|
21
|
+
'\once{}' => [''],
|
|
22
|
+
'\dosomething{123}{456}' => ['123','456']
|
|
23
|
+
}.each do |str,tgt|
|
|
24
|
+
node = COMMAND_PARSER.parse(str)
|
|
25
|
+
node.args.should eq tgt
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe CommandParser do
|
|
4
|
+
describe '#parse' do
|
|
5
|
+
before :all do
|
|
6
|
+
@parser = CommandParser.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should parse as a CommandNode' do
|
|
10
|
+
[ '\bake','\baketwo{}{}','\sandwich{Ham}{Cheese}',
|
|
11
|
+
'\icecream{Vanilla}{Chocolate Syrup}{sprinkles}',
|
|
12
|
+
'\gobbledegook{akw4hf&Q(#^$hlka}{::".[p,!!!}'
|
|
13
|
+
].each do |str|
|
|
14
|
+
@parser.should parse_as(str,CommandNode)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe CommentParser do
|
|
4
|
+
context 'string starts with #' do
|
|
5
|
+
it 'should parse' do
|
|
6
|
+
[ "#",
|
|
7
|
+
"# Hello world",
|
|
8
|
+
"# This can be anything at all :)"
|
|
9
|
+
].each do |str|
|
|
10
|
+
COMMENT_PARSER.should parse(str)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe FileNode do
|
|
4
|
+
describe '#command_nodes' do
|
|
5
|
+
it 'should return the given command nodes' do
|
|
6
|
+
cmd_strs = ['\bake','\once{}','\dosomething{123}{456}',"\\seq{abc}{\2 \2 \1C2\n \2 \2}"]
|
|
7
|
+
cmds = cmd_strs.map{ |str| COMMAND_PARSER.parse(str) }
|
|
8
|
+
[" ","\n"].each do |sep|
|
|
9
|
+
str = cmd_strs.join(sep)
|
|
10
|
+
node = FILE_PARSER.parse(str)
|
|
11
|
+
command_nodes = node.command_nodes
|
|
12
|
+
command_nodes.each_index do |i|
|
|
13
|
+
command_nodes[i].name.should eq cmds[i].name
|
|
14
|
+
command_nodes[i].args.should eq cmds[i].args
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe FileParser do
|
|
4
|
+
{
|
|
5
|
+
'commands spanning multiple lines' => (
|
|
6
|
+
"\t \\seq{ABC}{\n" +
|
|
7
|
+
"\t /2 /2 /4C2 /4C2 /2\n" +
|
|
8
|
+
"\t /2 /2:2 (/4 /4C4):2\n" +
|
|
9
|
+
"\t }\n" +
|
|
10
|
+
"\t \\seq{DEF}{\n" +
|
|
11
|
+
"\t /4 /4 mylabel}\n" +
|
|
12
|
+
"\n"),
|
|
13
|
+
'commands on same line' => (
|
|
14
|
+
"\\seq{ABC}{ /2 /4C2 }\\seq{DEF}{ /4C2 /4C2}\\starttempo{120}"
|
|
15
|
+
),
|
|
16
|
+
'expressions, commands, and comments' => (
|
|
17
|
+
"# This is a comment, everything after is fine!!!\n" +
|
|
18
|
+
"\\seq{ABC}{ /2 /4C2} \\seq{DEF}{ /4C2 /4C2}\n" +
|
|
19
|
+
"# Another comment here\n" +
|
|
20
|
+
"\\starttempo{120}\n" +
|
|
21
|
+
"# Annnnd, the last word.\n"
|
|
22
|
+
)
|
|
23
|
+
}.each do |context_str,str|
|
|
24
|
+
context context_str do
|
|
25
|
+
it 'should parse as FileNode' do
|
|
26
|
+
FILE_PARSER.should parse_as(str,FileNode)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
{ :duplicate => [DuplicateModifierParser.new,DuplicateModifierNode],
|
|
4
|
+
:transpose => [TransposeModifierParser.new,TransposeModifierNode],
|
|
5
|
+
:stretch => [StretchModifierParser.new,StretchModifierNode],
|
|
6
|
+
}.each do |modtype,classes|
|
|
7
|
+
modparser, nodeclass = classes
|
|
8
|
+
|
|
9
|
+
describe nodeclass do
|
|
10
|
+
describe '#process' do
|
|
11
|
+
it 'should produce a modified array, according to str' do
|
|
12
|
+
SEQUENCES.each do |seqstr,src|
|
|
13
|
+
MODIFIERS[modtype].each do |modstr,modlambda|
|
|
14
|
+
tgt = modlambda.call(src)
|
|
15
|
+
|
|
16
|
+
modnode = modparser.parse(modstr)
|
|
17
|
+
res = modnode.process src
|
|
18
|
+
res.should be_a Array
|
|
19
|
+
res.should eq tgt
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
{ :duplicate => [DuplicateModifierParser,DuplicateModifierNode],
|
|
4
|
+
:transpose => [TransposeModifierParser,TransposeModifierNode],
|
|
5
|
+
:stretch => [StretchModifierParser,StretchModifierNode],
|
|
6
|
+
}.each do |modtype,classes|
|
|
7
|
+
modparser, nodeclass = classes
|
|
8
|
+
|
|
9
|
+
describe modparser do
|
|
10
|
+
before :all do
|
|
11
|
+
@parser = modparser.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should parse as #{nodeclass}" do
|
|
15
|
+
MODIFIERS[modtype].keys.each do |str|
|
|
16
|
+
@parser.should parse_as(str,nodeclass)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe AccentParser do
|
|
4
|
+
before :all do
|
|
5
|
+
@parser = AccentParser.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it 'should parse a "."' do
|
|
9
|
+
@parser.parse(".").should_not be nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should parse a \"'\"" do
|
|
13
|
+
@parser.parse("'").should_not be nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should parse a ">"' do
|
|
17
|
+
@parser.parse(">").should_not be nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should parse a "^"' do
|
|
21
|
+
@parser.parse("^").should_not be nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'should parse a "_"' do
|
|
25
|
+
@parser.parse("_").should_not be nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe NumDenNode do
|
|
4
|
+
{
|
|
5
|
+
'1/2' => Rational(1,2),
|
|
6
|
+
'5/100' => Rational(5,100),
|
|
7
|
+
'007/777' => Rational(7,777)
|
|
8
|
+
}.each do |str,tgt|
|
|
9
|
+
res = DUR_PARSER.parse(str)
|
|
10
|
+
context str do
|
|
11
|
+
it 'should parse as NumDenNode' do
|
|
12
|
+
res.should be_a NumDenNode
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '#to_r' do
|
|
16
|
+
r = res.to_r
|
|
17
|
+
it 'should produce a Rational' do
|
|
18
|
+
r.should be_a Rational
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'should produce value matching input str' do
|
|
22
|
+
r.should eq tgt
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe NumOnlyNode do
|
|
30
|
+
{
|
|
31
|
+
'1/' => Rational(1,1),
|
|
32
|
+
'5' => Rational(5,1),
|
|
33
|
+
'007/' => Rational(7,1)
|
|
34
|
+
}.each do |str,tgt|
|
|
35
|
+
res = DUR_PARSER.parse(str)
|
|
36
|
+
context str do
|
|
37
|
+
it 'should parse as NumOnlyNode' do
|
|
38
|
+
res.should be_a NumOnlyNode
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '#to_r' do
|
|
42
|
+
r = res.to_r
|
|
43
|
+
it 'should produce a Rational' do
|
|
44
|
+
r.should be_a Rational
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'should produce value matching input str' do
|
|
48
|
+
r.should eq tgt
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe DenOnlyNode do
|
|
56
|
+
{
|
|
57
|
+
'/2' => Rational(1,2),
|
|
58
|
+
'/100' => Rational(1,100),
|
|
59
|
+
'/777' => Rational(1,777)
|
|
60
|
+
}.each do |str,tgt|
|
|
61
|
+
res = DUR_PARSER.parse(str)
|
|
62
|
+
context str do
|
|
63
|
+
it 'should parse as DenOnlyNode' do
|
|
64
|
+
res.should be_a DenOnlyNode
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe '#to_r' do
|
|
68
|
+
r = res.to_r
|
|
69
|
+
it 'should produce a Rational' do
|
|
70
|
+
r.should be_a Rational
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'should produce value matching input str' do
|
|
74
|
+
r.should eq tgt
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe DurationParser do
|
|
4
|
+
before :all do
|
|
5
|
+
@valid = {
|
|
6
|
+
:numbers => [1,5,50,3999,01,0010,0000005050],
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@invalid = {
|
|
10
|
+
:numbers => [0,00],
|
|
11
|
+
}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context 'valid (non-zero) numerator and denominator' do
|
|
15
|
+
["n","n/","n/d","/d"].each do |expr|
|
|
16
|
+
it "should parse durations of the form #{expr}" do
|
|
17
|
+
@valid[:numbers].each do |n|
|
|
18
|
+
@valid[:numbers].each do |d|
|
|
19
|
+
str = expr.gsub('n',"#{n}")
|
|
20
|
+
str = str.gsub('d',"#{d}")
|
|
21
|
+
DUR_PARSER.parse(str).should_not be nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'invalid (zero) numerator and valid denominator' do
|
|
29
|
+
["n","n/","n/d"].each do |expr|
|
|
30
|
+
it "should parse durations of the form #{expr}" do
|
|
31
|
+
@invalid[:numbers].each do |n|
|
|
32
|
+
@valid[:numbers].each do |d|
|
|
33
|
+
str = expr.gsub('n',"#{n}")
|
|
34
|
+
str = str.gsub('d',"#{d}")
|
|
35
|
+
DUR_PARSER.parse(str).should be nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'valid numerator and invalid (zero) denominator' do
|
|
43
|
+
["n/d","/d"].each do |expr|
|
|
44
|
+
it "should parse durations of the form #{expr}" do
|
|
45
|
+
@valid[:numbers].each do |n|
|
|
46
|
+
@invalid[:numbers].each do |d|
|
|
47
|
+
str = expr.gsub('n',"#{n}")
|
|
48
|
+
str = str.gsub('d',"#{d}")
|
|
49
|
+
DUR_PARSER.parse(str).should be nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'invalid numerator and invalid denominator' do
|
|
57
|
+
["n","n/","n/d","/d"].each do |expr|
|
|
58
|
+
it "should parse durations of the form #{expr}" do
|
|
59
|
+
@invalid[:numbers].each do |n|
|
|
60
|
+
@invalid[:numbers].each do |d|
|
|
61
|
+
str = expr.gsub('n',"#{n}")
|
|
62
|
+
str = str.gsub('d',"#{d}")
|
|
63
|
+
DUR_PARSER.parse(str).should be nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe LinkNode do
|
|
4
|
+
parser = LinkParser.new
|
|
5
|
+
|
|
6
|
+
{
|
|
7
|
+
'=C4' => Link::Slur.new(C4),
|
|
8
|
+
'/Db2' => Link::Portamento.new(Db2),
|
|
9
|
+
'~C#2' => Link::Glissando.new(Db2),
|
|
10
|
+
'-Db2' => Link::Legato.new(Db2),
|
|
11
|
+
}.each do |str,tgt|
|
|
12
|
+
res = parser.parse(str)
|
|
13
|
+
context str do
|
|
14
|
+
it 'should parse as LinkNode' do
|
|
15
|
+
res.should be_a LinkNode
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '#to_pitch' do
|
|
19
|
+
l = res.to_link
|
|
20
|
+
it 'should produce a Link object' do
|
|
21
|
+
l.should be_a Link
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'should produce pitch matching input str' do
|
|
25
|
+
l.should eq tgt
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe LinkParser do
|
|
4
|
+
before :all do
|
|
5
|
+
@parser = LinkParser.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it 'should parse a "=C2"' do
|
|
9
|
+
@parser.parse("=C2").should_not be nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'should parse a "-C2"' do
|
|
13
|
+
@parser.parse("-C2").should_not be nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should parse a "~C2"' do
|
|
17
|
+
@parser.parse("~C2").should_not be nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should parse a "/C2"' do
|
|
21
|
+
@parser.parse("/C2").should_not be nil
|
|
22
|
+
end
|
|
23
|
+
end
|