From: David Kastrup Date: Thu, 16 Jan 2014 10:25:23 +0000 (+0100) Subject: Issue 3815: Parser: harmonize \lyricsto and \addlyrics arguments X-Git-Tag: release/2.19.2-1~19^2~1 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=940767af99f39411e3e519a75968be11d47e3083;p=lilypond.git Issue 3815: Parser: harmonize \lyricsto and \addlyrics arguments Previously, they allowed arbitrary music but since that required looking at lookahead tokens in the wrong mode, it led to strange errors like with lyr=\lyricsto A { } mus={c} when mus= was parsed as a single token in lyrics mode. Now both \addlyrics and \lyricsto accept merely the same kind of delimited argument list that \lyrics or \chords accept. Additionally, to preserve compatibility to a lot of examples, music identifiers like \mus are permitted as the argument to \lyricsto and \addlyrics. Since this requires a change in existing uses, this includes a convert-ly rule that removes redundant uses of \lyricmode and rearranges the combination with context starters such that \lyricsto in general is applied last, like \lyricmode would be. --- diff --git a/lily/parser.yy b/lily/parser.yy index 2a647c1ec6..ccc87218f2 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -2058,6 +2058,23 @@ optional_id: } ; +// We must not have lookahead tokens parsed in lyric mode. In order +// to save confusion, we take almost the same set as permitted with +// \lyricmode and/or \lyrics. However, music identifiers are also +// allowed, and they obviously do not require switching into lyrics +// mode for parsing. + +lyric_mode_music: + { + parser->lexer_->push_lyric_state (); + } grouped_music_list + { + parser->lexer_->pop_state (); + $$ = $2; + } + | MUSIC_IDENTIFIER + ; + complex_music: music_function_call | repeated_music { $$ = $1; } @@ -2170,20 +2187,11 @@ mode_changing_head_with_context: ; new_lyrics: - ADDLYRICS { parser->lexer_->push_lyric_state (); } - /*cont */ - composite_music { - /* Can also use music at the expensive of two S/Rs similar to - \repeat \alternative */ - parser->lexer_->pop_state (); - - $$ = scm_cons ($3, SCM_EOL); + ADDLYRICS lyric_mode_music { + $$ = scm_list_1 ($2); } - | new_lyrics ADDLYRICS { - parser->lexer_->push_lyric_state (); - } composite_music { - parser->lexer_->pop_state (); - $$ = scm_cons ($4, $1); + | new_lyrics ADDLYRICS lyric_mode_music { + $$ = scm_cons ($3, $1); } ; @@ -2191,11 +2199,8 @@ re_rhythmed_music: composite_music new_lyrics { $$ = MAKE_SYNTAX ("add-lyrics", @$, $1, scm_reverse_x ($2, SCM_EOL)); } %prec COMPOSITE - | LYRICSTO simple_string { - parser->lexer_->push_lyric_state (); - } music { - parser->lexer_->pop_state (); - $$ = MAKE_SYNTAX ("lyric-combine", @$, $2, $4); + | LYRICSTO simple_string lyric_mode_music { + $$ = MAKE_SYNTAX ("lyric-combine", @$, $2, $3); } ; diff --git a/python/convertrules.py b/python/convertrules.py index ec8bd266ef..bbafef4a3d 100644 --- a/python/convertrules.py +++ b/python/convertrules.py @@ -3698,6 +3698,19 @@ def conv (str): def conv (str): return str +@rule ((2, 19, 2), r"\lyricsto \new/\context/... -> \new/\context/... \lyricsto") +def conv (str): + word=r'(?:#?"[^"]*"|\b' + wordsyntax + r'\b)' + str = re.sub (r"(\\lyricsto\s*" + word + r"\s*)(\\(?:new|context)\s*" + word + + r"(?:\s*=\s*" + word + r")?\s*)", + r"\2\1", str) + str = re.sub (r"(\\lyricsto\s*" + word + r"\s*)\\lyricmode\b\s*", + r"\1", str) + str = re.sub (r"(\\lyricsto\s*" + word + r"\s*)\\lyrics\b\s*", + r"\\new Lyrics \1", str) + str = re.sub (r'\\lyricmode\s*(\\lyricsto\b)', r"\1", str) + return str + # Guidelines to write rules (please keep this at the end of this file) # # - keep at most one rule per version; if several conversions should be done,