%{
-#define MY_MAKE_MUSIC(x, spot) make_music_with_input (ly_symbol2scm (x), spot)
+#define MY_MAKE_MUSIC(x, spot) \
+ make_music_with_input (ly_symbol2scm (x), \
+ parser->lexer_->override_input (spot))
/* ES TODO:
- Don't use lily module, create a new module instead.
#define LOWLEVEL_MAKE_SYNTAX(proc, args) \
scm_apply_0 (proc, args)
/* Syntactic Sugar. */
-#define MAKE_SYNTAX(name, location, ...) \
- LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant (name), scm_list_n (parser->self_scm (), make_input (location) , ##__VA_ARGS__, SCM_UNDEFINED))
+#define MAKE_SYNTAX(name, location, ...) \
+ LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant (name), scm_list_n (parser->self_scm (), make_input (parser->lexer_->override_input (location)), ##__VA_ARGS__, SCM_UNDEFINED))
#define START_MAKE_SYNTAX(name, ...) \
scm_list_n (ly_lily_module_constant (name) , ##__VA_ARGS__, SCM_UNDEFINED)
#define FINISH_MAKE_SYNTAX(start, location, ...) \
- LOWLEVEL_MAKE_SYNTAX (scm_car (start), scm_cons2 (parser->self_scm (), make_input (location), scm_append_x (scm_list_2 (scm_cdr (start), scm_list_n (__VA_ARGS__, SCM_UNDEFINED)))))
+ LOWLEVEL_MAKE_SYNTAX (scm_car (start), scm_cons2 (parser->self_scm (), make_input (parser->lexer_->override_input (location)), scm_append_x (scm_list_2 (scm_cdr (start), scm_list_n (__VA_ARGS__, SCM_UNDEFINED)))))
SCM get_next_unique_context_id ();
SCM get_next_unique_lyrics_context_id ();
static Music *make_music_with_input (SCM name, Input where);
SCM check_scheme_arg (Lily_parser *parser, Input loc,
- SCM arg, SCM args, SCM pred);
+ SCM arg, SCM args, SCM pred, SCM disp = SCM_UNDEFINED);
SCM make_music_from_simple (Lily_parser *parser, Input loc, SCM pitch);
SCM loc_on_music (Input loc, SCM arg);
SCM make_chord_elements (Input loc, SCM pitch, SCM dur, SCM modification_list);
%token HYPHEN "--"
%token CHORDMODIFIERS
-%token LYRIC_MARKUP
%token MULTI_MEASURE_REST
%token EVENT_IDENTIFIER
%token EVENT_FUNCTION
%token FRACTION
-%token LYRICS_STRING
%token LYRIC_ELEMENT
%token MARKUP_FUNCTION
%token MARKUP_LIST_FUNCTION
{
$$ = parser->lexer_->eval_scm_token ($1);
}
- | full_markup
| full_markup_list
| context_modification
| score_block
*/
assignment_id:
STRING { $$ = $1; }
- | LYRICS_STRING { $$ = $1; }
;
assignment:
| output_def
| context_def_spec_block
| music_assign
- | post_event_nofinger
+ | post_event_nofinger post_events
+ {
+ $$ = scm_reverse_x ($2, SCM_EOL);
+ if (Music *m = unsmob_music ($1))
+ {
+ if (m->is_mus_type ("post-event-wrapper"))
+ $$ = scm_append
+ (scm_list_2 (m->get_property ("elements"),
+ $$));
+ else
+ $$ = scm_cons ($1, $$);
+ }
+ if (scm_is_pair ($$)
+ && scm_is_null (scm_cdr ($$)))
+ $$ = scm_car ($$);
+ else
+ {
+ Music * m = MY_MAKE_MUSIC ("PostEvents", @$);
+ m->set_property ("elements", $$);
+ $$ = m->unprotect ();
+ }
+ }
| number_expression
| FRACTION
| string
music_embedded:
music
- | embedded_scm
{
- if (unsmob_music ($1)
- || scm_is_eq ($1, SCM_UNSPECIFIED))
- $$ = $1;
- else
- {
- @$.warning (_ ("Ignoring non-music expression"));
+ if (unsmob_music ($1)->is_mus_type ("post-event")) {
+ parser->parser_error (@1, _ ("unexpected post-event"));
$$ = SCM_UNSPECIFIED;
}
}
+ | music_embedded_backup BACKUP SCM_ARG
+ {
+ $$ = $3;
+ }
+ | music_embedded_backup BACKUP lyric_element_music
+ {
+ $$ = $3;
+ }
+ ;
+
+music_embedded_backup:
+ embedded_scm_closed
+ {
+ if (scm_is_eq ($1, SCM_UNSPECIFIED))
+ MYBACKUP (SCM_ARG, $1, @1);
+ else if (Music *m = unsmob_music ($1)) {
+ if (m->is_mus_type ("post-event")) {
+ parser->parser_error
+ (@1, _ ("unexpected post-event"));
+ MYBACKUP (SCM_ARG, SCM_UNSPECIFIED, @1);
+ } else
+ MYBACKUP (SCM_ARG, $1, @1);
+ } else if (parser->lexer_->is_lyric_state ()
+ && Text_interface::is_markup ($1))
+ MYBACKUP (LYRIC_ELEMENT, $1, @1);
+ else {
+ @$.warning (_ ("Ignoring non-music expression"));
+ MYBACKUP (SCM_ARG, SCM_UNSPECIFIED, @1);
+ }
+ }
;
music_arg:
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);
+ $$ = check_scheme_arg (parser, @4, t->unprotect (),
+ $3, $2, n);
}
}
}
| EXPECT_OPTIONAL EXPECT_SCM function_arglist SCM_IDENTIFIER
{
- SCM res = try_string_variants ($2, $4);
- if (SCM_UNBNDP (res))
- $$ = check_scheme_arg (parser, @4, $4, $3, $2);
- else
- $$ = scm_cons (res, $3);
+ $$ = check_scheme_arg (parser, @4,
+ try_string_variants ($2, $4),
+ $3, $2, $4);
}
| EXPECT_OPTIONAL EXPECT_SCM function_arglist STRING
{
- SCM res = try_string_variants ($2, $4);
- if (SCM_UNBNDP (res))
- $$ = check_scheme_arg (parser, @4, $4, $3, $2);
- else
- $$ = scm_cons (res, $3);
- }
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist LYRICS_STRING
- {
- SCM res = try_string_variants ($2, $4);
- if (SCM_UNBNDP (res))
- $$ = check_scheme_arg (parser, @4, $4, $3, $2);
- else
- $$ = scm_cons (res, $3);
+ $$ = check_scheme_arg (parser, @4,
+ try_string_variants ($2, $4),
+ $3, $2, $4);
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist lyric_markup
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist full_markup
{
$$ = check_scheme_arg (parser, @4, $4, $3, $2);
}
symbol_list_element:
STRING
- | LYRICS_STRING
| embedded_scm_bare
;
(scm_call_1
($2, make_music_from_simple
(parser, @4, $4))))
- MYREPARSE (@4, $2, LYRICS_STRING, $4);
+ MYREPARSE (@4, $2, STRING, $4);
else
MYREPARSE (@4, $2, SCM_ARG, $4);
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist LYRICS_STRING
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist STRING
{
$$ = $3;
SCM res = try_string_variants ($2, $4);
(scm_call_1
($2, make_music_from_simple
(parser, @4, $4))))
- MYREPARSE (@4, $2, LYRICS_STRING, $4);
+ MYREPARSE (@4, $2, STRING, $4);
else
MYREPARSE (@4, $2, SCM_ARG, $4);
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist STRING
- {
- $$ = $3;
- SCM res = try_string_variants ($2, $4);
- if (!SCM_UNBNDP (res))
- if (scm_is_pair (res))
- MYREPARSE (@4, $2, SYMBOL_LIST, res);
- else
- MYREPARSE (@4, $2, SCM_ARG, res);
- else
- MYREPARSE (@4, $2, SCM_ARG, $4);
- }
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist lyric_markup
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist full_markup
{
$$ = $3;
if (scm_is_true (scm_call_1 ($2, $4)))
(scm_call_1
($2, make_music_from_simple
(parser, @4, $4))))
- MYREPARSE (@4, $2, LYRICS_STRING, $4);
+ MYREPARSE (@4, $2, STRING, $4);
else
MYREPARSE (@4, $2, SCM_ARG, $4);
}
MYBACKUP (EVENT_IDENTIFIER, $4, @4);
}
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep lyric_markup
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep full_markup
{
if (scm_is_true (scm_call_1 ($2, $4)))
$$ = scm_cons ($4, $3);
MYBACKUP (STRING, $4, @4);
}
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep LYRICS_STRING
- {
- SCM res = try_string_variants ($2, $4);
- if (!SCM_UNBNDP (res))
- if (scm_is_pair (res)) {
- $$ = $3;
- MYREPARSE (@4, $2, SYMBOL_LIST, res);
- }
- else
- $$ = scm_cons (res, $3);
- else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
- MYBACKUP (LYRICS_STRING, $4, @4);
- }
- }
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup BACKUP
{
$$ = scm_cons ($1, $3);
MYREPARSE (@3, $1, SCM_ARG, $3);
}
| EXPECT_SCM function_arglist_optional STRING
- {
- $$ = $2;
- SCM res = try_string_variants ($1, $3);
- if (!SCM_UNBNDP (res))
- if (scm_is_pair (res))
- MYREPARSE (@3, $1, SYMBOL_LIST, res);
- else
- MYREPARSE (@3, $1, SCM_ARG, res);
- else
- // This is going to flag a syntax error, we
- // know the predicate to be false.
- MYREPARSE (@3, $1, SCM_ARG, $3);
- }
- | EXPECT_SCM function_arglist_optional LYRICS_STRING
{
$$ = $2;
SCM res = try_string_variants ($1, $3);
// know the predicate to be false.
MYREPARSE (@3, $1, SCM_ARG, $3);
}
- | EXPECT_SCM function_arglist_optional lyric_markup
+ | EXPECT_SCM function_arglist_optional full_markup
{
$$ = $2;
if (scm_is_true (scm_call_1 ($1, $3)))
}
}
| REVERT revert_arg {
- $$ = scm_list_3 (ly_symbol2scm ("pop"),
- scm_car ($2),
- scm_cdr ($2));
+ $$ = scm_cons (ly_symbol2scm ("pop"), $2);
}
;
// \revert Accidental.color
revert_arg:
+ revert_arg_backup BACKUP symbol_list_arg
+ {
+ $$ = $3;
+ }
+ ;
+
+revert_arg_backup:
revert_arg_part
{
if (scm_is_null ($1)
else
MYBACKUP (SYMBOL_LIST, scm_reverse_x ($1, SCM_EOL), @1);
}
- | revert_arg BACKUP symbol_list_arg
- {
- $$ = $3;
- }
;
// revert_arg_part delivers results in reverse
revert_arg_part:
symbol_list_part
- | revert_arg BACKUP SCM_ARG '.' symbol_list_part
+ | revert_arg_backup BACKUP SCM_ARG '.' symbol_list_part
{
$$ = scm_append_x (scm_list_2 ($5, $3));
}
- | revert_arg BACKUP SCM_ARG symbol_list_part
+ | revert_arg_backup BACKUP SCM_ARG symbol_list_part
{
$$ = scm_append_x (scm_list_2 ($4, $3));
}
simple_string: STRING {
$$ = $1;
}
- | LYRICS_STRING {
- $$ = $1;
- }
| embedded_scm_bare
{
if (scm_is_string ($1)) {
| bare_number
| FRACTION
| lyric_element
- | STRING
;
scalar_closed:
| bare_number
| FRACTION
| lyric_element
- | STRING
;
$$ = SCM_EOL;
}
| post_events post_event {
- unsmob_music ($2)->set_spot (@2);
- $$ = scm_cons ($2, $$);
+ $$ = $1;
+ if (Music *m = unsmob_music ($2))
+ {
+ if (m->is_mus_type ("post-event-wrapper"))
+ {
+ for (SCM p = m->get_property ("elements");
+ scm_is_pair (p);
+ p = scm_cdr (p))
+ {
+ $$ = scm_cons (scm_car (p), $$);
+ }
+ } else {
+ m->set_spot (@2);
+ $$ = scm_cons ($2, $$);
+ }
+ }
}
;
}
| script_dir music_function_call_closed {
$$ = $2;
- if (!SCM_UNBNDP ($1))
+ if (!unsmob_music ($2)->is_mus_type ("post-event")) {
+ parser->parser_error (@2, _ ("post-event expected"));
+ $$ = SCM_UNSPECIFIED;
+ } else if (!SCM_UNBNDP ($1))
{
unsmob_music ($$)->set_property ("direction", $1);
}
make_simple_markup ($1));
$$ = t->unprotect ();
}
- | LYRICS_STRING {
- Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
- t->set_property ("text",
- make_simple_markup ($1));
- $$ = t->unprotect ();
- }
| embedded_scm_closed
{
Music *m = unsmob_music ($1);
;
lyric_element:
- lyric_markup {
+ full_markup {
$$ = $1;
}
- | LYRICS_STRING {
+ | STRING {
$$ = $1;
}
| LYRIC_ELEMENT
lyric_element_music:
lyric_element optional_notemode_duration post_events {
+ if (!parser->lexer_->is_lyric_state ())
+ parser->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
$$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
if (scm_is_pair ($3))
unsmob_music ($$)->set_property
}
;
-/*
-This should be done more dynamically if possible.
-*/
-
-lyric_markup:
- LYRIC_MARKUP
- { parser->lexer_->push_markup_state (); }
- markup_top {
- $$ = $3;
- parser->lexer_->pop_state ();
- }
- ;
-
full_markup_list:
MARKUPLIST
{ parser->lexer_->push_markup_state (); }
;
markup_top:
- markup_list {
+ simple_markup_list {
$$ = scm_list_2 (ly_lily_module_constant ("line-markup"), $1);
}
- | markup_head_1_list simple_markup {
- $$ = scm_car (scm_call_2 (ly_lily_module_constant ("map-markup-command-list"), $1, scm_list_1 ($2)));
+ | markup_head_1_list simple_markup
+ {
+ $$ = scm_car (MAKE_SYNTAX ("composed-markup-list",
+ @2, $1, scm_list_1 ($2)));
}
| simple_markup {
$$ = $1;
;
-markup_list:
+simple_markup_list:
markup_composed_list {
$$ = $1;
}
- | markup_braced_list {
+ | markup_uncomposed_list
+ ;
+
+markup_uncomposed_list:
+ markup_braced_list {
$$ = $1;
}
| markup_command_list {
}
;
-markup_composed_list:
- markup_head_1_list markup_braced_list {
- $$ = scm_call_2 (ly_lily_module_constant ("map-markup-command-list"), $1, $2);
+markup_list:
+ simple_markup_list
+ | markup_score
+ {
+ $$ = scm_list_1 (scm_list_2 (ly_lily_module_constant ("score-lines-markup-list"), $1));
+ }
+ ;
+
+markup_score:
+ SCORE {
+ SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
+ parser->lexer_->push_note_state (nn);
+ } '{' score_body '}' {
+ $$ = $4;
+ parser->lexer_->pop_state ();
+ }
+ ;
+markup_composed_list:
+ markup_head_1_list markup_uncomposed_list {
+ $$ = MAKE_SYNTAX ("composed-markup-list",
+ @2, $1, $2);
}
;
| markup_braced_list_body markup {
$$ = scm_cons ($2, $1);
}
- | markup_braced_list_body markup_list {
+ | markup_braced_list_body simple_markup_list {
$$ = scm_reverse_x ($2, $1);
}
;
STRING {
$$ = make_simple_markup ($1);
}
- | SCORE {
- SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
- parser->lexer_->push_note_state (nn);
- } '{' score_body '}' {
- $$ = scm_list_2 (ly_lily_module_constant ("score-markup"), $4);
- parser->lexer_->pop_state ();
- }
| MARKUP_FUNCTION markup_command_basic_arguments {
$$ = scm_cons ($1, scm_reverse_x ($2, SCM_EOL));
}
{
$$ = $2;
}
+ | markup_score
+ {
+ $$ = scm_list_2 (ly_lily_module_constant ("score-markup"), $1);
+ }
;
markup:
- markup_head_1_list simple_markup {
- SCM mapper = ly_lily_module_constant ("map-markup-command-list");
- $$ = scm_car (scm_call_2 (mapper, $1, scm_list_1 ($2)));
+ markup_head_1_list simple_markup
+ {
+ $$ = scm_car (MAKE_SYNTAX ("composed-markup-list",
+ @2, $1, scm_list_1 ($2)));
}
| simple_markup {
$$ = $1;
} else if (Music *mus = unsmob_music (sid)) {
mus = mus->clone ();
*destination = mus->self_scm ();
- unsmob_music (*destination)->
- set_property ("origin", make_input (last_input_));
-
bool is_event = mus->is_mus_type ("post-event");
mus->unprotect ();
return is_event ? EVENT_IDENTIFIER : MUSIC_IDENTIFIER;
return scm_from_locale_string (s);
}
+// check_scheme_arg checks one argument with a given predicate for use
+// in an argument list and throws a syntax error if it is unusable.
+// The argument is prepended to the argument list in any case. After
+// throwing a syntax error, the argument list is terminated with #f as
+// its last cdr in order to mark it as uncallable while not losing
+// track of its total length.
+//
+// There are a few special considerations: if optional argument disp
+// is given (otherwise it defaults to SCM_UNDEFINED), it will be used
+// instead of arg in a prospective error message. This is useful if
+// arg is not the actual argument but rather a transformation of it.
+//
+// If arg itself is SCM_UNDEFINED, the predicate is considered false
+// and an error message using disp is produced unconditionally.
+
SCM check_scheme_arg (Lily_parser *parser, Input loc,
- SCM arg, SCM args, SCM pred)
+ SCM arg, SCM args, SCM pred, SCM disp)
{
- args = scm_cons (arg, args);
- if (scm_is_true (scm_call_1 (pred, arg)))
- return args;
+ if (SCM_UNBNDP (arg))
+ args = scm_cons (disp, args);
+ else {
+ args = scm_cons (arg, args);
+ if (scm_is_true (scm_call_1 (pred, arg)))
+ return args;
+ }
scm_set_cdr_x (scm_last_pair (args), SCM_EOL);
- MAKE_SYNTAX ("argument-error", loc, scm_length (args), pred, arg);
+ MAKE_SYNTAX ("argument-error", loc, scm_length (args), pred,
+ SCM_UNBNDP (disp) ? arg : disp);
scm_set_cdr_x (scm_last_pair (args), SCM_BOOL_F);
return args;
}
if (unsmob_music (simple))
return simple;
if (parser->lexer_->is_note_state ()) {
- Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
- n->set_property ("duration", parser->default_duration_.smobbed_copy ());
- if (scm_is_symbol (simple))
+ if (scm_is_symbol (simple)) {
+ Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
+ n->set_property ("duration", parser->default_duration_.smobbed_copy ());
n->set_property ("drum-type", simple);
- else if (unsmob_pitch (simple))
+ return n->unprotect ();
+ }
+ if (unsmob_pitch (simple)) {
+ Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
+ n->set_property ("duration", parser->default_duration_.smobbed_copy ());
n->set_property ("pitch", simple);
- else {
- n->unprotect ();
- return simple;
+ return n->unprotect ();
}
- return n->unprotect ();
+ return simple;
} else if (parser->lexer_->is_lyric_state ()) {
if (Text_interface::is_markup (simple))
return MAKE_SYNTAX ("lyric-event", loc, simple,