Я пишу грамматику для компиляции файлов .abc. Это текстовые файлы, в которых каждая строка текста представляет собой музыкальный голос (инструмент, играющий несколько нот). В моей грамматике я использую построчную структуру текста для разбора одной строки за раз. Упрощенная грамматика выглядит следующим образом.
// Body
// spaces and tabs have explicit meaning in the body, don't automatically ignore them
abc_body ::= abc_line+;
abc_line ::= element+ end_of_line (lyric end_of_line)? | middle_of_body_field | comment;
element ::= note_element | rest_element | tuplet_element | barline | nth_repeat | space_or_tab;
// notes
note_element ::= note | chord;
note ::= pitch note_length?;
pitch ::= accidental? basenote octave?;
octave ::= "'"+ | ","+;
note_length ::= (digit+)? ("/" (digit+)?)?;
note_length_strict ::= digit+ "/" digit+;
// "^" is sharp, "_" is flat, and "=" is neutral
accidental ::= "^" | "^^" | "_" | "__" | "=";
basenote ::= "C" | "D" | "E" | "F" | "G" | "A" | "B" | "c" | "d" | "e" | "f" | "g" | "a" | "b";
// rests
rest_element ::= "z" note_length?;
// tuplets
tuplet_element ::= tuplet_spec note_element+;
tuplet_spec ::= "(" digit ;
// chords
chord ::= "[" note+ "]";
barline ::= "|" | "||" | "[|" | "|]" | ":|" | "|:";
nth_repeat ::= "[1" | "[2";
// A voice field might reappear in the middle of a piece
// to indicate the change of a voice
middle_of_body_field ::= field_voice;
lyric ::= "w:" lyrical_element*;
lyrical_element ::= " "+ | "-" | "_" | "*" | "~" | backslash_hyphen | "|" | lyric_text;
// lyric_text should be defined appropriately
lyric_text ::= [.]*;
backslash_hyphen ::= "\\" "-";
//backslash immediately followed by hyphen
// General
comment ::= space_or_tab* "%" comment_text newline;
//comment_text should be defined appropriately
comment_text ::= [.]*;
end_of_line ::= newline | comment;
digit ::= [0-9];
newline ::= "\n" | "\r" "\n"?;
space_or_tab ::= " " | "\t";
text ::= .*;
Но у меня есть проблема с этим подходом. Для любого действительного файла .abc я получаю сообщение об ошибке в последней строке файла. Парсер пытается сопоставить end_of_line, но встречает конец строки. Это означало бы, что после последнего раза нужно быть новой строкой. Любые предложения или обойти эту проблему?