Sunday, December 20, 2009

Got It!

I've now got a simple working ABC tune parser. (Well, working in at least so far as it passed all the tests I've thought up so far.) Once I cracked the whitespace issue, the remaining piece fell into shape quickly. Figuring out that \h and \v were useful for horizontal and vertical whitepsace also helped. Here's the grammar I'm using now:
use v6;

grammar ABC
{
regex header_field_name { \w }
regex header_field_data { \N* }
regex header_field { ^^ <header_field_name> ':' \s* <header_field_data> $$ }
regex header { [<header_field> \v]+ }

regex basenote { <[a..g]+[A..G]> }
regex octave { \'+ | \,+ }
regex accidental { '^' | '^^' | '_' | '__' | '=' }
regex pitch { <accidental>? <basenote> <octave>? }

regex tie { '-' }
regex note_length { [\d* ['/' \d*]? ] | '/' }
regex note { <pitch> <note_length>? <tie>? }

regex rest_type { <[x..z]> }
regex rest { <rest_type> <note_length>? }

regex gracing { '+' <alpha>+ '+' }

regex spacing { \h+ }

regex broken_rhythm_bracket { ['<'+ | '>'+] }
regex broken_rhythm { <note> <g1=gracing>* <broken_rhythm_bracket> <g2=gracing>* <note> }

regex element { <broken_rhythm> | <note> | <rest> | <gracing> | <spacing> }

regex barline { ':|:' | '|:' | '|' | ':|' | '::' }

regex bar { <element>+ <barline>? }

regex line_of_music { <barline>? <bar>+ }

regex music { [<line_of_music> \s*\v?]+ }

regex tune { <header> <music> }
}

This will successfully parse the sample ABC I gave in my first post on this topic.

Where to go from here? 1) I'd like to write a simple script that can put the grammar to work as is. I'm thinking maybe a script which can test if a tune is playable on a D/G accordion. 2) So far, the grammar only supports a subset of ABC. Off the top of my head, it doesn't support chords (either as labels above the music or as more than one notehead at once) and it doesn't support in-line key changes or time changes. I'm guessing these will be fairly easy to add. 3) I'd like to be able to map the parse to actual Perl 6 classes to make the ABCs easier to manipulate. 4) I'd like to be able to use those classes to write out ABCs.

So much to do!

No comments:

Post a Comment