lydown 0.3.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.
@@ -0,0 +1,160 @@
1
+ grammar Lydown
2
+ include Lydown::Parsing
3
+
4
+ rule lines
5
+ line ([\n] line)* <Root>
6
+ end
7
+ rule stream_switch
8
+ music_stream / lyrics_stream / lyrics2_stream
9
+ end
10
+ rule music_stream
11
+ '=music' white_space? [\n] music ([\n] !stream_breaker music)*
12
+ end
13
+ rule lyrics_stream
14
+ '=lyrics' white_space? [\n] lyrics_content ([\n] !stream_breaker lyrics_content)*
15
+ end
16
+ rule lyrics2_stream
17
+ '=lyrics2' white_space? [\n] lyrics2_content ([\n] !stream_breaker lyrics2_content)*
18
+ end
19
+ rule stream_breaker
20
+ stream_switch / stream_breaking_setting
21
+ end
22
+ rule stream_breaking_setting
23
+ '-' white_space* ('part:' / 'movement:') setting_value comment?
24
+ end
25
+ rule line
26
+ stream_switch / comment / setting / lyrics / music
27
+ end
28
+ rule comment
29
+ '//' comment_content
30
+ end
31
+ rule comment_content
32
+ [^\n]* <CommentContent>
33
+ end
34
+ rule setting
35
+ white_space? '-' white_space* setting_key ':' setting_value comment? <Setting>
36
+ end
37
+ rule setting_key
38
+ [a-z0-9_]+ <Setting::Key>
39
+ end
40
+ rule setting_value
41
+ (!"\n" !"//" .)* <Setting::Value>
42
+ end
43
+ rule music
44
+ white_space? event* comment?
45
+ end
46
+ rule white_space
47
+ [ \t]+
48
+ end
49
+ rule event
50
+ (barline / duration / note / standalone_figures / rest / silence / phrasing / tie) white_space*
51
+ end
52
+ rule barline
53
+ ('?|' / ':|][|:' / '[|:' / ':|]' / [\|\.\:]+) <Barline>
54
+ # ('|' / '.' / '||' / '.|' / '..' / '|.|' / '|.' /
55
+ # '.|') <Barline>
56
+ end
57
+ rule duration
58
+ duration_value / duration_macro
59
+ end
60
+ rule duration_value
61
+ number dots* multiplier? <DurationValue>
62
+ end
63
+ rule number
64
+ [0-9]+
65
+ end
66
+ rule dots
67
+ '.'+
68
+ end
69
+ rule multiplier
70
+ '*' number ('/' number)*
71
+ end
72
+ rule duration_macro
73
+ '{' duration_macro__expression '}'
74
+ end
75
+ rule duration_macro__expression
76
+ (macro_name / macro_event*) <DurationMacroExpression>
77
+ end
78
+ rule macro_event
79
+ (duration / note_placeholder / rest / silence / phrasing / tie) white_space*
80
+ end
81
+ rule macro_name
82
+ [a-zA-Z_] [a-zA-Z0-9_]*
83
+ end
84
+ rule note_placeholder
85
+ [_@] expression*
86
+ end
87
+ rule note
88
+ note_head octave* accidental_flag? figures? expression* <Note>
89
+ end
90
+ rule expression
91
+ (expression_shorthand / expression_longhand) <Note::Expression>
92
+ end
93
+
94
+ rule expression_shorthand
95
+ [\_\.`]
96
+ end
97
+ rule expression_longhand
98
+ '\\' [^\s\n]+
99
+ end
100
+ rule figures # bass figures
101
+ '<' figures_component? (white_space? figures_component)* '>'
102
+ end
103
+ rule figures_component
104
+ ('_' / [#bh] / ([1-9] [\+\-\!\\'`]*)) <FiguresComponent>
105
+ end
106
+ rule standalone_figures
107
+ duration_value? figures <StandAloneFigures>
108
+ end
109
+ rule rest
110
+ [rR] multiplier* <Rest>
111
+ end
112
+ rule silence
113
+ [s] multiplier* <Silence>
114
+ end
115
+ rule note_head
116
+ [a-g] accidental* <Note::Head>
117
+ end
118
+ rule accidental
119
+ [\+\-]+
120
+ end
121
+ rule octave
122
+ [\,']+ <Note::Octave>
123
+ end
124
+ rule accidental_flag
125
+ [\!\?] <Note::AccidentalFlag>
126
+ end
127
+ rule phrasing
128
+ beam_open / beam_close / slur_open / slur_close
129
+ end
130
+ rule beam_open
131
+ [\[] white_space* <Phrasing::BeamOpen>
132
+ end
133
+ rule beam_close
134
+ white_space* [\]] white_space* <Phrasing::BeamClose>
135
+ end
136
+ rule slur_open
137
+ [\(] white_space* <Phrasing::SlurOpen>
138
+ end
139
+ rule slur_close
140
+ white_space* [\)] white_space* <Phrasing::SlurClose>
141
+ end
142
+ rule tie
143
+ regular_tie / short_tie
144
+ end
145
+ rule regular_tie
146
+ '~' <Tie>
147
+ end
148
+ rule short_tie
149
+ '&' <ShortTie>
150
+ end
151
+ rule lyrics
152
+ '>' white_space* lyrics_content
153
+ end
154
+ rule lyrics_content
155
+ (!"\n" !"//" .)* <Lyrics>
156
+ end
157
+ rule lyrics2_content
158
+ (!"\n" !"//" .)* <Lyrics2>
159
+ end
160
+ end
@@ -0,0 +1,191 @@
1
+ module Lydown::Parsing
2
+ module Root
3
+ def _to_stream(element, stream)
4
+ if element.elements
5
+ element.elements.each do |e|
6
+ e.respond_to?(:to_stream) ? e.to_stream(stream) : _to_stream(e, stream)
7
+ end
8
+ end
9
+ stream
10
+ end
11
+
12
+ def to_stream(stream = [])
13
+ _to_stream(self, stream)
14
+ stream
15
+ end
16
+ end
17
+
18
+ module CommentContent
19
+ def to_stream(stream)
20
+ stream << {type: :comment, content: text_value.strip}
21
+ end
22
+ end
23
+
24
+ module Setting
25
+ include Root
26
+
27
+ def to_stream(stream)
28
+ level = (text_value =~ /^([\s]+)/) ? ($1.length / 2) : 0
29
+ @setting = {type: :setting, level: level}
30
+ _to_stream(self, stream)
31
+ end
32
+
33
+ def setting
34
+ @setting
35
+ end
36
+
37
+ def emit_setting(stream)
38
+ stream << @setting
39
+ end
40
+
41
+ module Key
42
+ def to_stream(stream)
43
+ parent.setting[:key] = text_value
44
+ end
45
+ end
46
+
47
+ module Value
48
+ def to_stream(stream)
49
+ parent.setting[:value] = text_value.strip
50
+ parent.emit_setting(stream)
51
+ end
52
+ end
53
+ end
54
+
55
+ module DurationValue
56
+ def to_stream(stream)
57
+ stream << {type: :duration, value: text_value}
58
+ end
59
+ end
60
+
61
+ module Note
62
+ include Root
63
+
64
+ def to_stream(stream)
65
+ note = {type: :note, raw: text_value}
66
+ _to_stream(self, note)
67
+ stream << note
68
+ end
69
+
70
+ module Head
71
+ def to_stream(note)
72
+ note[:head] = text_value
73
+ end
74
+ end
75
+
76
+ module Octave
77
+ def to_stream(note)
78
+ note[:octave] = text_value
79
+ end
80
+ end
81
+
82
+ module AccidentalFlag
83
+ def to_stream(note)
84
+ note[:accidental_flag] = text_value
85
+ end
86
+ end
87
+
88
+ module Expression
89
+ def to_stream(note)
90
+ note[:expressions] ||= []
91
+ note[:expressions] << text_value
92
+ end
93
+ end
94
+ end
95
+
96
+ module FiguresComponent
97
+ def to_stream(note)
98
+ note[:figures] ||= []
99
+ note[:figures] << text_value
100
+ end
101
+ end
102
+
103
+ module StandAloneFigures
104
+ include Root
105
+
106
+ def to_stream(stream)
107
+ note = {type: :stand_alone_figures}
108
+ _to_stream(self, note)
109
+ stream << note
110
+ end
111
+ end
112
+
113
+ module Phrasing
114
+ module BeamOpen
115
+ def to_stream(stream)
116
+ stream << {type: :beam_open}
117
+ end
118
+ end
119
+
120
+ module BeamClose
121
+ def to_stream(stream)
122
+ stream << {type: :beam_close}
123
+ end
124
+ end
125
+
126
+ module SlurOpen
127
+ def to_stream(stream)
128
+ stream << {type: :slur_open}
129
+ end
130
+ end
131
+
132
+ module SlurClose
133
+ def to_stream(stream)
134
+ stream << {type: :slur_close}
135
+ end
136
+ end
137
+ end
138
+
139
+ module Tie
140
+ def to_stream(stream)
141
+ stream << {type: :tie}
142
+ end
143
+ end
144
+
145
+ module ShortTie
146
+ def to_stream(stream)
147
+ stream << {type: :short_tie}
148
+ end
149
+ end
150
+
151
+ module Rest
152
+ def to_stream(stream)
153
+ rest = {type: :rest, raw: text_value, head: text_value[0]}
154
+ if text_value =~ /^R(\*([0-9]+))?$/
155
+ rest[:multiplier] = $2 || '1'
156
+ end
157
+
158
+ stream << rest
159
+ end
160
+ end
161
+
162
+ module Silence
163
+ def to_stream(stream)
164
+ stream << {type: :silence, raw: text_value, head: text_value[0]}
165
+ end
166
+ end
167
+
168
+ module DurationMacroExpression
169
+ def to_stream(stream)
170
+ stream << {type: :duration_macro, macro: text_value}
171
+ end
172
+ end
173
+
174
+ module Lyrics
175
+ def to_stream(stream)
176
+ stream << {type: :lyrics, content: text_value}
177
+ end
178
+ end
179
+
180
+ module Lyrics2
181
+ def to_stream(stream)
182
+ stream << {type: :lyrics, stream: :lyrics2, content: text_value}
183
+ end
184
+ end
185
+
186
+ module Barline
187
+ def to_stream(stream)
188
+ stream << {type: :barline, barline: text_value}
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,33 @@
1
+ require 'polyglot'
2
+ require 'treetop'
3
+
4
+ require 'lydown/parsing/nodes'
5
+ require 'lydown/parsing/lydown.treetop'
6
+
7
+ # Treetop.load 'lydown/parsing/lydown'
8
+
9
+ class LydownParser
10
+ def self.parse(source, opts = {})
11
+ parser = self.new
12
+ ast = parser.parse(source)
13
+ unless ast
14
+ error_msg = format_parser_error(source, parser, opts)
15
+ STDERR.puts error_msg
16
+ raise LydownError, error_msg
17
+ else
18
+ ast.to_stream
19
+ end
20
+ end
21
+
22
+ def self.format_parser_error(source, parser, opts)
23
+ msg = opts[:source_filename] ? "#{opts[:source_filename]}: " : ""
24
+ if opts[:nice_error]
25
+ msg << "Unexpected character at line #{parser.failure_line} column #{parser.failure_column}:\n"
26
+ else
27
+ msg << "#{parser.failure_reason}:\n"
28
+ end
29
+ msg << " #{source.lines[parser.failure_line - 1]} #{' ' * parser.failure_column}^"
30
+
31
+ msg
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ module Lydown::Rendering
2
+ class Base
3
+ def initialize(event, work, stream, idx)
4
+ @event = event
5
+ @work = work
6
+ @stream = stream
7
+ @idx = idx
8
+ end
9
+
10
+ def translate
11
+ # do nothing by default
12
+ end
13
+
14
+ def next_event
15
+ idx = @idx + 1
16
+ while idx < @stream.size
17
+ e = @stream[idx]
18
+ return e if e && e[:type] != :comment
19
+ idx += 1
20
+ end
21
+ nil
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ module Lydown::Rendering
2
+ class Comment < Base
3
+ def translate
4
+ @work.emit(:music, "\n%{#{@event[:content]}%}\n")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,185 @@
1
+ ly_dir: ./_ly
2
+ pdf_dir: ./_pdf
3
+ midi_dir: ./_midi
4
+ lilypond_cmd: lilypond
5
+ parts:
6
+ soprano:
7
+ clef: treble
8
+ beaming: manual
9
+ midi_instrument: voice oohs
10
+ soprano1:
11
+ clef: treble
12
+ beaming: manual
13
+ midi_instrument: voice oohs
14
+ soprano2:
15
+ clef: treble
16
+ beaming: manual
17
+ midi_instrument: voice oohs
18
+ alto:
19
+ clef: treble
20
+ beaming: manual
21
+ midi_instrument: voice oohs
22
+ alto1:
23
+ clef: treble
24
+ beaming: manual
25
+ midi_instrument: voice oohs
26
+ alto2:
27
+ clef: treble
28
+ beaming: manual
29
+ midi_instrument: voice oohs
30
+ tenor:
31
+ clef: treble_8
32
+ beaming: manual
33
+ midi_instrument: voice oohs
34
+ tenor1:
35
+ clef: treble_8
36
+ beaming: manual
37
+ midi_instrument: voice oohs
38
+ tenor2:
39
+ clef: treble_8
40
+ beaming: manual
41
+ midi_instrument: voice oohs
42
+ tenore:
43
+ clef: treble_8
44
+ beaming: manual
45
+ midi_instrument: voice oohs
46
+ tenore1:
47
+ clef: treble_8
48
+ beaming: manual
49
+ midi_instrument: voice oohs
50
+ tenore2:
51
+ clef: treble_8
52
+ beaming: manual
53
+ midi_instrument: voice oohs
54
+ bass:
55
+ clef: bass
56
+ beaming: manual
57
+ midi_instrument: voice oohs
58
+ bass1:
59
+ clef: bass
60
+ beaming: manual
61
+ midi_instrument: voice oohs
62
+ bass2:
63
+ clef: bass
64
+ beaming: manual
65
+ midi_instrument: voice oohs
66
+ basso:
67
+ clef: bass
68
+ beaming: manual
69
+ midi_instrument: voice oohs
70
+ basso1:
71
+ clef: bass
72
+ beaming: manual
73
+ midi_instrument: voice oohs
74
+ basso2:
75
+ clef: bass
76
+ beaming: manual
77
+ midi_instrument: voice oohs
78
+ violin:
79
+ clef: treble
80
+ midi_instrument: violin
81
+ violon:
82
+ clef: treble
83
+ midi_instrument: violin
84
+ violino:
85
+ clef: treble
86
+ midi_instrument: violin
87
+ violin1:
88
+ clef: treble
89
+ midi_instrument: violin
90
+ violin2:
91
+ clef: treble
92
+ midi_instrument: violin
93
+ violon1:
94
+ clef: treble
95
+ midi_instrument: violin
96
+ violon2:
97
+ clef: treble
98
+ midi_instrument: violin
99
+ violino1:
100
+ clef: treble
101
+ midi_instrument: violin
102
+ violino2:
103
+ clef: treble
104
+ midi_instrument: violin
105
+ violini:
106
+ clef: treble
107
+ midi_instrument: violin
108
+ viola:
109
+ clef: alto
110
+ midi_instrument: viola
111
+ viola1:
112
+ clef: alto
113
+ midi_instrument: viola
114
+ viola2:
115
+ clef: alto
116
+ midi_instrument: viola
117
+ viola-da-gamba:
118
+ clef: bass
119
+ midi_instrument: viola
120
+ viola-da-gamba1:
121
+ clef: bass
122
+ midi_instrument: viola
123
+ viola-da-gamba2:
124
+ clef: bass
125
+ midi_instrument: viola
126
+ gamba1:
127
+ clef: alto
128
+ midi_instrument: viola
129
+ gamba2:
130
+ clef: alto
131
+ midi_instrument: viola
132
+ fagott:
133
+ clef: bass
134
+ midi_instrument: bassoon
135
+ fagotto:
136
+ clef: bass
137
+ midi_instrument: bassoon
138
+ violoncello:
139
+ clef: bass
140
+ midi_instrument: cello
141
+ cello:
142
+ clef: bass
143
+ midi_instrument: cello
144
+ continuo:
145
+ clef: bass
146
+ midi_instrument: cello
147
+ embed_figures: true
148
+ organo:
149
+ clef: bass
150
+ midi_instrument: church organ
151
+ oboe:
152
+ clef: treble
153
+ midi_instrument: oboe
154
+ oboe1:
155
+ clef: treble
156
+ midi_instrument: oboe
157
+ oboe2:
158
+ clef: treble
159
+ midi_instrument: oboe
160
+ flauto:
161
+ clef: treble
162
+ midi_instrument: recorder
163
+ flauto1:
164
+ clef: treble
165
+ midi_instrument: recorder
166
+ flauto2:
167
+ clef: treble
168
+ midi_instrument: recorder
169
+ flute:
170
+ midi_instrument: flute
171
+ flute1:
172
+ midi_instrument: flute
173
+ flute2:
174
+ midi_instrument: flute
175
+ score:
176
+ order:
177
+ - [flauto1, flauto2, flauto3, flute1, flute2, flute3]
178
+ - [oboe1, oboe2, oboe3]
179
+ - [violino1, violino2, violino3, violin1, violin2, violin3]
180
+ - viola
181
+ - [gamba1, gamba2]
182
+ - [soprano, alto, tenore, basso]
183
+ - [soprano1, alto1, tenore1, basso1]
184
+ - [soprano2, alto2, tenore2, basso2]
185
+ - continuo
@@ -0,0 +1,106 @@
1
+ module Lydown::Rendering
2
+ module Figures
3
+ def add_figures(figures, value)
4
+ if @work['process/running_values']
5
+ @work['process/running_values'].each do |v|
6
+ silence = "s"
7
+ if v != @work['process/last_figures_value']
8
+ silence << v
9
+ @work['process/last_figures_value'] = v
10
+ end
11
+ @work.emit(:figures, "#{silence} ")
12
+ end
13
+ @work['process/running_values'] = []
14
+ end
15
+
16
+ figures = lilypond_figures(figures)
17
+ if value != @work['process/last_figures_value']
18
+ figures << value
19
+ @work['process/last_figures_value'] = value
20
+ end
21
+
22
+ @work.emit(:figures, "#{figures} ")
23
+ @work.emit(:figures, EXTENDERS_ON) if @event[:figure_extenders_on]
24
+ @work.emit(:figures, EXTENDERS_OFF) if @event[:figure_extenders_off]
25
+ end
26
+
27
+ def add_stand_alone_figures(figures)
28
+ if @work['process/running_values']
29
+ # for stand alone figures, we regard the stand alone figure as being
30
+ # aligned to the last note. Therefore we pop its value from
31
+ # running_values array.
32
+ @work['process/running_values'].pop
33
+ end
34
+ value = @work['process/figures_duration_value'] || @work['process/last_value']
35
+ add_figures(figures, value)
36
+ end
37
+
38
+ def lilypond_figures(figures)
39
+ if figures
40
+ check_tenues(figures)
41
+ "<#{translate_figures(figures)}>"
42
+ else
43
+ "s"
44
+ end
45
+ end
46
+
47
+ def check_tenues(figures)
48
+ next_event = next_figures_event
49
+ unless next_event
50
+ # if next figures event is not found, check if there is a tenue, and
51
+ # add extenders off flag
52
+ @event[:figure_extenders_off] = true if @event[:tenue]
53
+ return
54
+ end
55
+
56
+ if next_event[:figures]
57
+ next_event[:tenue] = next_event[:figures].include?('_')
58
+ if next_event[:tenue] && !@event[:tenue]
59
+ @event[:figure_extenders_on] = true
60
+ elsif !next_event[:tenue] && @event[:tenue]
61
+ @event[:figure_extenders_off] = true
62
+ end
63
+
64
+ # transform underscores into figure components
65
+ next_event[:figures].each_with_index do |component, idx|
66
+ next_event[:figures][idx] = @event[:figures][idx] if component == '_'
67
+ end
68
+ end
69
+ end
70
+
71
+ def translate_figures(figures)
72
+ figures.map {|n| n.gsub(ALTERATION_RE) {|a| ALTERATION[a]}}.join(' ')
73
+ end
74
+
75
+ ALTERATION_RE = /[#bh`']/
76
+ ALTERATION = {
77
+ '#' => '_+',
78
+ 'b' => '_-',
79
+ 'h' => '_!',
80
+ '`' => '\\\\',
81
+ "'" => "/"
82
+ }
83
+ EXTENDERS_ON = "\\bassFigureExtendersOn "
84
+ EXTENDERS_OFF = "\\bassFigureExtendersOff "
85
+
86
+ HIDDEN_FORMAT = "\\once \\override BassFigure #'implicit = ##t"
87
+
88
+ def next_figures_event
89
+ idx = @idx + 1
90
+ while idx < @stream.size
91
+ event = @stream[idx]
92
+ case event[:type]
93
+ when :setting
94
+ if ['part', 'movement'].include? event[:key]
95
+ return nil
96
+ end
97
+ when :note
98
+ return event if event[:figures]
99
+ when :stand_alone_figures
100
+ return event
101
+ end
102
+ idx += 1
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,14 @@
1
+ module Lydown::Rendering
2
+ class Lyrics < Base
3
+ def translate
4
+ value = lilypond_lyrics(@event[:content])
5
+ @work.emit(@event[:stream] || :lyrics, value, ' ')
6
+ end
7
+
8
+ def lilypond_lyrics(lyrics)
9
+ lyrics.
10
+ gsub(/_+/) {|m| " __ #{'_ ' * (m.size - 1)}"}.
11
+ gsub(/\-+/) {|m| " -- #{'_ ' * (m.size - 1)}"}
12
+ end
13
+ end
14
+ end