%token BOOK_IDENTIFIER
%token CHORD_MODIFIER
%token CHORD_REPETITION
-%token CONTEXT_MOD_IDENTIFIER
%token DRUM_PITCH
/* Artificial token for durations in argument lists */
%token DURATION_ARG
toplevel_expression:
- {
- parser->lexer_->add_scope (get_header (parser));
- } lilypond_header {
- parser->lexer_->set_identifier (ly_symbol2scm ("$defaultheader"), $2);
+ header_block {
+ parser->lexer_->set_identifier (ly_symbol2scm ("$defaultheader"), $1);
}
| book_block {
SCM proc = parser->lexer_->lookup_identifier ("toplevel-book-handler");
id = ly_symbol2scm ("$defaultlayout");
parser->lexer_->set_identifier (id, $1);
+ } else if (ly_is_module ($1))
+ {
+ SCM module = get_header (parser);
+ ly_module_copy (module, $1);
+ parser->lexer_->set_identifier
+ (ly_symbol2scm ("$defaultheader"), module);
} else if (!scm_is_eq ($1, SCM_UNSPECIFIED))
parser->parser_error (@1, _("bad expression type"));
}
| partial_markup
| full_markup_list
| context_modification
+ | header_block
| score_block
| context_def_spec_block
| book_block
| lilypond_header_body assignment {
}
- | lilypond_header_body embedded_scm {
-
+ | lilypond_header_body SCM_TOKEN {
+ // Evaluate and ignore #xxx, as opposed to \xxx
+ parser->lexer_->eval_scm_token ($2, @2);
+ }
+ | lilypond_header_body embedded_scm_active {
+ if (ly_is_module ($2))
+ ly_module_copy (scm_current_module (), $2);
+ else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
+ parser->parser_error (@2, _("bad expression type"));
}
;
}
;
+header_block:
+ {
+ parser->lexer_->add_scope (get_header (parser));
+ } lilypond_header {
+ $$ = $2;
+ }
+ ;
+
/*
DECLARATIONS
*/
;
identifier_init_nonumber:
- score_block
+ header_block
+ | score_block
| book_block
| bookpart_block
| output_def
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 (to_boolean (od->c_variable ("is-paper")))
- id = ly_symbol2scm ("$defaultpaper");
- else if (to_boolean (od->c_variable ("is-midi")))
- id = ly_symbol2scm ("$defaultmidi");
- else if (to_boolean (od->c_variable ("is-layout")))
- id = ly_symbol2scm ("$defaultlayout");
-
- parser->lexer_->set_identifier (id, $2);
+ if (to_boolean (od->lookup_variable (ly_symbol2scm ("is-paper")))) {
+ unsmob<Book> ($1)->paper_ = od;
+ set_paper (parser, od);
+ } else {
+ parser->parser_error (@2, _ ("need \\paper for paper block"));
+ }
+ } else if (ly_is_module ($2))
+ {
+ ly_module_copy (unsmob<Book> ($1)->header_, $2);
} else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
parser->parser_error (@2, _("bad expression type"));
}
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 (to_boolean (od->c_variable ("is-paper")))
- id = ly_symbol2scm ("$defaultpaper");
- else if (to_boolean (od->c_variable ("is-midi")))
- id = ly_symbol2scm ("$defaultmidi");
- else if (to_boolean (od->c_variable ("is-layout")))
- id = ly_symbol2scm ("$defaultlayout");
-
- parser->lexer_->set_identifier (id, $2);
+ if (to_boolean (od->lookup_variable (ly_symbol2scm ("is-paper")))) {
+ unsmob<Book> ($1)->paper_ = od;
+ } else {
+ parser->parser_error (@2, _ ("need \\paper for paper block"));
+ }
+ } else if (ly_is_module ($2)) {
+ Book *book = unsmob<Book> ($1);
+ if (!ly_is_module (book->header_))
+ book->header_ = ly_make_module (false);
+ ly_module_copy (book->header_, $2);
} else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
parser->parser_error (@2, _("bad expression type"));
}
scm_set_cdr_x ($$, scm_cons ($2, scm_cdr ($$)));
else
$$ = scm_cons ($2, $$);
+ } else if (ly_is_module ($2)) {
+ SCM module = SCM_UNSPECIFIED;
+ if (score) {
+ module = score->get_header ();
+ if (!ly_is_module (module))
+ {
+ module = ly_make_module (false);
+ score->set_header (module);
+ }
+ } else if (scm_is_pair ($$) && ly_is_module (scm_car ($$)))
+ module = scm_car ($$);
+ else {
+ module = ly_make_module (false);
+ $$ = scm_cons (module, $$);
+ }
+ ly_module_copy (module, $2);
} else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
parser->parser_error (@2, _("Spurious expression in \\score"));
}
parser->lexer_->pop_state ();
$$ = $4;
}
- | WITH CONTEXT_MOD_IDENTIFIER
- {
- $$ = $2;
- }
- | CONTEXT_MOD_IDENTIFIER
- {
- $$ = $1;
- }
| WITH context_modification_arg
{
if (unsmob<Music> ($2)) {
if (unsmob<Context_mod> ($2))
$$ = $2;
else {
- parser->parser_error (@2, _ ("not a context mod"));
+ // let's permit \with #*unspecified* to go for
+ // an empty context mod
+ if (!scm_is_eq ($2, SCM_UNSPECIFIED))
+ parser->parser_error (@2, _ ("not a context mod"));
$$ = Context_mod ().smobbed_copy ();
}
}
| MUSIC_IDENTIFIER
;
-optional_context_mod:
- /**/ {
- $$ = SCM_EOL;
- }
- | context_modification
+/* A list of single mods collected from a (possibly empty) sequence of
+ * context modifications, usually written as \with ... \with ...
+ */
+
+optional_context_mods:
+ context_modification_mods_list
{
- $$ = $1;
+ if (scm_is_pair ($1))
+ $$ = scm_append_x (scm_reverse_x ($1, SCM_EOL));
}
;
+/* The worker for optional_context_mods conses a (reversed) list where
+ * each element contains the list of single context mods from one
+ * context modification block. Context_mod::get_mods creates fresh
+ * copies, so it's okay to use append! on them.
+ */
+
+context_modification_mods_list:
+ /**/ {
+ $$ = SCM_EOL;
+ }
+ | context_modification_mods_list context_modification
+ {
+ if (Context_mod *m = unsmob<Context_mod> ($2))
+ $$ = scm_cons (m->get_mods (), $1);
+ }
+ ;
+
+/* A Context_mod is a container for a list of context mods like
+ * \consists ... \override ... . context_mod_list produces a
+ * Context_mod from the inside of a \with { ... } statement.
+ */
+
context_mod_list:
/**/ {
$$ = Context_mod ().smobbed_copy ();
if (!SCM_UNBNDP ($2))
unsmob<Context_mod> ($1)->add_context_mod ($2);
}
- | context_mod_list CONTEXT_MOD_IDENTIFIER {
- Context_mod *md = unsmob<Context_mod> ($2);
- if (md)
- unsmob<Context_mod> ($1)->add_context_mods (md->get_mods ());
- }
| context_mod_list context_mod_arg {
- if (scm_is_eq ($2, SCM_UNSPECIFIED))
- ;
- else if (unsmob<Music> ($2)) {
+ if (unsmob<Music> ($2)) {
SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler");
$2 = scm_call_1 (proc, $2);
}
if (unsmob<Context_mod> ($2))
unsmob<Context_mod> ($$)->add_context_mods
(unsmob<Context_mod> ($2)->get_mods ());
- else {
+ else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
parser->parser_error (@2, _ ("not a context mod"));
- }
}
;
context_prefix:
- CONTEXT symbol optional_id optional_context_mod {
- Context_mod *ctxmod = unsmob<Context_mod> ($4);
- SCM mods = SCM_EOL;
- if (ctxmod)
- mods = ctxmod->get_mods ();
- $$ = START_MAKE_SYNTAX (context_specification, $2, $3, mods, SCM_BOOL_F);
+ CONTEXT symbol optional_id optional_context_mods {
+ $$ = START_MAKE_SYNTAX (context_specification, $2, $3, $4, SCM_BOOL_F);
}
- | NEWCONTEXT symbol optional_id optional_context_mod {
- Context_mod *ctxmod = unsmob<Context_mod> ($4);
- SCM mods = SCM_EOL;
- if (ctxmod)
- mods = ctxmod->get_mods ();
- $$ = START_MAKE_SYNTAX (context_specification, $2, $3, mods, SCM_BOOL_T);
+ | NEWCONTEXT symbol optional_id optional_context_mods {
+ $$ = START_MAKE_SYNTAX (context_specification, $2, $3, $4, SCM_BOOL_T);
}
;
new_lyrics:
- ADDLYRICS optional_context_mod lyric_mode_music {
- Context_mod *ctxmod = unsmob<Context_mod> ($2);
- SCM mods = SCM_EOL;
- if (ctxmod)
- mods = ctxmod->get_mods ();
- $$ = scm_acons ($3, mods, SCM_EOL);
+ ADDLYRICS optional_context_mods lyric_mode_music {
+ $$ = scm_acons ($3, $2, SCM_EOL);
}
- | new_lyrics ADDLYRICS optional_context_mod lyric_mode_music {
- Context_mod *ctxmod = unsmob<Context_mod> ($3);
- SCM mods = SCM_EOL;
- if (ctxmod)
- mods = ctxmod->get_mods ();
- $$ = scm_acons ($4, mods, $1);
+ | new_lyrics ADDLYRICS optional_context_mods lyric_mode_music {
+ $$ = scm_acons ($4, $3, $1);
}
;
}
parser->lexer_->pop_state ();
}
- | mode_changing_head_with_context optional_context_mod grouped_music_list {
- Context_mod *ctxmod = unsmob<Context_mod> ($2);
- SCM mods = SCM_EOL;
- if (ctxmod)
- mods = ctxmod->get_mods ();
- $$ = MAKE_SYNTAX (context_specification, @$, $1, SCM_EOL, mods, SCM_BOOL_T, $3);
+ | mode_changing_head_with_context optional_context_mods grouped_music_list {
+ $$ = MAKE_SYNTAX (context_specification, @$, $1, SCM_EOL, $2, SCM_BOOL_T, $3);
if (scm_is_eq ($1, ly_symbol2scm ("ChordNames")))
{
$$ = MAKE_SYNTAX (unrelativable_music, @$, $$);
return SCM_IDENTIFIER;
} else if (unsmob<Context_mod> (sid)) {
*destination = unsmob<Context_mod> (sid)->smobbed_copy ();
- return CONTEXT_MOD_IDENTIFIER;
+ return SCM_IDENTIFIER;
} else if (Music *mus = unsmob<Music> (sid)) {
mus = mus->clone ();
*destination = mus->self_scm ();