extern crate peg;
peg::parser!{
pub grammar hum_grammar() for str {
pub rule score() -> Vec<(String, String)>
= commands:command()* {
commands
}
rule command() -> (String, String)
= comment()
/ tempo()
/ time()
/ checkpoint()
/ voice()
/ measure()
/ reset()
/ note()
rule comment() -> (String, String)
= ws()* "~" text:$((!['\n'][_])*) eol() {
("comment".to_string(), text.trim().to_string())
}
rule tempo() -> (String, String)
= ws()* "[" ws()* text:$(number()) "_bpm" ws()* "]" ws()* {
("tempo".to_string(), text.to_string())
}
rule time() -> (String, String)
= ws()* "[" ws()* text:$(fraction()) ws()* "]" ws()* {
("time".to_string(), text.to_string())
}
rule checkpoint() -> (String, String)
= ws()* "*"+ ws()* {
("checkpoint".to_string(), "(。^‿^。)".to_string())
}
rule voice() -> (String, String)
= ws()* "%" ws()* text:$(name()) ws()* {
("voice".to_string(), text.to_string())
}
rule measure() -> (String, String)
= ws()* "|" ws()* {
("measure".to_string(), "(。 ̄▽ ̄。)θ~♪♪".to_string())
}
rule reset() -> (String, String)
= ws()* ";" ws_not_newline()* (!['\n'][_])* eol() {
("reset".to_string(), "ヽ(。^▽^。)ノ".to_string())
}
rule note() -> (String, String)
= ws()*
"(" ws()* note_name:$(name()) ws()+ length:$(fraction()) ws()* ")"
dots:$("+"*) ws()* {
(note_name.to_string(), format!("{}{}", length, dots).to_string())
}
rule name()
= ['a'..='z' | 'A'..='Z' | '0'..='9' | '_']+
rule fraction()
= ['0'..='9' | '/']+
rule number()
= ['0'..='9']+
rule ws()
= " "
/ "-" / "\t"
/ "\r"
/ "\n"
rule eol()
= "\n"
/ ![_]
rule ws_not_newline()
= " "
/ "-" / "\t"
/ "\r"
}
}