X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fparser.yy;h=33f5b983283b0c7dc916c766e30ceac848609853;hb=3d456562eb14c3dc8515038a25a2dde24b2486b8;hp=ee499ac15c7db5b0cdedc1828bf02f6bc196d90d;hpb=dc1b858539d92d2d08ac7c7c5be2d708222495d9;p=lilypond.git diff --git a/lily/parser.yy b/lily/parser.yy index ee499ac15c..33f5b98328 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -332,7 +332,6 @@ If we give names, Bison complains. %token BOOK_IDENTIFIER %token CHORD_MODIFIER %token CHORD_REPETITION -%token CONTEXT_DEF_IDENTIFIER %token CONTEXT_MOD_IDENTIFIER %token DRUM_PITCH %token PITCH_IDENTIFIER @@ -349,7 +348,6 @@ If we give names, Bison complains. %token MUSIC_IDENTIFIER %token NOTENAME_PITCH %token NUMBER_IDENTIFIER -%token OUTPUT_DEF_IDENTIFIER %token REAL %token RESTNAME %token SCM_ARG @@ -450,6 +448,17 @@ toplevel_expression: { SCM proc = parser->lexer_->lookup_identifier ("toplevel-score-handler"); scm_call_2 (proc, parser->self_scm (), $1); + } else if (Output_def * od = unsmob_output_def ($1)) { + SCM id = SCM_EOL; + + if (od->c_variable ("is-paper") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultpaper"); + else if (od->c_variable ("is-midi") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultmidi"); + else if (od->c_variable ("is-layout") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultlayout"); + + parser->lexer_->set_identifier (id, $1); } else if (!scm_is_eq ($1, SCM_UNSPECIFIED)) parser->parser_error (@1, _("bad expression type")); } @@ -676,9 +685,14 @@ identifier_init_nonumber: context_def_spec_block: CONTEXT '{' context_def_spec_body '}' - { + { $$ = $3; - unsmob_context_def ($$)->origin ()->set_spot (@$); + Context_def *td = unsmob_context_def ($$); + if (!td) { + $$ = Context_def::make_scm (); + td = unsmob_context_def ($$); + } + td->origin ()->set_spot (@$); } ; @@ -696,47 +710,54 @@ context_mod_arg: } ; -context_mod_embedded: - context_mod_arg - { - if (unsmob_music ($1)) { - SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler"); - $1 = scm_call_2 (proc, parser->self_scm (), $1); - } - if (unsmob_context_mod ($1)) - $$ = $1; - else { - parser->parser_error (@1, _ ("not a context mod")); - $$ = Context_mod ().smobbed_copy (); - } - } - ; - context_def_spec_body: /**/ { - $$ = Context_def::make_scm (); - } - | CONTEXT_DEF_IDENTIFIER { - $$ = $1; + $$ = SCM_UNSPECIFIED; } | context_def_spec_body context_mod { - if (!SCM_UNBNDP ($2)) + if (!SCM_UNBNDP ($2)) { + Context_def *td = unsmob_context_def ($$); + if (!td) { + $$ = Context_def::make_scm (); + td = unsmob_context_def ($$); + } unsmob_context_def ($$)->add_context_mod ($2); + } } | context_def_spec_body context_modification { Context_def *td = unsmob_context_def ($$); + if (!td) { + $$ = Context_def::make_scm (); + td = unsmob_context_def ($$); + } SCM new_mods = unsmob_context_mod ($2)->get_mods (); for (SCM m = new_mods; scm_is_pair (m); m = scm_cdr (m)) { td->add_context_mod (scm_car (m)); } } - | context_def_spec_body context_mod_embedded { - Context_def *td = unsmob_context_def ($$); - SCM new_mods = unsmob_context_mod ($2)->get_mods (); - for (SCM m = new_mods; scm_is_pair (m); m = scm_cdr (m)) { - td->add_context_mod (scm_car (m)); - } + | context_def_spec_body context_mod_arg { + Context_def *td = unsmob_context_def ($1); + if (scm_is_eq ($2, SCM_UNSPECIFIED)) + ; + else if (!td && unsmob_context_def ($2)) + $$ = $2; + else { + if (!td) { + $$ = Context_def::make_scm (); + td = unsmob_context_def ($$); + } + if (unsmob_music ($2)) { + SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler"); + $2 = scm_call_2 (proc, parser->self_scm (), $2); + } + if (Context_mod *cm = unsmob_context_mod ($2)) { + for (SCM m = cm->get_mods (); scm_is_pair (m); m = scm_cdr (m)) { + td->add_context_mod (scm_car (m)); + } + } else + parser->parser_error (@2, _ ("not a context mod")); + } } ; @@ -811,6 +832,17 @@ book_body: { SCM proc = parser->lexer_->lookup_identifier ("book-score-handler"); scm_call_2 (proc, $1, $2); + } else if (Output_def *od = unsmob_output_def ($2)) { + SCM id = SCM_EOL; + + if (od->c_variable ("is-paper") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultpaper"); + else if (od->c_variable ("is-midi") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultmidi"); + else if (od->c_variable ("is-layout") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultlayout"); + + parser->lexer_->set_identifier (id, $2); } else if (!scm_is_eq ($2, SCM_UNSPECIFIED)) parser->parser_error (@2, _("bad expression type")); } @@ -881,6 +913,17 @@ bookpart_body: { SCM proc = parser->lexer_->lookup_identifier ("bookpart-score-handler"); scm_call_2 (proc, $1, $2); + } else if (Output_def *od = unsmob_output_def ($2)) { + SCM id = SCM_EOL; + + if (od->c_variable ("is-paper") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultpaper"); + else if (od->c_variable ("is-midi") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultmidi"); + else if (od->c_variable ("is-layout") == SCM_BOOL_T) + id = ly_symbol2scm ("$defaultlayout"); + + parser->lexer_->set_identifier (id, $2); } else if (!scm_is_eq ($2, SCM_UNSPECIFIED)) parser->parser_error (@2, _("bad expression type")); } @@ -905,86 +948,98 @@ score_block: } ; -score_headers: - /* empty */ - { - $$ = SCM_EOL; - } - | score_headers - { - if (!scm_is_pair ($1) - || !ly_is_module (scm_car ($1))) - $1 = scm_cons (ly_make_module (false), $1); - parser->lexer_->add_scope (scm_car ($1)); - } lilypond_header - { - $$ = $1; - } - | score_headers output_def - { - Output_def *od = unsmob_output_def ($2); - if (od->lookup_variable (ly_symbol2scm ("is-paper")) == SCM_BOOL_T) - { - parser->parser_error (@2, _("\\paper cannot be used in \\score, use \\layout instead")); - - } - else - { +score_body: + score_items { + if (!unsmob_score ($1)) { + parser->parser_error (@1, _("Missing music in \\score")); + $$ = (new Score)->unprotect (); if (scm_is_pair ($1) && ly_is_module (scm_car ($1))) - scm_set_cdr_x ($1, scm_cons ($2, scm_cdr ($1))); - else - $$ = scm_cons ($2, $1); + { + unsmob_score ($$)->set_header (scm_car ($1)); + $1 = scm_cdr ($1); + } + for (SCM p = scm_reverse_x ($1, SCM_EOL); + scm_is_pair (p); p = scm_cdr (p)) + { + unsmob_score ($$)-> + add_output_def (unsmob_output_def (scm_car (p))); + } } } + | score_body error { + unsmob_score ($$)->error_found_ = true; + } ; - - -score_body: - score_headers music { - SCM scorify = ly_lily_module_constant ("scorify-music"); - $$ = scm_call_2 (scorify, $2, parser->self_scm ()); +score_item: + embedded_scm + | music + | output_def + ; - if (scm_is_pair ($1) && ly_is_module (scm_car ($1))) - { - unsmob_score ($$)->set_header (scm_car ($1)); - $1 = scm_cdr ($1); - } - for (SCM p = scm_reverse_x ($1, SCM_EOL); - scm_is_pair (p); p = scm_cdr (p)) - { - unsmob_score ($$)-> - add_output_def (unsmob_output_def (scm_car (p))); - } - } - | embedded_scm_active { - if (!unsmob_score ($1)) - { - $$ = (new Score)->unprotect (); - parser->parser_error (@1, _("score expected")); - } +score_items: + /* empty */ + { + $$ = SCM_EOL; } - | score_body + | score_items score_item { - Score *score = unsmob_score ($1); - if (!ly_is_module (score->get_header ())) - score->set_header (ly_make_module (false)); - parser->lexer_->add_scope (score->get_header ()); - } lilypond_header - | score_body output_def { - Output_def *od = unsmob_output_def ($2); - if (od->lookup_variable (ly_symbol2scm ("is-paper")) == SCM_BOOL_T) - { - parser->parser_error (@2, _("\\paper cannot be used in \\score, use \\layout instead")); - + Output_def *od = unsmob_output_def ($2); + if (od) { + if (od->lookup_variable (ly_symbol2scm ("is-paper")) == SCM_BOOL_T) + { + parser->parser_error (@2, _("\\paper cannot be used in \\score, use \\layout instead")); + od = 0; + $2 = SCM_UNSPECIFIED; + } + } else if (!unsmob_score ($$)) { + if (unsmob_music ($2)) { + SCM scorify = ly_lily_module_constant ("scorify-music"); + $2 = scm_call_2 (scorify, $2, parser->self_scm ()); + } + if (unsmob_score ($2)) + { + $$ = $2; + $2 = SCM_UNSPECIFIED; + } } - else - { - unsmob_score ($1)->add_output_def (od); + Score *score = unsmob_score ($$); + if (score && scm_is_pair ($1)) { + if (ly_is_module (scm_car ($1))) + { + score->set_header (scm_car ($1)); + $1 = scm_cdr ($1); + } + for (SCM p = scm_reverse_x ($1, SCM_EOL); + scm_is_pair (p); p = scm_cdr (p)) + { + score->add_output_def (unsmob_output_def (scm_car (p))); + } } + if (od) { + if (score) + score->add_output_def (od); + else if (scm_is_pair ($$) && ly_is_module (scm_car ($$))) + scm_set_cdr_x ($$, scm_cons ($2, scm_cdr ($$))); + else + $$ = scm_cons ($2, $$); + } else if (!scm_is_eq ($2, SCM_UNSPECIFIED)) + parser->parser_error (@2, _("Spurious expression in \\score")); } - | score_body error { - unsmob_score ($$)->error_found_ = true; + | score_items + { + if (Score *score = unsmob_score ($1)) { + if (!ly_is_module (score->get_header ())) + score->set_header (ly_make_module (false)); + parser->lexer_->add_scope (score->get_header ()); + } else { + if (!scm_is_pair ($1) || !ly_is_module (scm_car ($1))) + $1 = scm_cons (ly_make_module (false), $1); + parser->lexer_->add_scope (scm_car ($1)); + } + } lilypond_header + { + $$ = $1; } ; @@ -1008,7 +1063,8 @@ paper_block: output_def: output_def_body '}' { - $$ = $1; + if (scm_is_pair ($1)) + $$ = scm_car ($1); parser->lexer_->remove_scope (); parser->lexer_->pop_state (); @@ -1054,24 +1110,56 @@ music_or_context_def: output_def_body: output_def_head_with_mode_switch '{' { - $$ = $1; - unsmob_output_def ($$)->input_origin_.set_spot (@$); - } - | output_def_head_with_mode_switch '{' OUTPUT_DEF_IDENTIFIER { - Output_def *o = unsmob_output_def ($3); - o->input_origin_.set_spot (@$); - $$ = o->self_scm (); - parser->lexer_->remove_scope (); - parser->lexer_->add_scope (o->scope_); + unsmob_output_def ($1)->input_origin_.set_spot (@$); + // This is a stupid trick to mark the beginning of the + // body for deciding whether to allow + // embedded_scm_active to have an output definition + $$ = scm_list_1 ($1); } | output_def_body assignment { - + if (scm_is_pair ($1)) + $$ = scm_car ($1); } - | output_def_body embedded_scm { - + | output_def_body embedded_scm_active + { + // We don't switch into note mode for Scheme functions + // here. Does not seem warranted/required in output + // definitions. + if (scm_is_pair ($1)) + { + Output_def *o = unsmob_output_def ($2); + if (o) { + o->input_origin_.set_spot (@$); + $1 = o->self_scm (); + parser->lexer_->remove_scope (); + parser->lexer_->add_scope (o->scope_); + $2 = SCM_UNSPECIFIED; + } else + $1 = scm_car ($1); + } + if (unsmob_context_def ($2)) + assign_context_def (unsmob_output_def ($1), $2); + // Seems unlikely, but let's be complete: + else if (unsmob_music ($2)) + { + SCM proc = parser->lexer_->lookup_identifier + ("output-def-music-handler"); + scm_call_3 (proc, parser->self_scm (), + $1, $2); + } else if (!scm_is_eq ($2, SCM_UNSPECIFIED)) + parser->parser_error (@2, _("bad expression type")); + $$ = $1; + } + | output_def_body SCM_TOKEN { + if (scm_is_pair ($1)) + $$ = scm_car ($1); + // Evaluate and ignore #xxx, as opposed to \xxx + parser->lexer_->eval_scm_token ($2, @2); } | output_def_body { + if (scm_is_pair ($1)) + $1 = scm_car ($1); SCM nn = parser->lexer_->lookup_identifier ("pitchnames"); parser->lexer_->push_note_state (nn); } music_or_context_def @@ -1086,6 +1174,7 @@ output_def_body: scm_call_3 (proc, parser->self_scm (), $1, $3); } + $$ = $1; } | output_def_body error { @@ -1299,9 +1388,19 @@ context_mod_list: if (md) unsmob_context_mod ($1)->add_context_mods (md->get_mods ()); } - | context_mod_list context_mod_embedded { - unsmob_context_mod ($1)->add_context_mods - (unsmob_context_mod ($2)->get_mods ()); + | context_mod_list context_mod_arg { + if (scm_is_eq ($2, SCM_UNSPECIFIED)) + ; + else if (unsmob_music ($2)) { + SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler"); + $2 = scm_call_2 (proc, parser->self_scm (), $2); + } + if (unsmob_context_mod ($2)) + unsmob_context_mod ($$)->add_context_mods + (unsmob_context_mod ($2)->get_mods ()); + else { + parser->parser_error (@2, _ ("not a context mod")); + } } ; @@ -1429,7 +1528,6 @@ function_arglist_nonbackup: $$ = check_scheme_arg (parser, @4, t->unprotect (), $3, $2, n); } - } | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup '-' REAL { @@ -1706,7 +1804,6 @@ function_arglist_backup: parser->lexer_->push_extra_token (@4, '-'); } } - } | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup '-' REAL { @@ -1983,7 +2080,6 @@ function_arglist_common_reparse: else MYREPARSE (@4, $1, SCM_ARG, $4); } - } | EXPECT_SCM function_arglist_optional '-' REAL { @@ -2025,6 +2121,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; } @@ -2137,20 +2250,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); } ; @@ -2158,11 +2262,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); } ; @@ -2256,7 +2357,7 @@ revert_arg_part: | revert_arg_backup BACKUP SCM_ARG symbol_list_part { $$ = scm_append_x (scm_list_2 ($4, $3)); - } + } ; context_def_mod: @@ -2606,6 +2707,7 @@ chord_body_element: music_function_chord_body: music_function_call | MUSIC_IDENTIFIER + | embedded_scm ; event_function_event: @@ -2688,7 +2790,7 @@ post_event_nofinger: { $$ = $2; unsmob_music ($$)->set_property ("direction", scm_from_int (DOWN)); - } + } ; post_event: @@ -2716,7 +2818,7 @@ direction_less_event: a->set_property ("tremolo-type", $1); $$ = a->unprotect (); } - | event_function_event + | event_function_event ; direction_reqd_event: @@ -2946,12 +3048,16 @@ dots: tremolo_type: ':' { - $$ = SCM_INUM0; + $$ = scm_from_int (parser->default_tremolo_type_); } | ':' UNSIGNED { - if (SCM_UNBNDP (make_duration ($2))) + if (SCM_UNBNDP (make_duration ($2))) { parser->parser_error (@2, _ ("not a duration")); - $$ = $2; + $$ = scm_from_int (parser->default_tremolo_type_); + } else { + $$ = $2; + parser->default_tremolo_type_ = scm_to_int ($2); + } } ; @@ -3079,20 +3185,20 @@ pitch_or_music: n = MY_MAKE_MUSIC ("RestEvent", @$); else n = MY_MAKE_MUSIC ("NoteEvent", @$); - + n->set_property ("pitch", $1); if (SCM_UNBNDP ($5)) n->set_property ("duration", parser->default_duration_.smobbed_copy ()); else n->set_property ("duration", $5); - + if (scm_is_number ($4)) { int q = scm_to_int ($4); n->set_property ("absolute-octave", scm_from_int (q-1)); } - + if (to_boolean ($3)) n->set_property ("cautionary", SCM_BOOL_T); if (to_boolean ($2) || to_boolean ($3)) @@ -3407,7 +3513,7 @@ markup_scm: } } BACKUP ; - + markup_list: markup_composed_list { @@ -3431,7 +3537,13 @@ markup_uncomposed_list: SCM nn = parser->lexer_->lookup_identifier ("pitchnames"); parser->lexer_->push_note_state (nn); } '{' score_body '}' { - unsmob_score ($4)->origin ()->set_spot (@$); + Score *sc = unsmob_score ($4); + sc->origin ()->set_spot (@$); + if (sc->defs_.empty ()) { + Output_def *od = get_layout (parser); + sc->add_output_def (od); + od->unprotect (); + } $$ = scm_list_1 (scm_list_2 (ly_lily_module_constant ("score-lines-markup-list"), $4)); parser->lexer_->pop_state (); } @@ -3508,7 +3620,13 @@ simple_markup: SCM nn = parser->lexer_->lookup_identifier ("pitchnames"); parser->lexer_->push_note_state (nn); } '{' score_body '}' { - unsmob_score ($4)->origin ()->set_spot (@$); + Score *sc = unsmob_score ($4); + sc->origin ()->set_spot (@$); + if (sc->defs_.empty ()) { + Output_def *od = get_layout (parser); + sc->add_output_def (od); + od->unprotect (); + } $$ = scm_list_2 (ly_lily_module_constant ("score-markup"), $4); parser->lexer_->pop_state (); } @@ -3570,16 +3688,12 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid) } else if (scm_is_number (sid)) { *destination = sid; return NUMBER_IDENTIFIER; - } else if (unsmob_context_def (sid)) { - Context_def *def= unsmob_context_def (sid)->clone (); - - *destination = def->self_scm (); - def->unprotect (); - - return CONTEXT_DEF_IDENTIFIER; + } else if (unsmob_context_def (sid)) + { + *destination = unsmob_context_def (sid)->clone ()->unprotect (); + return SCM_IDENTIFIER; } else if (unsmob_context_mod (sid)) { *destination = unsmob_context_mod (sid)->smobbed_copy (); - return CONTEXT_MOD_IDENTIFIER; } else if (Music *mus = unsmob_music (sid)) { mus = mus->clone (); @@ -3594,12 +3708,8 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid) *destination = unsmob_duration (sid)->smobbed_copy (); return DURATION_IDENTIFIER; } else if (unsmob_output_def (sid)) { - Output_def *p = unsmob_output_def (sid); - p = p->clone (); - - *destination = p->self_scm (); - p->unprotect (); - return OUTPUT_DEF_IDENTIFIER; + *destination = unsmob_output_def (sid)->clone ()->unprotect (); + return SCM_IDENTIFIER; } else if (unsmob_score (sid)) { *destination = unsmob_score (sid)->clone ()->unprotect (); return SCM_IDENTIFIER;