musa-dsl 0.14.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +20 -0
  4. data/LICENSE.md +157 -0
  5. data/README.md +8 -0
  6. data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
  7. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
  8. data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
  9. data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
  10. data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
  11. data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
  12. data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
  13. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
  14. data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
  15. data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
  16. data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
  17. data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
  18. data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
  19. data/lib/musa-dsl/core-ext.rb +13 -0
  20. data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
  21. data/lib/musa-dsl/datasets/gdv.rb +499 -0
  22. data/lib/musa-dsl/datasets/pdv.rb +44 -0
  23. data/lib/musa-dsl/datasets.rb +5 -0
  24. data/lib/musa-dsl/generative/darwin.rb +145 -0
  25. data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
  26. data/lib/musa-dsl/generative/markov.rb +78 -0
  27. data/lib/musa-dsl/generative/rules.rb +282 -0
  28. data/lib/musa-dsl/generative/variatio.rb +331 -0
  29. data/lib/musa-dsl/generative.rb +5 -0
  30. data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
  31. data/lib/musa-dsl/midi/midi-voices.rb +274 -0
  32. data/lib/musa-dsl/midi.rb +2 -0
  33. data/lib/musa-dsl/music/chord-definition.rb +99 -0
  34. data/lib/musa-dsl/music/chord-definitions.rb +13 -0
  35. data/lib/musa-dsl/music/chords.rb +326 -0
  36. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
  37. data/lib/musa-dsl/music/scales.rb +584 -0
  38. data/lib/musa-dsl/music.rb +6 -0
  39. data/lib/musa-dsl/neuma/neuma.rb +181 -0
  40. data/lib/musa-dsl/neuma.rb +1 -0
  41. data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
  42. data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
  43. data/lib/musa-dsl/neumalang.rb +3 -0
  44. data/lib/musa-dsl/repl/repl.rb +143 -0
  45. data/lib/musa-dsl/repl.rb +1 -0
  46. data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
  47. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
  48. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
  49. data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
  50. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
  51. data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
  52. data/lib/musa-dsl/sequencer.rb +1 -0
  53. data/lib/musa-dsl/series/base-series.rb +245 -0
  54. data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
  55. data/lib/musa-dsl/series/holder-serie.rb +87 -0
  56. data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
  57. data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
  58. data/lib/musa-dsl/series/proxy-serie.rb +69 -0
  59. data/lib/musa-dsl/series/queue-serie.rb +94 -0
  60. data/lib/musa-dsl/series/series.rb +8 -0
  61. data/lib/musa-dsl/series.rb +1 -0
  62. data/lib/musa-dsl/transport/clock.rb +36 -0
  63. data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
  64. data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
  65. data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
  66. data/lib/musa-dsl/transport/timer-clock.rb +102 -0
  67. data/lib/musa-dsl/transport/timer.rb +40 -0
  68. data/lib/musa-dsl/transport/transport.rb +137 -0
  69. data/lib/musa-dsl/transport.rb +9 -0
  70. data/lib/musa-dsl.rb +17 -0
  71. data/musa-dsl.gemspec +17 -0
  72. metadata +174 -0
