musa-dsl 0.14.16
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/.gitignore +10 -0
- data/Gemfile +20 -0
- data/LICENSE.md +157 -0
- data/README.md +8 -0
- data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
- data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
- data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
- data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
- data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
- data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
- data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
- data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
- data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
- data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
- data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
- data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
- data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
- data/lib/musa-dsl/core-ext.rb +13 -0
- data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
- data/lib/musa-dsl/datasets/gdv.rb +499 -0
- data/lib/musa-dsl/datasets/pdv.rb +44 -0
- data/lib/musa-dsl/datasets.rb +5 -0
- data/lib/musa-dsl/generative/darwin.rb +145 -0
- data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
- data/lib/musa-dsl/generative/markov.rb +78 -0
- data/lib/musa-dsl/generative/rules.rb +282 -0
- data/lib/musa-dsl/generative/variatio.rb +331 -0
- data/lib/musa-dsl/generative.rb +5 -0
- data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
- data/lib/musa-dsl/midi/midi-voices.rb +274 -0
- data/lib/musa-dsl/midi.rb +2 -0
- data/lib/musa-dsl/music/chord-definition.rb +99 -0
- data/lib/musa-dsl/music/chord-definitions.rb +13 -0
- data/lib/musa-dsl/music/chords.rb +326 -0
- data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
- data/lib/musa-dsl/music/scales.rb +584 -0
- data/lib/musa-dsl/music.rb +6 -0
- data/lib/musa-dsl/neuma/neuma.rb +181 -0
- data/lib/musa-dsl/neuma.rb +1 -0
- data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
- data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
- data/lib/musa-dsl/neumalang.rb +3 -0
- data/lib/musa-dsl/repl/repl.rb +143 -0
- data/lib/musa-dsl/repl.rb +1 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
- data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
- data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
- data/lib/musa-dsl/sequencer.rb +1 -0
- data/lib/musa-dsl/series/base-series.rb +245 -0
- data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
- data/lib/musa-dsl/series/holder-serie.rb +87 -0
- data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
- data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
- data/lib/musa-dsl/series/proxy-serie.rb +69 -0
- data/lib/musa-dsl/series/queue-serie.rb +94 -0
- data/lib/musa-dsl/series/series.rb +8 -0
- data/lib/musa-dsl/series.rb +1 -0
- data/lib/musa-dsl/transport/clock.rb +36 -0
- data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
- data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
- data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
- data/lib/musa-dsl/transport/timer-clock.rb +102 -0
- data/lib/musa-dsl/transport/timer.rb +40 -0
- data/lib/musa-dsl/transport/transport.rb +137 -0
- data/lib/musa-dsl/transport.rb +9 -0
- data/lib/musa-dsl.rb +17 -0
- data/musa-dsl.gemspec +17 -0
- 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
|