Ошибка синтаксического анализатора Regex в конце строки - PullRequest
0 голосов
/ 09 мая 2018

Я пишу грамматику для компиляции файлов .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, но встречает конец строки. Это означало бы, что после последнего раза нужно быть новой строкой. Любые предложения или обойти эту проблему?

1 Ответ

0 голосов
/ 10 мая 2018

Один из подходов состоит в том, чтобы реорганизовать грамматику (то есть без изменения языка), чтобы отделить окончательный newline от abc_line, то есть до такой степени, что вы можете написать

abc_line ::= abc_line_content newline

Затем измените:

abc_body ::= abc_line+

до:

abc_body ::= abc_line_content (newline abc_line_content)*

(при необходимости добавляя newline?, т. Е. Если в некоторых файлах do есть символ новой строки в конце последней строки).

...