1use datatypes::*;
2
3peg::parser! {
4pub grammar abc() for str {
50 rule number() -> u32
51 = n:$(['1'..='9']['0'..='9']*) { n.parse().unwrap() }
52
53 rule space()
54 = [' ' | '\t']+
55
56 rule optional_space()
57 = [' ' | '\t']*
58
59 pub rule tune_book() -> TuneBook
60 = h:file_header()? ts:tune()* { TuneBook::new(h, ts) } /
61 ![_] { TuneBook::new(None, vec![]) }
62
63 pub rule file_header() -> FileHeader
64 = fields:info_field_any()* "\n" { FileHeader::new(fields) }
65
66 pub rule tune() -> Tune
67 = h:tune_header() b:tune_body()? { Tune::new(h, b) }
68
69 pub rule tune_header() -> TuneHeader
70 = "X:" optional_space() n:number() "\n"
71 t:info_field(<$("T")>)
72 extra:info_field_non_special()*
73 k:info_field(<$("K")>) {
74 let mut info = vec![InfoField::new('X', n.to_string()), t];
75 for field in extra.into_iter() { info.push(field); }
76 info.push(k);
77 TuneHeader::new(info)
78 }
79
80 rule info_field<'a>(n: rule<&'a str>) -> InfoField
81 = name:n() ":" optional_space() t:$((!"\n"[_])*) "\n" {
82 InfoField::new(
83 name.chars().next().unwrap(),
84 t.to_string()
85 )
86 }
87
88 rule info_field_any() -> InfoField
89 = info_field(<$(['A'..='Z' | 'a'..='z'])>)
90
91 rule info_field_non_special() -> InfoField
92 = info_field(<$(!['K' | 'X']['A'..='Z' | 'a'..='z'])>)
93
94 pub rule tune_body() -> TuneBody
95 = m:music_line()+ { TuneBody::new(m) } /
96 "\n" { TuneBody::new(vec![]) }
97
98 pub rule music_line() -> MusicLine
99 = s:music_symbol()+ music_line_end() { MusicLine::new(s) }
100
101 pub rule music_symbol() -> MusicSymbol
102 = n:note() "`"* { n } /
103 r:rest() { r } /
104 c:chord() { c } /
105 b:bar() { b } /
106 e:ending() { e } /
107 g:grace_notes() { g } /
108 t:tuplet() { t } /
109 space() { MusicSymbol::VisualBreak }
110
111 pub rule note() -> MusicSymbol
112 = d:decorations() a:accidental()? n:note_uppercase() o:octave()? l:length()? t:tie()? {
113 MusicSymbol::new_note(
114 d, a, n, o.unwrap_or(1), l.unwrap_or(1.0), t
115 )
116 } /
117 d:decorations() a:accidental()? n:note_lowercase() o:octave()? l:length()? t:tie()? {
118 MusicSymbol::new_note(
119 d, a, n, o.unwrap_or(1) + 1, l.unwrap_or(1.0), t
120 )
121 }
122
123 pub rule note_uppercase() -> Note
124 = "A" { Note::A } /
125 "B" { Note::B } /
126 "C" { Note::C } /
127 "D" { Note::D } /
128 "E" { Note::E } /
129 "F" { Note::F } /
130 "G" { Note::G }
131
132 pub rule note_lowercase() -> Note
133 = "a" { Note::A } /
134 "b" { Note::B } /
135 "c" { Note::C } /
136 "d" { Note::D } /
137 "e" { Note::E } /
138 "f" { Note::F } /
139 "g" { Note::G }
140
141 rule tie() -> Tie
142 = ".-" { Tie::Dotted } /
143 "-" { Tie::Solid }
144
145 pub rule bar() -> MusicSymbol
146 = b:$([':' | '|' | '[' | '\\' | ']']+) { MusicSymbol::Bar(b.to_string()) }
147
148 rule music_line_end()
149 = "\n" / ![_]
150
151 rule decorations() -> Vec<Decoration>
152 = decoration()*
153
154 rule decoration() -> Decoration
155 = d:decoration_symbol() space()? { d }
156
157 rule decoration_symbol() -> Decoration
158 = "." { Decoration::Staccato } /
159 "~" { Decoration::Roll } /
160 "H" { Decoration::Fermata } /
161 "L" { Decoration::Accent } /
162 "M" { Decoration::LowerMordent } /
163 "O" { Decoration::Coda } /
164 "P" { Decoration::UpperMordent } /
165 "S" { Decoration::Segno } /
166 "T" { Decoration::Trill } /
167 "u" { Decoration::UpBow } /
168 "v" { Decoration::DownBow } /
169 "!" d:$((!['\n' | '!'][_])+) "!" { Decoration::Unresolved(d.to_string()) }
170
171 rule accidental() -> Accidental
172 = "^^" { Accidental::DoubleSharp } /
173 "__" { Accidental::DoubleFlat } /
174 "^" { Accidental::Sharp } /
175 "_" { Accidental::Flat } /
176 "=" { Accidental::Natural }
177
178 rule octave() -> i8
179 = p:$([',' | '\'']+) {
180 let mut octave = 1;
181 for c in p.chars() {
182 match c {
183 ',' => octave -= 1,
184 '\'' => octave += 1,
185 _ => panic!("Parser malfunctioned. Unexpected octave identifier")
186 }
187 }
188 octave
189 }
190
191 rule length() -> f32
192 = "/" n:number() { 1.0 / (n as f32) } /
193 s:$("/"+) { 1.0 / (s.len() as f32).exp2() } /
194 n1:number() "/" n2:number() { (n1 as f32) / (n2 as f32) } /
195 n:number() { n as f32 }
196
197 pub rule rest() -> MusicSymbol
198 = "z" n:number()? { MusicSymbol::Rest(Rest::Note(n.unwrap_or(1))) } /
199 "Z" n:number()? { MusicSymbol::Rest(Rest::Measure(n.unwrap_or(1))) } /
200 "x" n:number()? { MusicSymbol::Rest(Rest::NoteHidden(n.unwrap_or(1))) } /
201 "X" n:number()? { MusicSymbol::Rest(Rest::MeasureHidden(n.unwrap_or(1))) }
202
203 pub rule ending() -> MusicSymbol
204 = "[" n:number() space()? { MusicSymbol::Ending(n) }
205
206 pub rule chord() -> MusicSymbol
207 = d:decorations() "[" n:note()+ "]" l:length()? {
208 MusicSymbol::Chord {
209 decorations: d,
210 notes: n,
211 length: l.unwrap_or(1f32)
212 }
213 }
214
215 pub rule grace_notes() -> MusicSymbol
216 = "{" a:"/"? n:note()* "}" {
217 MusicSymbol::GraceNotes {
218 acciaccatura: a,
219 notes: n
220 }
221 }
222
223 pub rule tuplet() -> MusicSymbol
224 = "(" p:number() space()? n:note()*<{ p as usize }> {?
225 MusicSymbol::tuplet_with_defaults(p, None, None, n)
226 } /
227 "(" p:number() ":" q:number()? ":" r:number()? space()? n:note()*<{ p as usize }> {?
228 MusicSymbol::tuplet_with_defaults(p, q, r, n)
229 } /
230 "(" p:number() ":" q:number() space()? n:note()*<{ p as usize }> {?
231 MusicSymbol::tuplet_with_defaults(p, Some(q), None, n)
232 }
233}}