+ complex_music
+ | music_bare
+ ;
+
+/* Music that can be parsed without lookahead */
+closed_music:
+ music_bare
+ | complex_music_prefix closed_music
+ {
+ $$ = FINISH_MAKE_SYNTAX ($1, @$, $2);
+ }
+ ;
+
+music_bare:
+ mode_changed_music
+ | MUSIC_IDENTIFIER
+ | grouped_music_list
+ ;
+
+grouped_music_list:
+ simultaneous_music { $$ = $1; }
+ | sequential_music { $$ = $1; }
+ ;
+
+/* An argument list. If a function \foo expects scm scm pitch, then the lexer expands \foo into the token sequence:
+ MUSIC_FUNCTION EXPECT_PITCH EXPECT_SCM EXPECT_SCM EXPECT_NO_MORE_ARGS
+and this rule returns the reversed list of arguments. */
+
+function_arglist_skip:
+ function_arglist_common
+ | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_skip
+ {
+ $$ = scm_cons ($1, $3);
+ } %prec FUNCTION_ARGLIST
+ | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_skip
+ {
+ $$ = scm_cons ($1, $3);
+ } %prec FUNCTION_ARGLIST
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip
+ {
+ $$ = scm_cons ($1, $3);
+ } %prec FUNCTION_ARGLIST
+ ;
+
+
+function_arglist_nonbackup_common:
+ EXPECT_OPTIONAL EXPECT_PITCH function_arglist pitch_also_in_chords {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed duration_length {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed FRACTION
+ {
+ $$ = check_scheme_arg (parser, @4, $4, $3, $2);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed post_event_nofinger
+ {
+ $$ = check_scheme_arg (parser, @4, $4, $3, $2);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed '-' UNSIGNED
+ {
+ SCM n = scm_difference ($5, SCM_UNDEFINED);
+ if (scm_is_true (scm_call_1 ($2, n)))
+ $$ = scm_cons (n, $3);
+ else {
+ Music *t = MY_MAKE_MUSIC ("FingeringEvent", @5);
+ t->set_property ("digit", $5);
+ $$ = t->unprotect ();
+ if (scm_is_true (scm_call_1 ($2, $$)))
+ $$ = scm_cons ($$, $3);
+ else
+ $$ = check_scheme_arg (parser, @4, n, $3, $2);
+ }
+
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed '-' REAL
+ {
+ $$ = check_scheme_arg (parser, @4,
+ scm_difference ($5, SCM_UNDEFINED),
+ $3, $2);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed '-' NUMBER_IDENTIFIER
+ {
+ $$ = check_scheme_arg (parser, @4,
+ scm_difference ($5, SCM_UNDEFINED),
+ $3, $2);
+ }
+ ;
+
+function_arglist_closed_nonbackup:
+ function_arglist_nonbackup_common
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist embedded_scm_arg_closed
+ {
+ $$ = check_scheme_arg (parser, @4, $4, $3, $2);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed bare_number_closed
+ {
+ $$ = check_scheme_arg (parser, @4, $4, $3, $2);
+ }
+ ;
+
+function_arglist_nonbackup:
+ function_arglist_nonbackup_common
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist embedded_scm_arg
+ {
+ $$ = check_scheme_arg (parser, @4, $4, $3, $2);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed bare_number
+ {
+ $$ = check_scheme_arg (parser, @4, $4, $3, $2);
+ }
+ ;
+
+function_arglist_keep:
+ function_arglist_common
+ | function_arglist_backup
+ ;
+
+function_arglist_closed_keep:
+ function_arglist_closed_common
+ | function_arglist_backup
+ ;
+
+function_arglist_backup:
+ EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm_arg_closed
+ {
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = scm_cons ($4, $3);
+ } else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (SCM_IDENTIFIER, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep post_event_nofinger
+ {
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = scm_cons ($4, $3);
+ } else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (EVENT_IDENTIFIER, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep lyric_element
+ {
+ // There is no point interpreting a lyrics string as
+ // an event, since we don't allow music possibly
+ // followed by durations or postevent into closed
+ // music, and we only accept closed music in optional
+ // arguments at the moment. If this changes, more
+ // complex schemes might become interesting here as
+ // well: see how we do this at the mandatory argument
+ // point.
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ $$ = scm_cons ($4, $3);
+ else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (LYRICS_STRING, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep UNSIGNED
+ {
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = $3;
+ MYREPARSE (@4, $2, UNSIGNED, $4);
+ } else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (UNSIGNED, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep REAL
+ {
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = $3;
+ MYREPARSE (@4, $2, REAL, $4);
+ } else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (REAL, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep NUMBER_IDENTIFIER
+ {
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = scm_cons ($4, $3);
+ } else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (NUMBER_IDENTIFIER, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep FRACTION
+ {
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = scm_cons ($4, $3);
+ } else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (FRACTION, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep '-' UNSIGNED
+ {
+ SCM n = scm_difference ($5, SCM_UNDEFINED);
+ if (scm_is_true (scm_call_1 ($2, n))) {
+ $$ = $3;
+ MYREPARSE (@5, $2, REAL, n);
+ } else {
+ Music *t = MY_MAKE_MUSIC ("FingeringEvent", @5);
+ t->set_property ("digit", $5);
+ $$ = t->unprotect ();
+ if (scm_is_true (scm_call_1 ($2, $$)))
+ $$ = scm_cons ($$, $3);
+ else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
+ MYBACKUP (UNSIGNED, $5, @5);
+ parser->lexer_->push_extra_token ('-');
+ }
+ }
+
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep '-' REAL
+ {
+ SCM n = scm_difference ($5, SCM_UNDEFINED);
+ if (scm_is_true (scm_call_1 ($2, n))) {
+ MYREPARSE (@5, $2, REAL, n);
+ $$ = $3;
+ } else {
+ MYBACKUP (REAL, n, @5);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep '-' NUMBER_IDENTIFIER
+ {
+ SCM n = scm_difference ($5, SCM_UNDEFINED);
+ if (scm_is_true (scm_call_1 ($2, n))) {
+ $$ = scm_cons (n, $3);
+ } else {
+ MYBACKUP (NUMBER_IDENTIFIER, n, @5);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_keep pitch_also_in_chords
+ {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_keep duration_length
+ {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup BACKUP
+ {
+ $$ = scm_cons ($1, $3);
+ MYBACKUP(0, SCM_UNDEFINED, @3);
+ }
+ | function_arglist_backup REPARSE embedded_scm_arg_closed
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ | function_arglist_backup REPARSE bare_number
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ ;
+
+function_arglist:
+ function_arglist_common
+ | function_arglist_nonbackup
+ ;
+
+function_arglist_common:
+ function_arglist_bare
+ | EXPECT_SCM function_arglist_optional embedded_scm_arg
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $2, $1);
+ }
+ | EXPECT_SCM function_arglist_closed_optional bare_number
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $2, $1);
+ }
+ | EXPECT_SCM function_arglist_closed_optional FRACTION
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $2, $1);
+ }
+ | EXPECT_SCM function_arglist_closed_optional post_event_nofinger
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $2, $1);
+ }
+ | function_arglist_common_minus
+ | function_arglist_common_lyric
+ ;
+
+function_arglist_common_lyric:
+ EXPECT_SCM function_arglist_optional lyric_element
+ {
+ // We check how the predicate thinks about a lyrics
+ // event or about a markup. If it accepts neither, we
+ // backup the original token. Otherwise we commit to
+ // taking the token. Depending on what the predicate
+ // is willing to accept, we interpret as a string, as
+ // a lyric event, or ambiguously (meaning that if
+ // something looking like a duration or post event
+ // follows, we take the event, otherwise the string).
+ SCM lyric_event = MAKE_SYNTAX ("lyric-event", @3, $3,
+ parser->default_duration_.smobbed_copy ());
+ if (scm_is_true (scm_call_1 ($1, $3)))
+ if (scm_is_true (scm_call_1 ($1, lyric_event)))
+ {
+ $$ = $2;
+ MYREPARSE (@3, $1, LYRICS_STRING, $3);
+ } else {
+ $$ = scm_cons ($3, $2);
+ }
+ else if (scm_is_true (scm_call_1 ($1, lyric_event)))
+ {
+ $$ = $2;
+ MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
+ } else {
+ // This is going to flag a syntax error, we
+ // know the predicate to be false.
+ check_scheme_arg (parser, @3,
+ $3, $2, $1);
+ }
+ }
+ | function_arglist_common_lyric REPARSE lyric_element_arg
+ {
+ // This should never be false
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ ;
+
+function_arglist_common_minus:
+ EXPECT_SCM function_arglist_closed_optional '-' UNSIGNED
+ {
+ SCM n = scm_difference ($4, SCM_UNDEFINED);
+ if (scm_is_true (scm_call_1 ($1, n))) {
+ $$ = $2;
+ MYREPARSE (@4, $1, REAL, n);
+ } else {
+ Music *t = MY_MAKE_MUSIC ("FingeringEvent", @4);
+ t->set_property ("digit", $4);
+ $$ = t->unprotect ();
+ if (scm_is_true (scm_call_1 ($1, $$)))
+ $$ = scm_cons ($$, $2);
+ else
+ $$ = check_scheme_arg (parser, @3, n, $2, $1);
+ }
+
+ }
+ | EXPECT_SCM function_arglist_closed_optional '-' REAL
+ {
+ $$ = $2;
+ SCM n = scm_difference ($4, SCM_UNDEFINED);
+ MYREPARSE (@4, $1, REAL, n);
+ }
+ | EXPECT_SCM function_arglist_closed_optional '-' NUMBER_IDENTIFIER
+ {
+ SCM n = scm_difference ($4, SCM_UNDEFINED);
+ $$ = check_scheme_arg (parser, @4, n, $2, $1);
+ }
+ | function_arglist_common_minus REPARSE bare_number
+ {
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
+ }