@@ -0,0 +1,181 @@
1
+ module Musa::Neumalang
2
+ module Neumas # Neumas serie
3
+ # TODO implementar | ???? neumas | neumas = parallel neumas, no?
4
+ end
5
+
6
+ module Neuma
7
+ module Parallel
8
+ include Neuma
9
+ end
10
+
11
+ def |(other)
12
+ if is_a?(Parallel)
13
+ clone.tap { |_| _[:parallel] << convert_to_parallel_element(other) }.extend(Parallel)
14
+ else
15
+ { kind: :parallel,
16
+ parallel: [clone, convert_to_parallel_element(other)]
17
+ }.extend(Parallel)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def convert_to_parallel_element(e)
24
+ case e
25
+ when String then { kind: :serie, serie: e.to_neumas }.extend(Neuma)
26
+ else
27
+ raise ArgumentError, "Dont know how to convert to neuma #{e}"
28
+ end
29
+ end
30
+ end
31
+
32
+ module Dataset
33
+ class Decorator
34
+ def process(element, base_duration:, tick_duration:)
35
+ element
36
+ end
37
+
38
+ def check(value_or_array, &block)
39
+ if block_given?
40
+ if value_or_array.is_a?(Array)
41
+ value_or_array.each { |value| yield value }
42
+ else
43
+ yield value_or_array
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ class TwoNeumasDecorator < Decorator
50
+ def process(element1, element2, base_duration:, tick_duration:)
51
+ element2
52
+ end
53
+ end
54
+
55
+ class Decorators
56
+ attr_reader :decorators
57
+ attr_accessor :appogiatura_decorator
58
+
59
+ def initialize(*decorators, appogiatura_decorator: nil, base_duration: nil, tick_duration: nil)
60
+ @base_duration = 1/4r
61
+ @tick_duration = tick_duration || 1/96r
62
+
63
+ @appogiatura_decorator = appogiatura_decorator
64
+ @decorators = decorators
65
+ end
66
+
67
+ def process(element)
68
+ if @appogiatura_decorator
69
+ element = @appogiatura_decorator.process(element, base_duration: @base_duration, tick_duration: @tick_duration)
70
+ end
71
+
72
+ @decorators.each do |processor|
73
+ if element
74
+ if element.is_a?(Array)
75
+ element = element.collect { |element_i| processor.process(element_i, base_duration: @base_duration, tick_duration: @tick_duration) }.flatten(1)
76
+ else
77
+ element = processor.process(element, base_duration: @base_duration, tick_duration: @tick_duration)
78
+ end
79
+ end
80
+ end
81
+
82
+ element
83
+ end
84
+ end
85
+
86
+ protected
87
+
88
+ def positive_sign_of(x)
89
+ x >= 0 ? '+' : ''
90
+ end
91
+
92
+ def sign_of(x)
93
+ '++-'[x <=> 0]
94
+ end
95
+
96
+ def velocity_of(x)
97
+ %w[ppp pp p mp mf f ff fff][x + 3]
98
+ end
99
+
100
+ def modificator_string(modificator, parameter_or_parameters)
101
+ case parameter_or_parameters
102
+ when true
103
+ modificator.to_s
104
+ when Array
105
+ "#{modificator.to_s}(#{parameter_or_parameters.collect { |p| parameter_to_string(p) }.join(', ')})"
106
+ else
107
+ "#{modificator.to_s}(#{parameter_to_string(parameter_or_parameters)})"
108
+ end
109
+ end
110
+
111
+ private
112
+
113
+ def parameter_to_string(parameter)
114
+ case parameter
115
+ when String
116
+ "\"#{parameter}\""
117
+ when Numeric
118
+ "#{parameter}"
119
+ when Symbol
120
+ "#{parameter}"
121
+ end
122
+ end
123
+ end
124
+
125
+ class ProtoDecoder
126
+ def subcontext
127
+ self
128
+ end
129
+
130
+ def decode(_element)
131
+ raise NotImplementedError
132
+ end
133
+ end
134
+
135
+ class DifferentialDecoder < ProtoDecoder
136
+ def decode(attributes)
137
+ parse attributes
138
+ end
139
+
140
+ def parse(_attributes)
141
+ raise NotImplementedError
142
+ end
143
+ end
144
+
145
+ class Decoder < DifferentialDecoder
146
+ def initialize(base, processor: nil)
147
+ @base = base
148
+ @last = base.clone
149
+
150
+ @processor = processor
151
+ end
152
+
153
+ attr_accessor :processor
154
+ attr_reader :base
155
+
156
+ def base=(base)
157
+ @base = base
158
+ @last = base.clone
159
+ end
160
+
161
+ def subcontext
162
+ Decoder.new @base
163
+ end
164
+
165
+ def decode(attributes)
166
+ result = apply parse(attributes), on: @last
167
+
168
+ @last = result.clone
169
+
170
+ if @processor
171
+ @processor.process(result)
172
+ else
173
+ result
174
+ end
175
+ end
176
+
177
+ def apply(_action, on:)
178
+ raise NotImplementedError
179
+ end
180
+ end
181
+ end
@@ -0,0 +1 @@
1
+ require 'musa-dsl/neuma/neuma'
@@ -0,0 +1,294 @@
1
+ grammar Neumalang
2
+
3
+ rule content
4
+ sentences
5
+ end
6
+
7
+ rule sentences
8
+ (spaces (sentence spaces)*) <Musa::Neumalang::Parser::Sentences>
9
+ end
10
+
11
+ rule sentence
12
+ expression
13
+ end
14
+
15
+ rule expression
16
+ variable_assign | call_methods_expression | object_expression | event
17
+ end
18
+
19
+ rule object_expression
20
+ braced_command | reference_expression | bracketed_expression | use_variable | constant | neuma
21
+ end
22
+
23
+ rule reference_expression
24
+ (ampersand spaces expression) <Musa::Neumalang::Parser::ReferenceExpression>
25
+ end
26
+
27
+ rule variable_assign
28
+ ((use_variable spaces equal spaces)+ expression) <Musa::Neumalang::Parser::VariableAssign>
29
+ end
30
+
31
+ rule event
32
+ (double_colon name parameters?) <Musa::Neumalang::Parser::Event>
33
+ end
34
+
35
+ rule braced_command
36
+ (lbrace spaces complex_command spaces rbrace parameters?) <Musa::Neumalang::Parser::BracedCommand>
37
+ end
38
+
39
+ rule call_methods_expression
40
+ (object_expression (dot method_call)+) <Musa::Neumalang::Parser::CallMethodsExpression>
41
+ end
42
+
43
+ rule bracketed_expression
44
+ bracketed_bar_sentences | bracketed_sentences
45
+ end
46
+
47
+ rule method_call
48
+ (name parameters?) { { method: capture(:name).value.to_sym }.merge(capture(:parameters) ? capture(:parameters).value : {}) }
49
+ end
50
+
51
+ rule neuma
52
+ appogiatura_neuma | simple_neuma
53
+ end
54
+
55
+ rule appogiatura_neuma
56
+ (lpar spaces a:simple_neuma spaces rpar spaces b:simple_neuma) { capture(:b).value.tap { |_| _[:neuma] << { appogiatura: capture(:a).value[:neuma] } } }
57
+ end
58
+
59
+ rule simple_neuma
60
+ neuma_as_dotted_attributes_beginning_with_dot | neuma_as_dotted_attributes_beginning_with_simple_attribute | neuma_between_angles_attributes
61
+ end
62
+
63
+ rule constant
64
+ number | symbol | string
65
+ end
66
+
67
+ rule bracketed_bar_sentences
68
+ (lbracket spaces aa:sentences (bar spaces bb:sentences)+ rbracket) <Musa::Neumalang::Parser::BracketedBarSentences>
69
+ end
70
+
71
+ rule bracketed_sentences
72
+ (lbracket spaces sentences rbracket) <Musa::Neumalang::Parser::BracketedSentences>
73
+ end
74
+
75
+ rule use_variable
76
+ (at name) <Musa::Neumalang::Parser::UseVariable>
77
+ end
78
+
79
+ rule parameters
80
+ parameters_a | parameters_b | parameters_c
81
+ end
82
+
83
+ rule parameters_a
84
+ (lpar positional_parameters comma key_parameters rpar) { { value_parameters: capture(:positional_parameters).value, key_parameters: capture(:key_parameters).value } }
85
+ end
86
+
87
+ rule parameters_b
88
+ (lpar key_parameters rpar) { { key_parameters: capture(:key_parameters).value } }
89
+ end
90
+
91
+ rule parameters_c
92
+ (lpar positional_parameters rpar) { { value_parameters: capture(:positional_parameters).value } }
93
+ end
94
+
95
+ rule positional_parameters
96
+ (spaces a:sentence (spaces comma spaces b:sentence spaces)* spaces) {
97
+ [ capture(:a).value ] + captures(:b).collect { |c| c.value }
98
+ }
99
+ end
100
+
101
+ rule key_parameters
102
+ (spaces a:key_value_parameter (spaces comma spaces b:key_value_parameter spaces)* spaces) {
103
+
104
+ result = capture(:a).value.clone
105
+
106
+ captures(:b).each { |c| result.merge! c.value }
107
+
108
+ result
109
+ }
110
+ end
111
+
112
+ rule key_value_parameter
113
+ (key:name colon spaces value:sentence) { { capture(:key).value.to_sym => capture(:value).value } }
114
+ end
115
+
116
+ rule complex_command
117
+ (everything_except_braces? lbrace spaces complex_command spaces rbrace)* everything_except_braces?
118
+ end
119
+
120
+
121
+ rule neuma_as_dotted_attributes_beginning_with_simple_attribute
122
+ (a:simple_attribute (dot b:attribute)*) <Musa::Neumalang::Parser::NeumaAsDottedAttributesBeginningWithSimpleAttribute>
123
+ end
124
+
125
+ rule neuma_as_dotted_attributes_beginning_with_dot
126
+ ((dot attribute)+ | dot) <Musa::Neumalang::Parser::NeumaAsDottedAttributesBeginningWithDot>
127
+ end
128
+
129
+ rule neuma_between_angles_attributes
130
+ (langle spaces simple_attribute? spaces (attribute spaces)* rangle) <Musa::Neumalang::Parser::NeumaBetweenAnglesAttributes>
131
+ end
132
+
133
+ rule attribute
134
+ (modifier_attribute | simple_attribute)
135
+ end
136
+
137
+ rule simple_attribute
138
+ everything_that_can_be_an_attribute !colon
139
+ end
140
+
141
+ rule modifier_attribute
142
+ modifier_call_without_parameters | modifier_call_with_parameters
143
+ end
144
+
145
+ rule modifier_call_without_parameters
146
+ (name &attribute_change) { { modifier: capture(:name).value.to_sym } }
147
+ end
148
+
149
+ rule modifier_call_with_parameters
150
+ (name modifier_parameters) { { modifier: capture(:name).value.to_sym }.merge(capture(:modifier_parameters) ? capture(:modifier_parameters).value : {}) }
151
+ end
152
+
153
+ rule modifier_parameters
154
+ (lpar modifier_positional_parameters rpar) { { parameters: capture(:modifier_positional_parameters).value } }
155
+ end
156
+
157
+ rule modifier_positional_parameters
158
+ (spaces a:modifier_parameter_constant (spaces comma spaces b:modifier_parameter_constant spaces)* spaces) {
159
+ if capture(:b)
160
+ [ capture(:a).value ] + captures(:b).collect { |c| c.value }
161
+ else
162
+ capture(:a).value
163
+ end
164
+ }
165
+ end
166
+
167
+ rule modifier_parameter_constant
168
+ raw_number | raw_symbol | raw_string
169
+ end
170
+
171
+ rule number
172
+ float | rational | integer
173
+ end
174
+
175
+ rule raw_number
176
+ raw_float | raw_rational | raw_integer
177
+ end
178
+
179
+ rule symbol
180
+ (colon name) <Musa::Neumalang::Parser::Symbol>
181
+ end
182
+
183
+ rule raw_symbol
184
+ (name &spaces) { capture(:name).value.to_sym }
185
+ end
186
+
187
+ rule string
188
+ (double_quote everything_except_double_quote double_quote) <Musa::Neumalang::Parser::String>
189
+ end
190
+
191
+ rule raw_string
192
+ (double_quote everything_except_double_quote double_quote) { capture(:everything_except_double_quote).value }
193
+ end
194
+
195
+ rule float
196
+ (single_quote str:(digits dot digits) spaces) <Musa::Neumalang::Parser::Float>
197
+ end
198
+
199
+ rule raw_float
200
+ (str:(digits dot digits) spaces) { capture(:str).value.to_f }
201
+ end
202
+
203
+ rule integer
204
+ (single_quote digits spaces) <Musa::Neumalang::Parser::Integer>
205
+ end
206
+
207
+ rule raw_integer
208
+ (digits spaces) { capture(:digits).value.to_i }
209
+ end
210
+
211
+ rule rational
212
+ (single_quote str:(digits slash digits) spaces) <Musa::Neumalang::Parser::Rational>
213
+ end
214
+
215
+ rule raw_rational
216
+ (str: (digits slash digits) spaces) { capture(:str).value.to_r }
217
+ end
218
+
219
+ rule comment
220
+ (lcomment complex_comment rcomment) | hash_comment
221
+ end
222
+
223
+ rule hash_comment
224
+ (hsh_at_start_of_line | space+) everything_until_eol
225
+ end
226
+
227
+ rule complex_comment
228
+ everything_except_comment? (lcomment complex_comment rcomment)* everything_except_comment?
229
+ end
230
+
231
+ rule digits
232
+ [0-9]+ ('_' [0-9]+)*
233
+ end
234
+
235
+ rule name
236
+ /[[:alpha:]]\w*/
237
+ end
238
+
239
+ rule everything_that_can_be_an_attribute
240
+ /[^({|}|\[|\]|\(|\)|\<|\>|.|,|:|=| |\t|\n|\r|\"|@|&|\|)]+/m
241
+ end
242
+
243
+ rule attribute_change
244
+ space | dot | rbracket | rpar | rbrace | eol
245
+ end
246
+
247
+ rule everything_until_eol
248
+ ~/$/
249
+ end
250
+
251
+ rule everything_except_comment
252
+ ~/((\*\/)|(\/\*))/m
253
+ end
254
+
255
+ rule everything_except_braces
256
+ ~/({|})/m
257
+ end
258
+
259
+ rule everything_except_double_quote
260
+ ~/(\")/m
261
+ end
262
+
263
+ rule hsh_at_start_of_line
264
+ /\A#/
265
+ end
266
+
267
+ rule double_quote '"' end
268
+ rule single_quote '\'' end
269
+ rule dot '.' end
270
+ rule comma ',' end
271
+ rule colon ':' end
272
+ rule double_colon '::' end
273
+ rule bar '|' end
274
+ rule slash '/' end
275
+ rule lpar '(' end
276
+ rule rpar ')' end
277
+ rule lbrace '{' end
278
+ rule rbrace '}' end
279
+ rule lbracket '[' end
280
+ rule rbracket ']' end
281
+ rule langle '<' end
282
+ rule rangle '>' end
283
+ rule at '@' end
284
+ rule ampersand '&' end
285
+ rule equal '=' end
286
+ rule lcomment '/*' end
287
+ rule rcomment '*/' end
288
+ rule hsh '#' end
289
+ rule eol /$/ end
290
+
291
+ rule space /[ \t\n\r]/m end
292
+ rule spaces (space | comment)* end
293
+
294
+ end
@@ -0,0 +1,179 @@
1
+ require 'musa-dsl/series'
2
+ require 'citrus'
3
+
4
+ module Musa::Neumalang
5
+ module Parser
6
+ module Sentences
7
+ include Musa::Series
8
+
9
+ def value
10
+ _SE(captures(:sentence).collect(&:value), extends: Neumas)
11
+ end
12
+ end
13
+
14
+ module BracketedBarSentences
15
+ include Musa::Series
16
+
17
+ def value
18
+ { kind: :parallel,
19
+ parallel: [{ kind: :serie, serie: S(*capture(:aa).value) }] + captures(:bb).collect { |c| { kind: :serie, serie: S(*c.value) } }
20
+ }.extend(Neuma::Parallel)
21
+ end
22
+ end
23
+
24
+ module BracketedSentences
25
+ include Musa::Series
26
+
27
+ def value
28
+ { kind: :serie,
29
+ serie: S(*capture(:sentences).value) }.extend Neuma
30
+ end
31
+ end
32
+
33
+ module ReferenceExpression
34
+ def value
35
+ { kind: :reference,
36
+ reference: capture(:expression).value }.extend Neuma
37
+ end
38
+ end
39
+
40
+ module VariableAssign
41
+ def value
42
+ { kind: :assign_to,
43
+ assign_to: captures(:use_variable).collect { |c| c.value[:use_variable] }, assign_value: capture(:expression).value
44
+ }.extend Neuma
45
+ end
46
+ end
47
+
48
+ module Event
49
+ def value
50
+ { kind: :event,
51
+ event: capture(:name).value.to_sym
52
+ }.merge(capture(:parameters) ? capture(:parameters).value : {}).extend Neuma
53
+ end
54
+ end
55
+
56
+ module BracedCommand
57
+ def value
58
+ { kind: :command,
59
+ command: eval("proc { #{capture(:complex_command).value.strip} }")
60
+ }.merge(capture(:parameters) ? capture(:parameters).value : {}).extend Neuma
61
+ end
62
+ end
63
+
64
+ module CallMethodsExpression
65
+ def value
66
+ { kind: :call_methods,
67
+ call_methods: captures(:method_call).collect(&:value),
68
+ on: capture(:object_expression).value }.extend Neuma
69
+ end
70
+ end
71
+
72
+ module UseVariable
73
+ def value
74
+ { kind: :use_variable,
75
+ use_variable: "@#{capture(:name).value}".to_sym }.extend Neuma
76
+ end
77
+ end
78
+
79
+ module NeumaAsDottedAttributesBeginningWithSimpleAttribute
80
+ def value
81
+ { kind: :neuma,
82
+ neuma: (capture(:a) ? [capture(:a).value] : []) + captures(:b).collect(&:value) }.extend Neuma
83
+ end
84
+ end
85
+
86
+ module NeumaAsDottedAttributesBeginningWithDot
87
+ def value
88
+ { kind: :neuma,
89
+ neuma: (capture(:attribute) ? [ nil ] : []) + captures(:attribute).collect(&:value) }.extend Neuma
90
+ end
91
+ end
92
+
93
+ module NeumaBetweenAnglesAttributes
94
+ def value
95
+ { kind: :neuma,
96
+ neuma: (capture(:simple_attribute) ? [capture(:simple_attribute).value] : []) + captures(:attribute).collect(&:value) }.extend Neuma
97
+ end
98
+ end
99
+
100
+ module Symbol
101
+ def value
102
+ { kind: :value,
103
+ value: capture(:name).value.to_sym }.extend Neuma
104
+ end
105
+ end
106
+
107
+ module String
108
+ def value
109
+ { kind: :value,
110
+ value: capture(:everything_except_double_quote).value }.extend Neuma
111
+ end
112
+ end
113
+
114
+ module Float
115
+ def value
116
+ { kind: :value,
117
+ value: capture(:str).value.to_f }.extend Neuma
118
+ end
119
+ end
120
+
121
+ module Integer
122
+ def value
123
+ { kind: :value,
124
+ value: capture(:digits).value.to_i }.extend Neuma
125
+ end
126
+ end
127
+
128
+ module Rational
129
+ def value
130
+ { kind: :value,
131
+ value: capture(:str).value.to_r }.extend Neuma
132
+ end
133
+ end
134
+ end
135
+
136
+ def self.register(grammar_path)
137
+ Citrus.load grammar_path
138
+ end
139
+
140
+ def self.parse(string_or_file, language: nil, decode_with: nil, debug: nil)
141
+ language ||= Neumalang
142
+
143
+ match = nil
144
+
145
+ if string_or_file.is_a? String
146
+ match = language.parse string_or_file
147
+
148
+ elsif string_or_file.is_a? File
149
+ match = language.parse string_or_file.read
150
+
151
+ else
152
+ raise ArgumentError, 'Only String or File allowed to be parsed'
153
+ end
154
+
155
+ match.dump if debug
156
+
157
+ serie = match.value
158
+
159
+ if decode_with
160
+ serie.eval do |e|
161
+ if e[:kind] == :neuma
162
+ decode_with.decode(e[:neuma])
163
+ else
164
+ raise ArgumentError, "Don't know how to convert #{e} to neuma"
165
+ end
166
+ end
167
+ else
168
+ serie
169
+ end
170
+ end
171
+
172
+ def self.parse_file(filename, decode_with: nil, debug: nil)
173
+ File.open filename do |file|
174
+ parse file, decode_with: decode_with, debug: debug
175
+ end
176
+ end
177
+
178
+ register File.join(File.dirname(__FILE__), 'neumalang')
179
+ end
@@ -0,0 +1,3 @@
1
+ require 'musa-dsl/neumalang/neumalang'
2
+
3
+