Skip to content

Commit

Permalink
Do not fail parsing on unsupported directives
Browse files Browse the repository at this point in the history
  • Loading branch information
José Luis C.D. committed Oct 19, 2024
1 parent 62e6166 commit 7b0a1c0
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 26 deletions.
10 changes: 4 additions & 6 deletions src/grammar/chordpro.pest
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,11 @@ directive_args_chords = _{ ":" ~ args_chords }
start_chorus = _{ start_directive ~ ("start_of_chorus"|"soc") ~ directive_args? ~ end_directive ~ NEWLINE? }
end_chorus = _{ start_directive ~ ("end_of_chorus"|"eoc") ~ end_directive ~ NEWLINE? }

title = { start_directive ~ ("title"|"t") ~ directive_args ~ end_directive ~ NEWLINE? }
artist = { start_directive ~ "artist" ~ directive_args ~ end_directive ~ NEWLINE? }
capo = { start_directive ~ "capo" ~ directive_args ~ end_directive ~ NEWLINE? }
directive_name = {(!(end_directive | ":") ~ ANY)* }
directive = { start_directive ~ directive_name ~ directive_args_chords? ~ end_directive ~ NEWLINE? }

comment = { start_directive ~ ("comment"|"c") ~ directive_args_chords ~ end_directive ~ NEWLINE? }

meta = { title | artist | capo }
comment = { start_directive ~ ("comment"|"c") ~ directive_args_chords ~ end_directive ~ NEWLINE? }

// Lyrics
text = ${ (!(start_chord | end_chord | start_directive | end_directive | NEWLINE) ~ ANY)+ }
Expand All @@ -51,4 +49,4 @@ text = ${ (!(start_chord | end_chord | start_directive | end_directive | NEWLINE
chorus = {start_chorus ~ (paragraph | NEWLINE)* ~ end_chorus }

section = { chorus | comment | paragraph }
chordpro = { SOI ~ (meta | section | NEWLINE)* ~ EOI }
chordpro = { SOI ~ (section | directive | NEWLINE)* ~ EOI }
90 changes: 70 additions & 20 deletions src/songparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,24 +185,31 @@ impl<'a> FromPair<'a> for Section {
}

impl Song {
fn parse_meta<'a, 'b>(&'b mut self, pairs: Pairs<'a, Rule>) {
let pair = pairs.peek().unwrap();
match pair.as_rule() {
Rule::title => {
self.title = pair.into_inner().peek().unwrap().as_str().to_owned();
}
Rule::artist => {
self.artist = pair.into_inner().peek().unwrap().as_str().to_owned();
}
Rule::capo => {
let capo_str = pair.into_inner().peek().unwrap().as_str();
if let Ok(capo) = u8::from_str(capo_str) {
self.capo = capo;
} else {
self.capo = 100;
fn parse_directive<'a, 'b>(&'b mut self, mut pairs: Pairs<'a, Rule>) {
let name = pairs.next();
let data = pairs.next();

if let Some(name) = name {
if name.as_rule() == Rule::directive_name {
match name.as_str() {
"title" => {
self.title = data.map(|x| x.as_str()).unwrap_or("").to_owned();
},
"artist" => {
self.artist = data.map(|x| x.as_str()).unwrap_or("").to_owned();
},
"capo" => {
let capo_str = data.map(|x| x.as_str()).unwrap_or("");

if let Ok(capo) = u8::from_str(capo_str) {
self.capo = capo;
} else {
self.capo = 0;
}
}
_ => {}
}
}
_ => {}
}
}
}
Expand All @@ -214,8 +221,8 @@ impl HasRule for Song {
impl<'a> ProcessChild<'a> for Song {
fn process_child(&mut self, pair: Pair<'a, Rule>) {
match pair.as_rule() {
Rule::meta => {
self.parse_meta(pair.into_inner());
Rule::directive => {
self.parse_directive(pair.into_inner());
}
Rule::section => {
self.song.push(Section::from_pair(pair));
Expand Down Expand Up @@ -319,11 +326,24 @@ mod tests {
})
}

#[test]
fn test_comment_parse() {
parse_test!( Section {
r#"{comment: This is a comment [Am]}"#
=>
Section::Comment(
Line(vec![
Chunk::Lyrics("This is a comment ".to_string()),
Chunk::Chord(chord!("Am")),
]),
)
})
}

#[test]
fn test_song_parse() {
parse_test!( Song {
r#"
{title: Wish You Were Here}
r#"{title: Wish You Were Here}
{artist: Pink Floyd}
{soc}
Expand Down Expand Up @@ -353,6 +373,36 @@ mod tests {
})
}

#[test]
fn test_unknown_directive() {
parse_test!( Song {
r#"{directive not known}
{other: directive not known}
[C]How I wish, how I wish you were [D]here
We're just [Am]two lost souls swimming in a fish bowl,[G] year after year"#
=> Song{
title: "".to_string(),
artist: "".to_string(),
capo: 0,
song: vec![Section::Verse(Paragraph(vec![
Line(vec![
Chunk::Chord(chord!("C")),
Chunk::Lyrics("How I wish, how I wish you were ".to_string()),
Chunk::Chord(chord!("D")),
Chunk::Lyrics("here".to_string())
]),
Line(vec![
Chunk::Lyrics("We're just ".to_string()),
Chunk::Chord(chord!("Am")),
Chunk::Lyrics("two lost souls swimming in a fish bowl,".to_string()),
Chunk::Chord(chord!("G")),
Chunk::Lyrics(" year after year".to_string())
])
]))]
}
})
}

#[test]
fn test_chord() {
parse_test!( Chord {
Expand Down

0 comments on commit 7b0a1c0

Please sign in to comment.