Reviewers: lemzwerg, Carl,

Message:
On 2020/02/11 22:37:39, Carl wrote:
> On 2020/02/11 21:46:52, lemzwerg wrote:
> > Good idea!  From inspection only, LGTM.
> 
> Sounds like a great idea!
> 
> Carl

Well, I sort of got a feature request. 
<https://music.stackexchange.com/questions/95259/lilypond-bug-with-octave-change-whole-note>

Description:
Special-case syntax error of duration before octave marks

A somewhat common note-entry error is to write something like c4''
that is (judging from my own experience) not even unusual for
experienced users to fall victim to occasionally.  So make a special
parser rule that deals "correctly" with that entry and delivers a more
helpful error message than the parser would muster on its own.

Please review this at https://codereview.appspot.com/557410043/

Affected files (+44, -0 lines):
  M lily/parser.yy


Index: lily/parser.yy
diff --git a/lily/parser.yy b/lily/parser.yy
index 
89511c5d9d67a8091cbf9e043d9b99def124be58..78f0269a55a4cb5999525b2d54c4aa03fdb2ea05
 100644
--- a/lily/parser.yy
+++ b/lily/parser.yy
@@ -3294,6 +3294,11 @@ quotes:
         | sup_quotes
         ;
 
+stray_quotes:
+       sub_quotes
+       | sup_quotes
+       ;
+
 sup_quotes:
        '\'' {
                $$ = scm_from_int (1);
@@ -3661,6 +3666,45 @@ pitch_or_music:
                        $$ = n->unprotect ();
                }
        } %prec ':'
+       // Next rule is a frequent note entry error, like c4''
+       //
+       // It is quite unlikely that an octave check precedes a
+       // duration, but we have to keep it in the rule in order not
+       // to force the parser into early decisions before actually
+       // seeing a stray quote.  So we try to best interpret that
+       // case as well, even though it's not a likely error case.
+       | pitch exclamations questions octave_check duration stray_quotes 
optional_rest post_events {
+               if (!parser->lexer_->is_note_state ())
+                       parser->parser_error (@1, _ ("have to be in Note mode 
for notes"));
+               {
+                       Music *n = 0;
+                       if (scm_is_true ($7))
+                               n = MY_MAKE_MUSIC ("RestEvent", @$);
+                       else
+                               n = MY_MAKE_MUSIC ("NoteEvent", @$);
+
+                       if (scm_is_number ($4))
+                       {
+                               int q = scm_to_int ($4) + scm_to_int ($6);
+                               n->set_property ("absolute-octave", 
scm_from_int (q-1));
+                       } else
+                               $1 = unsmob<Pitch> ($1)->transposed
+                                       (Pitch (scm_to_int ($6), 
0)).smobbed_copy ();
+
+                       n->set_property ("pitch", $1);
+                       n->set_property ("duration", $5);
+
+                       if (to_boolean ($3))
+                               n->set_property ("cautionary", SCM_BOOL_T);
+                       if (to_boolean ($2) || to_boolean ($3))
+                               n->set_property ("force-accidental", 
SCM_BOOL_T);
+                       if (scm_is_pair ($8))
+                               n->set_property ("articulations",
+                                                scm_reverse_x ($8, SCM_EOL));
+                       $$ = n->unprotect ();
+               }
+               parser->parser_error (@6, _ ("octave marks must precede 
duration"));
+       } %prec ':'
        | new_chord post_events {
                if (!parser->lexer_->is_chord_state ())
                         parser->parser_error (@1, _ ("have to be in Chord mode 
for chords"));



Reply via email to