%left PREC_BOT
%nonassoc REPEAT
%nonassoc ALTERNATIVE
-%left ADDLYRICS
-%left PREC_TOP
-
/* The above precedences tackle the shift/reduce problem
\repeat { \repeat } \alternative
*/
+%right FUNCTION_ARGUMENTS
+ MARKUP LYRICS_STRING MARKUP_IDENTIFIER STRING STRING_IDENTIFIER
+ SEQUENTIAL SIMULTANEOUS DOUBLE_ANGLE_OPEN MUSIC_IDENTIFIER '{'
+ PITCH_IDENTIFIER NOTENAME_PITCH TONICNAME_PITCH
+ SCM_FUNCTION SCM_IDENTIFIER SCM_TOKEN
+ UNSIGNED DURATION_IDENTIFIER
+
+ /* The above are the symbols that can start function arguments */
+
+%left ADDLYRICS
+%left PREC_TOP
+
+
+
%pure_parser
%locations
%token <i> EXPECT_DURATION "ly:duration?"
%token <i> EXPECT_SCM "scheme?"
%token <i> EXPECT_MARKUP_LIST "markup-list?"
+%token <scm> EXPECT_OPTIONAL "optional?"
/* After the last argument. */
%token <i> EXPECT_NO_MORE_ARGS;
%token <scm> PITCH_IDENTIFIER
%token <scm> DURATION_IDENTIFIER
%token <scm> EVENT_IDENTIFIER
+%token <scm> EVENT_FUNCTION
%token <scm> FRACTION
%token <scm> LYRICS_STRING
%token <scm> LYRIC_MARKUP_IDENTIFIER
%type <scm> braced_music_list
%type <scm> closed_music
%type <scm> music
-%type <scm> prefix_composite_music
+%type <scm> complex_music
+%type <scm> mode_changed_music
%type <scm> repeated_music
%type <scm> sequential_music
%type <scm> simple_music
%type <outputdef> output_def
%type <outputdef> paper_block
-%type <scm> generic_prefix_music_scm
+%type <scm> music_function_call
%type <scm> music_list
%type <scm> absolute_pitch
%type <scm> assignment_id
%type <scm> embedded_scm_closed
%type <scm> embedded_scm_chord_body
%type <scm> embedded_scm_event
+%type <scm> event_function_event
%type <scm> figure_list
%type <scm> figure_spec
%type <scm> fraction
%type <scm> full_markup
%type <scm> full_markup_list
%type <scm> function_arglist
+%type <scm> function_arglist_optional
+%type <scm> function_arglist_keep
%type <scm> function_arglist_bare
%type <scm> function_arglist_closed
+%type <scm> function_arglist_closed_optional
+%type <scm> function_arglist_closed_keep
%type <scm> identifier_init
%type <scm> lilypond
%type <scm> lilypond_header
| book_body lilypond_header {
$$->header_ = $2;
}
+ | book_body embedded_scm { }
| book_body error {
$$->paper_ = 0;
$$->scores_ = SCM_EOL;
| bookpart_body lilypond_header {
$$->header_ = $2;
}
+ | bookpart_body embedded_scm { }
| bookpart_body error {
$$->paper_ = 0;
$$->scores_ = SCM_EOL;
music:
simple_music
| composite_music
- | MUSIC_IDENTIFIER
;
;
composite_music:
- prefix_composite_music { $$ = $1; }
- | grouped_music_list { $$ = $1; }
+ complex_music
+ | closed_music
;
/* Music that can't be followed by additional events or durations */
closed_music:
- MUSIC_IDENTIFIER
+ mode_changed_music
+ | MUSIC_IDENTIFIER
| grouped_music_list
;
function_arglist:
function_arglist_bare
- | EXPECT_MUSIC function_arglist music {
+ | EXPECT_MUSIC function_arglist_optional music
+ {
+ $$ = scm_cons ($3, $2);
+ }
+ | EXPECT_SCM function_arglist_optional embedded_scm
+ {
$$ = scm_cons ($3, $2);
}
- | EXPECT_SCM function_arglist embedded_scm {
- $$ = scm_cons ($3, $2);
+ ;
+
+function_arglist_optional:
+ function_arglist_keep %prec FUNCTION_ARGUMENTS
+ | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ ;
+
+function_arglist_keep:
+ EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep full_markup {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep simple_string {
+ $$ = scm_cons ($4, $3);
+ }
+ | 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_keep simple_string
+ {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_keep closed_music
+ {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm
+ {
+ $$ = scm_cons ($4, $3);
+ }
+ | function_arglist
;
+
function_arglist_closed:
function_arglist_bare
- | EXPECT_MUSIC function_arglist closed_music {
+ | EXPECT_MUSIC function_arglist_optional closed_music
+ {
+ $$ = scm_cons ($3, $2);
+ }
+ | EXPECT_SCM function_arglist_optional embedded_scm_closed
+ {
$$ = scm_cons ($3, $2);
}
- | EXPECT_SCM function_arglist embedded_scm_closed {
- $$ = scm_cons ($3, $2);
+ ;
+
+function_arglist_closed_optional:
+ function_arglist_closed_keep %prec FUNCTION_ARGUMENTS
+ | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_closed_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_closed_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_closed_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_optional
+ {
+ $$ = scm_cons ($1, $3);
+ }
+ ;
+
+function_arglist_closed_keep:
+ EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep full_markup {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep simple_string {
+ $$ = scm_cons ($4, $3);
+ }
+ | 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_keep simple_string
+ {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_keep closed_music
+ {
+ $$ = scm_cons ($4, $3);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm_closed
+ {
+ $$ = scm_cons ($4, $3);
}
+ | function_arglist_closed
;
embedded_scm_closed:
function_arglist_bare:
EXPECT_NO_MORE_ARGS {
- /* This is for 0-ary functions, so they don't need to
- read a lookahead token */
$$ = SCM_EOL;
}
- | EXPECT_MARKUP function_arglist full_markup {
+ | EXPECT_MARKUP function_arglist_optional full_markup {
$$ = scm_cons ($3, $2);
}
- | EXPECT_MARKUP function_arglist simple_string {
+ | EXPECT_MARKUP function_arglist_optional simple_string {
$$ = scm_cons ($3, $2);
}
- | EXPECT_PITCH function_arglist pitch_also_in_chords {
- $$ = scm_cons ($3, $2);
+ | EXPECT_PITCH function_arglist_optional pitch_also_in_chords {
+ $$ = scm_cons ($3, $2);
}
- | EXPECT_DURATION function_arglist_closed duration_length {
- $$ = scm_cons ($3, $2);
+ | EXPECT_DURATION function_arglist_closed_optional duration_length {
+ $$ = scm_cons ($3, $2);
}
- | EXPECT_SCM function_arglist simple_string {
- $$ = scm_cons ($3, $2);
+ | EXPECT_SCM function_arglist_optional simple_string {
+ $$ = scm_cons ($3, $2);
}
;
-generic_prefix_music_scm:
+music_function_call:
MUSIC_FUNCTION function_arglist {
$$ = run_music_function (PARSER, @$,
$1, $2);
}
;
-
-prefix_composite_music:
- generic_prefix_music_scm
+complex_music:
+ music_function_call
| CONTEXT simple_string optional_id optional_context_mod music {
Context_mod *ctxmod = unsmob_context_mod ($4);
SCM mods = SCM_EOL;
$$ = MAKE_SYNTAX ("time-scaled-music", @$, $2, $3);
}
| repeated_music { $$ = $1; }
- | mode_changing_head grouped_music_list {
+ | relative_music { $$ = $1; }
+ | re_rhythmed_music { $$ = $1; }
+ ;
+
+mode_changed_music:
+ mode_changing_head grouped_music_list {
if ($1 == ly_symbol2scm ("chords"))
{
$$ = MAKE_SYNTAX ("unrelativable-music", @$, $2);
}
PARSER->lexer_->pop_state ();
}
- | relative_music { $$ = $1; }
- | re_rhythmed_music { $$ = $1; }
;
mode_changing_head:
| EXPECT_MUSIC music_function_chord_body_arglist chord_body_element {
$$ = scm_cons ($3, $2);
}
- | EXPECT_SCM function_arglist embedded_scm_chord_body {
+ | EXPECT_SCM function_arglist_optional embedded_scm_chord_body {
$$ = scm_cons ($3, $2);
}
;
| EXPECT_MUSIC music_function_event_arglist post_event {
$$ = scm_cons ($3, $2);
}
- | EXPECT_SCM function_arglist embedded_scm_event {
+ | EXPECT_SCM function_arglist_optional embedded_scm_event {
$$ = scm_cons ($3, $2);
}
;
}
;
+event_function_event:
+ EVENT_FUNCTION music_function_event_arglist {
+ $$ = run_music_function (PARSER, @$,
+ $1, $2);
+ }
+ ;
+
command_element:
command_event {
$$ = $1;
a->set_property ("tremolo-type", scm_from_int ($1));
$$ = a->unprotect ();
}
+ | event_function_event
;
direction_reqd_event:
args = scm_reverse_x (args, SCM_EOL);
+ SCM fallback = SCM_BOOL_F;
+ SCM pred = scm_car (sig);
+
+ if (scm_is_pair (pred))
+ {
+ fallback = scm_cdr (pred);
+ if (Music *m = unsmob_music (fallback)) {
+ m = m->clone ();
+ m->set_spot (loc);
+ fallback = m->unprotect ();
+ }
+ pred = scm_car (pred);
+ }
+
if (!to_boolean (scm_call_3 (type_check_proc, make_input (loc), scm_cdr (sig), args)))
{
parser->error_level_ = 1;
- return LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant ("void-music"), scm_list_2 (parser->self_scm (), make_input (loc)));
+ return fallback;
}
- SCM syntax_args = scm_list_5 (parser->self_scm (), make_input (loc), scm_car (sig), func, args);
+ SCM syntax_args = scm_list_n (parser->self_scm (), make_input (loc), pred, fallback, func, args, SCM_UNDEFINED);
return LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant ("music-function"), syntax_args);
}