-/* -*- mode: c++; c-file-style: "linux" -*- */
+/* -*- mode: c++; c-file-style: "linux"; indent-tabs-mode: t -*- */
/*
This file is part of LilyPond, the GNU music typesetter.
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);
SCM make_chord_step (SCM step, Rational alter);
SCM make_simple_markup (SCM a);
bool is_duration (int t);
-bool is_regular_identifier (SCM id);
+bool is_regular_identifier (SCM id, bool multiple=false);
+SCM try_string_variants (SCM pred, SCM str);
int yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser);
-void set_music_properties (Music *p, SCM a);
%}
%token FRACTION
%token LYRICS_STRING
%token LYRIC_ELEMENT
-%token LYRIC_MARKUP_IDENTIFIER
%token MARKUP_FUNCTION
%token MARKUP_LIST_FUNCTION
%token MARKUP_IDENTIFIER
%token OUTPUT_DEF_IDENTIFIER
%token REAL
%token RESTNAME
+%token SCM_ARG
%token SCM_FUNCTION
%token SCM_IDENTIFIER
%token SCM_TOKEN
-%token SCORE_IDENTIFIER
%token STRING
-%token STRING_IDENTIFIER
+%token SYMBOL_LIST
%token TONICNAME_PITCH
%left '-' '+'
SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
scm_call_2 (proc, parser->self_scm (), $1);
}
+ | SCM_TOKEN {
+ // Evaluate and ignore #xxx, as opposed to \xxx
+ parser->lexer_->eval_scm_token ($1);
+ }
+ | embedded_scm_active
+ {
+ SCM out = SCM_UNDEFINED;
+ if (Text_interface::is_markup ($1))
+ out = scm_list_1 ($1);
+ else if (Text_interface::is_markup_list ($1))
+ out = $1;
+ if (scm_is_pair (out))
+ {
+ SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
+ scm_call_2 (proc, parser->self_scm (), out);
+ } else if (!scm_is_eq ($1, SCM_UNSPECIFIED))
+ parser->parser_error (@1, _("bad expression type"));
+ }
| output_def {
SCM id = SCM_EOL;
Output_def * od = unsmob_output_def ($1);
| SCM_IDENTIFIER
;
+embedded_scm_active:
+ SCM_IDENTIFIER
+ | scm_function_call
+ ;
+
embedded_scm_bare_arg:
- embedded_scm_bare
- | STRING
- | STRING_IDENTIFIER
+ SCM_ARG
+ | SCM_TOKEN
+ {
+ $$ = parser->lexer_->eval_scm_token ($1);
+ }
| full_markup
| full_markup_list
| context_modification
/* empty */ { $$ = SCM_UNSPECIFIED; }
| lilypond_header_body assignment {
+ }
+ | lilypond_header_body embedded_scm {
+
}
;
parser->lexer_->set_identifier (path, $4);
$$ = SCM_UNSPECIFIED;
}
- | embedded_scm { $$ = SCM_UNSPECIFIED; }
;
| FRACTION
| string
| embedded_scm
- | full_markup
| full_markup_list
| context_modification
;
unsmob_context_def ($$)->origin ()->set_spot (@$);
}
| context_def_spec_body context_mod {
- unsmob_context_def ($$)->add_context_mod ($2);
+ if (!SCM_UNBNDP ($2))
+ unsmob_context_def ($$)->add_context_mod ($2);
}
| context_def_spec_body context_modification {
Context_def *td = unsmob_context_def ($$);
SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
scm_call_2 (proc, $1, $2);
}
+ | book_body SCM_TOKEN {
+ // Evaluate and ignore #xxx, as opposed to \xxx
+ parser->lexer_->eval_scm_token ($2);
+ }
+ | book_body embedded_scm_active
+ {
+ SCM out = SCM_UNDEFINED;
+ if (Text_interface::is_markup ($2))
+ out = scm_list_1 ($2);
+ else if (Text_interface::is_markup_list ($2))
+ out = $2;
+ if (scm_is_pair (out))
+ {
+ SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
+ scm_call_2 (proc, $1, out);
+ } else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
+ parser->parser_error (@2, _("bad expression type"));
+ }
| book_body
{
parser->lexer_->add_scope (unsmob_book ($1)->header_);
} lilypond_header
- | book_body embedded_scm { }
| book_body error {
Book *book = unsmob_book ($1);
book->paper_ = 0;
SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
scm_call_2 (proc, $1, $2);
}
+ | bookpart_body SCM_TOKEN {
+ // Evaluate and ignore #xxx, as opposed to \xxx
+ parser->lexer_->eval_scm_token ($2);
+ }
+ | bookpart_body embedded_scm_active
+ {
+ SCM out = SCM_UNDEFINED;
+ if (Text_interface::is_markup ($2))
+ out = scm_list_1 ($2);
+ else if (Text_interface::is_markup_list ($2))
+ out = $2;
+ if (scm_is_pair (out))
+ {
+ SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
+ scm_call_2 (proc, $1, out);
+ } else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
+ parser->parser_error (@2, _("bad expression type"));
+ }
| bookpart_body
{
Book *book = unsmob_book ($1);
book->header_ = ly_make_module (false);
parser->lexer_->add_scope (book->header_);
} lilypond_header
- | bookpart_body embedded_scm { }
| bookpart_body error {
Book *book = unsmob_book ($1);
book->paper_ = 0;
unsmob_score ($$)->origin ()->set_spot (@$);
}
- | SCORE_IDENTIFIER {
+ | embedded_scm_active {
+ Score *score;
+ if (unsmob_score ($1))
+ score = new Score (*unsmob_score ($1));
+ else {
+ score = new Score;
+ parser->parser_error (@1, _("score expected"));
+ }
unsmob_score ($$)->origin ()->set_spot (@$);
+ $$ = score->unprotect ();
}
| score_body
{
}
| output_def_body assignment {
+ }
+ | output_def_body embedded_scm {
+
}
| output_def_body
{
music_arg:
simple_music
{
- if (unsmob_pitch ($1)) {
- Music *n = MY_MAKE_MUSIC ("NoteEvent", @1);
- n->set_property ("pitch", $1);
- n->set_property ("duration",
- parser->default_duration_.smobbed_copy ());
- $$ = n->unprotect ();
- }
+ $$ = make_music_from_simple (parser, @1, $1);
+ if (!unsmob_music ($$))
+ parser->parser_error (@1, _ ("music expected"));
}
| composite_music %prec COMPOSITE
;
music_assign:
simple_music
| composite_music %prec COMPOSITE
- | lyric_element_music
;
repeated_music:
$$ = Context_mod ().smobbed_copy ();
}
| context_mod_list context_mod {
- unsmob_context_mod ($1)->add_context_mod ($2);
+ 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);
MUSIC_FUNCTION EXPECT_PITCH EXPECT_SCM EXPECT_SCM EXPECT_NO_MORE_ARGS
and this rule returns the reversed list of arguments. */
+/* Function argument lists come in a number of flavors. Whenever
+ * LilyPond has to pick between different flavors, the decision is
+ * either made because of tokens it has already seen, or it is
+ * postponed until tokens suitable for making the decision come up.
+ * For postponing decisions, it may be necessary that the competing
+ * rules are written in a way making them compatible until a decision
+ * can be made. Sometimes this is done by putting common traits into
+ * a separate "common" rule set.
+ *
+ * function_arglist: a full argument list. Optional arguments at the
+ * end of the list can only be skipped by writing \default in their
+ * place.
+ *
+ * function_arglist_backup: an argument list ending in an optional
+ * argument that may be skipped depending on its predicate.
+ *
+ * function_arglist_skip: an argument list _not_ ending in an optional
+ * argument that is actually taken.
+ *
+ * function_arglist_nonbackup: an argument list ending in an optional
+ * argument that may not be skipped because it is in end position and
+ * has not been shortcircuited with \default.
+ *
+ * function_arglist* / function_arglist_closed*: The closed variants
+ * don't end in simple music expressions that might still accept
+ * things like a duration or a postevent.
+ */
+
function_arglist_skip:
function_arglist_common
| EXPECT_OPTIONAL EXPECT_PITCH function_arglist_skip
| EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed duration_length {
$$ = scm_cons ($4, $3);
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed FRACTION
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist FRACTION
{
$$ = check_scheme_arg (parser, @4, $4, $3, $2);
}
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);
}
}
{
$$ = check_scheme_arg (parser, @4, $4, $3, $2);
}
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist SCM_IDENTIFIER
+ {
+ $$ = check_scheme_arg (parser, @4,
+ try_string_variants ($2, $4),
+ $3, $2, $4);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist STRING
+ {
+ $$ = check_scheme_arg (parser, @4,
+ try_string_variants ($2, $4),
+ $3, $2, $4);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist LYRICS_STRING
+ {
+ $$ = check_scheme_arg (parser, @4,
+ try_string_variants ($2, $4),
+ $3, $2, $4);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist lyric_markup
+ {
+ $$ = check_scheme_arg (parser, @4, $4, $3, $2);
+ }
+ ;
+
+symbol_list_arg:
+ SYMBOL_LIST
+ | SYMBOL_LIST '.' symbol_list_rev
+ {
+ $$ = scm_append (scm_list_2 ($1, scm_reverse_x ($3, SCM_EOL)));
+ }
+ ;
+
+symbol_list_rev:
+ symbol_list_part
+ | symbol_list_rev '.' symbol_list_part
+ {
+ $$ = scm_append_x (scm_list_2 ($3, $1));
+ }
+ ;
+
+// symbol_list_part delivers elements in reverse copy.
+
+symbol_list_part:
+ symbol_list_element
+ {
+ SCM sym_l_p = ly_lily_module_constant ("symbol-list?");
+ $$ = try_string_variants (sym_l_p, $1);
+ if (SCM_UNBNDP ($$)) {
+ parser->parser_error (@1, _("not a symbol"));
+ $$ = SCM_EOL;
+ } else
+ $$ = scm_reverse ($$);
+ }
+ ;
+
+
+symbol_list_element:
+ STRING
+ | LYRICS_STRING
+ | embedded_scm_bare
;
+
function_arglist_nonbackup:
function_arglist_nonbackup_common
| EXPECT_OPTIONAL EXPECT_SCM function_arglist embedded_scm_arg
{
$$ = check_scheme_arg (parser, @4, $4, $3, $2);
}
+ | function_arglist_nonbackup_reparse REPARSE SCM_ARG
+ {
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
+ }
+ | function_arglist_nonbackup_reparse REPARSE lyric_element_music
+ {
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
+ }
+ | function_arglist_nonbackup_reparse REPARSE symbol_list_arg
+ {
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
+ }
+ ;
+
+function_arglist_nonbackup_reparse:
+ EXPECT_OPTIONAL EXPECT_SCM function_arglist SCM_IDENTIFIER
+ {
+ $$ = $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 if (scm_is_true
+ (scm_call_1
+ ($2, make_music_from_simple
+ (parser, @4, $4))))
+ MYREPARSE (@4, $2, LYRICS_STRING, $4);
+ else
+ MYREPARSE (@4, $2, SCM_ARG, $4);
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist LYRICS_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 if (scm_is_true
+ (scm_call_1
+ ($2, make_music_from_simple
+ (parser, @4, $4))))
+ MYREPARSE (@4, $2, LYRICS_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
+ {
+ $$ = $3;
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ MYREPARSE (@4, $2, SCM_ARG, $4);
+ else if (scm_is_true
+ (scm_call_1
+ ($2, make_music_from_simple
+ (parser, @4, $4))))
+ MYREPARSE (@4, $2, LYRICS_STRING, $4);
+ else
+ MYREPARSE (@4, $2, SCM_ARG, $4);
+ }
;
function_arglist_keep:
$$ = scm_cons ($4, $3);
} else {
$$ = scm_cons (loc_on_music (@3, $1), $3);
- MYBACKUP (SCM_IDENTIFIER, $4, @4);
+ MYBACKUP (SCM_ARG, $4, @4);
}
}
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep post_event_nofinger
MYBACKUP (EVENT_IDENTIFIER, $4, @4);
}
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep lyric_element
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep lyric_markup
{
- // 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);
+ MYBACKUP (LYRIC_ELEMENT, $4, @4);
}
}
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep UNSIGNED
MYBACKUP (NUMBER_IDENTIFIER, $4, @4);
}
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep FRACTION
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep FRACTION
{
if (scm_is_true (scm_call_1 ($2, $4)))
{
MYREPARSE (@5, $2, REAL, n);
$$ = $3;
} else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
MYBACKUP (REAL, n, @5);
}
}
if (scm_is_true (scm_call_1 ($2, n))) {
$$ = scm_cons (n, $3);
} else {
+ $$ = scm_cons (loc_on_music (@3, $1), $3);
MYBACKUP (NUMBER_IDENTIFIER, n, @5);
}
}
{
$$ = scm_cons ($4, $3);
}
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep SCM_IDENTIFIER
+ {
+ 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 (SCM_IDENTIFIER, $4, @4);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep 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 (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);
MYBACKUP(0, SCM_UNDEFINED, @3);
}
- | function_arglist_backup REPARSE embedded_scm_arg_closed
+ | function_arglist_backup REPARSE bare_number
{
$$ = check_scheme_arg (parser, @3,
$3, $1, $2);
}
- | function_arglist_backup REPARSE bare_number
+ | function_arglist_backup REPARSE symbol_list_arg
{
- $$ = check_scheme_arg (parser, @3,
- $3, $1, $2);
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
}
;
$$ = check_scheme_arg (parser, @3,
$3, $2, $1);
}
- | EXPECT_SCM function_arglist_closed_optional FRACTION
+ | EXPECT_SCM function_arglist_optional FRACTION
{
$$ = check_scheme_arg (parser, @3,
$3, $2, $1);
$$ = check_scheme_arg (parser, @3,
$3, $2, $1);
}
- | function_arglist_common_minus
- | function_arglist_common_lyric
+ | 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_reparse REPARSE SCM_ARG
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ | function_arglist_common_reparse REPARSE lyric_element_music
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ | function_arglist_common_reparse REPARSE bare_number
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ | function_arglist_common_reparse REPARSE symbol_list_arg
+ {
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
+ }
;
-function_arglist_common_lyric:
- EXPECT_SCM function_arglist_optional lyric_element
+function_arglist_common_reparse:
+ EXPECT_SCM function_arglist_optional SCM_IDENTIFIER
{
- // 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;
+ $$ = $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 if (scm_is_true
+ (scm_call_1
+ ($1, make_music_from_simple (parser, @3, $3))))
MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
- } else {
+ else
// This is going to flag a syntax error, we
// know the predicate to be false.
- check_scheme_arg (parser, @3,
- $3, $2, $1);
- }
+ MYREPARSE (@3, $1, SCM_ARG, $3);
}
- | function_arglist_common_lyric REPARSE lyric_element_arg
+ | EXPECT_SCM function_arglist_optional STRING
{
- // This should never be false
- $$ = check_scheme_arg (parser, @3,
- $3, $1, $2);
+ $$ = $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);
}
- ;
-
-function_arglist_common_minus:
- EXPECT_SCM function_arglist_closed_optional '-' UNSIGNED
+ | EXPECT_SCM function_arglist_optional LYRICS_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 if (scm_is_true
+ (scm_call_1
+ ($1, make_music_from_simple (parser, @3, $3))))
+ MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
+ 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 lyric_markup
+ {
+ $$ = $2;
+ if (scm_is_true (scm_call_1 ($1, $3)))
+ MYREPARSE (@3, $1, SCM_ARG, $3);
+ else if (scm_is_true
+ (scm_call_1
+ ($1, make_music_from_simple (parser, @3, $3))))
+ MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
+ 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_closed_optional '-' UNSIGNED
{
+ $$ = $2;
SCM n = scm_difference ($4, SCM_UNDEFINED);
- if (scm_is_true (scm_call_1 ($1, n))) {
- $$ = $2;
+ if (scm_is_true (scm_call_1 ($1, n)))
MYREPARSE (@4, $1, REAL, n);
- } else {
+ 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);
+ SCM m = t->unprotect ();
+ if (scm_is_true (scm_call_1 ($1, m)))
+ MYREPARSE (@4, $1, SCM_ARG, m);
else
- $$ = check_scheme_arg (parser, @3, n, $2, $1);
+ MYREPARSE (@4, $1, SCM_ARG, $4);
}
}
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);
- }
;
function_arglist_closed:
$$ = check_scheme_arg (parser, @3,
$3, $2, $1);
}
- | EXPECT_SCM function_arglist_closed_optional '-' UNSIGNED
- {
- SCM n = scm_difference ($4, SCM_UNDEFINED);
- if (scm_is_true (scm_call_1 ($1, n))) {
- $$ = scm_cons (n, $2);
- } 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
- {
- $$ = check_scheme_arg (parser, @3,
- scm_difference ($4, SCM_UNDEFINED),
- $2, $1);
- }
| EXPECT_SCM function_arglist_closed_optional '-' NUMBER_IDENTIFIER
{
$$ = check_scheme_arg (parser, @3,
$$ = check_scheme_arg (parser, @3,
$3, $2, $1);
}
- | EXPECT_SCM function_arglist_closed_optional FRACTION
+ | EXPECT_SCM function_arglist_optional FRACTION
{
$$ = check_scheme_arg (parser, @3,
$3, $2, $1);
}
- | EXPECT_SCM function_arglist_optional lyric_element
+ | function_arglist_common_reparse REPARSE SCM_ARG
{
$$ = check_scheme_arg (parser, @3,
- $3, $2, $1);
+ $3, $1, $2);
+ }
+ | function_arglist_common_reparse REPARSE bare_number
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ | function_arglist_common_reparse REPARSE symbol_list_arg
+ {
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
}
;
;
-property_path_revved:
- embedded_scm_closed {
- $$ = scm_cons ($1, SCM_EOL);
- }
- | property_path_revved embedded_scm_closed {
- $$ = scm_cons ($2, $1);
- }
- ;
-
property_path:
- property_path_revved {
+ symbol_list_rev {
$$ = scm_reverse_x ($1, SCM_EOL);
}
+ | symbol_list_rev property_path {
+ $$ = scm_reverse_x ($1, $2);
+ }
;
property_operation:
$$ = scm_list_2 (ly_symbol2scm ("unset"),
scm_string_to_symbol ($2));
}
- | OVERRIDE simple_string property_path '=' scalar {
- $$ = scm_append (scm_list_2 (scm_list_3 (ly_symbol2scm ("push"),
- scm_string_to_symbol ($2), $5),
- $3));
+ | OVERRIDE property_path '=' scalar {
+ if (scm_ilength ($2) < 2) {
+ parser->parser_error (@2, _("bad grob property path"));
+ $$ = SCM_UNDEFINED;
+ } else {
+ $$ = scm_cons (ly_symbol2scm ("push"),
+ scm_cons2 (scm_car ($2),
+ $4,
+ scm_cdr ($2)));
+ }
}
- | REVERT simple_string embedded_scm {
+ | REVERT revert_arg {
$$ = scm_list_3 (ly_symbol2scm ("pop"),
- scm_string_to_symbol ($2), $3);
+ scm_car ($2),
+ scm_cdr ($2));
+ }
+ ;
+
+// This is all quite awkward for the sake of substantial backward
+// compatibility while at the same time allowing a more "natural" form
+// of specification not separating grob specification from grob
+// property path. The purpose of this definition of revert_arg is to
+// allow the symbol list which specifies grob and property to revert
+// to be optionally be split into two parts after the grob (which in
+// this case is just the first element of the list). symbol_list_part
+// is only one path component, but it can be parsed without lookahead,
+// so we can follow it with a synthetic BACKUP token when needed. If
+// the first symbol_list_part already contains multiple elements (only
+// possible if a Scheme expression provides them), we just parse for
+// additional elements introduced by '.', which is what the
+// SYMBOL_LIST backup in connection with the immediately following
+// rule using symbol_list_arg does.
+//
+// As long as we don't have our coffers filled with both grob and at
+// least one grob property specification, the rest of the required
+// symbol list chain may be provided either with or without a leading
+// dot. This is for both allowing the traditional
+// \revert Accidental #'color
+// as well as well as the "naive" form
+// \revert Accidental.color
+
+revert_arg:
+ revert_arg_part
+ {
+ if (scm_is_null ($1)
+ || scm_is_null (scm_cdr ($1)))
+ MYBACKUP (SCM_ARG, $1, @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
+ {
+ $$ = scm_append_x (scm_list_2 ($5, $3));
+ }
+ | revert_arg BACKUP SCM_ARG symbol_list_part
+ {
+ $$ = scm_append_x (scm_list_2 ($4, $3));
+ }
+ ;
+
context_def_mod:
CONSISTS { $$ = ly_symbol2scm ("consists"); }
| REMOVE { $$ = ly_symbol2scm ("remove"); }
}
;
-context_prop_spec:
- simple_string {
- if (!is_regular_identifier ($1))
+// If defined, at least two members.
+grob_prop_spec:
+ symbol_list_rev
+ {
+ SCM l = scm_reverse_x ($1, SCM_EOL);
+ if (scm_is_pair (l)
+ && to_boolean
+ (scm_object_property (scm_car (l),
+ ly_symbol2scm ("is-grob?"))))
+ l = scm_cons (ly_symbol2scm ("Bottom"), l);
+ if (scm_is_null (l) || scm_is_null (scm_cdr (l))) {
+ parser->parser_error (@1, _ ("bad grob property path"));
+ l = SCM_UNDEFINED;
+ }
+ $$ = l;
+ }
+ ;
+
+// If defined, at least three members
+grob_prop_path:
+ grob_prop_spec
+ {
+ if (!SCM_UNBNDP ($1) && scm_is_null (scm_cddr ($1)))
{
- @$.error (_("Grob name should be alphanumeric"));
+ parser->parser_error (@1, _ ("bad grob property path"));
+ $$ = SCM_UNDEFINED;
+ }
+ }
+ | grob_prop_spec property_path
+ {
+ if (!SCM_UNBNDP ($1)) {
+ $$ = scm_append_x (scm_list_2 ($1, $2));
+ if (scm_is_null (scm_cddr ($$))) {
+ parser->parser_error (@$, _ ("bad grob property path"));
+ $$ = SCM_UNDEFINED;
+ }
}
- $$ = scm_list_2 (ly_symbol2scm ("Bottom"),
- scm_string_to_symbol ($1));
}
- | simple_string '.' simple_string {
- $$ = scm_list_2 (scm_string_to_symbol ($1),
- scm_string_to_symbol ($3));
+ ;
+
+// Exactly two elements or undefined
+context_prop_spec:
+ symbol_list_rev
+ {
+ SCM l = scm_reverse_x ($1, SCM_EOL);
+ switch (scm_ilength (l)) {
+ case 1:
+ l = scm_cons (ly_symbol2scm ("Bottom"), l);
+ case 2:
+ break;
+ default:
+ parser->parser_error (@1, _ ("bad context property path"));
+ l = SCM_UNDEFINED;
+ }
+ $$ = l;
}
;
simple_music_property_def:
- OVERRIDE context_prop_spec property_path '=' scalar {
- $$ = scm_append (scm_list_2 (scm_list_n (scm_car ($2),
- ly_symbol2scm ("OverrideProperty"),
- scm_cadr ($2),
- $5, SCM_UNDEFINED),
- $3));
- }
- | REVERT context_prop_spec embedded_scm {
- $$ = scm_list_4 (scm_car ($2),
- ly_symbol2scm ("RevertProperty"),
- scm_cadr ($2),
- $3);
+ OVERRIDE grob_prop_path '=' scalar {
+ if (SCM_UNBNDP ($2))
+ $$ = SCM_UNDEFINED;
+ else {
+ $$ = scm_list_5 (scm_car ($2),
+ ly_symbol2scm ("OverrideProperty"),
+ scm_cadr ($2),
+ $4,
+ scm_cddr ($2));
+ }
+ }
+ | REVERT simple_revert_context revert_arg {
+ $$ = scm_list_4 ($2,
+ ly_symbol2scm ("RevertProperty"),
+ scm_car ($3),
+ scm_cdr ($3));
}
| SET context_prop_spec '=' scalar {
- $$ = scm_list_4 (scm_car ($2),
- ly_symbol2scm ("PropertySet"),
- scm_cadr ($2),
- $4);
+ if (SCM_UNBNDP ($2))
+ $$ = SCM_UNDEFINED;
+ else
+ $$ = scm_list_4 (scm_car ($2),
+ ly_symbol2scm ("PropertySet"),
+ scm_cadr ($2),
+ $4);
}
| UNSET context_prop_spec {
- $$ = scm_list_3 (scm_car ($2),
- ly_symbol2scm ("PropertyUnset"),
- scm_cadr ($2));
+ if (SCM_UNBNDP ($2))
+ $$ = SCM_UNDEFINED;
+ else
+ $$ = scm_list_3 (scm_car ($2),
+ ly_symbol2scm ("PropertyUnset"),
+ scm_cadr ($2));
+ }
+ ;
+
+
+// This is all quite awkward for the sake of substantial backward
+// compatibility while at the same time allowing a more "natural" form
+// of specification not separating grob specification from grob
+// property path. The purpose of this definition of
+// simple_revert_context is to allow the symbol list which specifies
+// grob and property to revert to be optionally be split into two
+// parts after the grob (which may be preceded by a context
+// specification, a case which we distinguish by checking whether the
+// first symbol is a valid grob symbol instead).
+//
+// See revert_arg above for the main work horse of this arrangement.
+// simple_revert_context just caters for the context and delegates the
+// rest of the job to revert_arg.
+
+simple_revert_context:
+ symbol_list_part
+ {
+ $1 = scm_reverse_x ($1, SCM_EOL);
+ if (scm_is_null ($1)
+ || to_boolean
+ (scm_object_property (scm_car ($1),
+ ly_symbol2scm ("is-grob?")))) {
+ $$ = ly_symbol2scm ("Bottom");
+ parser->lexer_->push_extra_token (SCM_IDENTIFIER, $1);
+ } else {
+ $$ = scm_car ($1);
+ parser->lexer_->push_extra_token (SCM_IDENTIFIER,
+ scm_cdr ($1));
+ }
}
;
music_property_def:
simple_music_property_def {
- $$ = LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant ("property-operation"), scm_cons2 (parser->self_scm (), make_input (@$), $1));
+ if (SCM_UNBNDP ($1))
+ $$ = MAKE_SYNTAX ("void-music", @1);
+ else
+ $$ = LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant ("property-operation"), scm_cons2 (parser->self_scm (), make_input (@$), $1));
}
;
STRING {
$$ = $1;
}
- | STRING_IDENTIFIER {
- $$ = $1;
- }
+ | full_markup
| string '+' string {
+ if (!scm_is_string ($1)) {
+ parser->parser_error (@1, (_ ("simple string expected")));
+ $1 = scm_string (SCM_EOL);
+ }
+ if (!scm_is_string ($3)) {
+ parser->parser_error (@3, (_ ("simple string expected")));
+ $3 = scm_string (SCM_EOL);
+ }
$$ = scm_string_append (scm_list_2 ($1, $3));
}
;
| LYRICS_STRING {
$$ = $1;
}
- | STRING_IDENTIFIER {
- $$ = $1;
+ | embedded_scm_bare
+ {
+ if (scm_is_string ($1)) {
+ $$ = $1;
+ } else {
+ parser->parser_error (@1, (_ ("simple string expected")));
+ $$ = scm_string (SCM_EOL);
+ }
}
;
scalar:
embedded_scm_arg
+ | SCM_IDENTIFIER
| bare_number
| FRACTION
| lyric_element
+ | STRING
;
scalar_closed:
embedded_scm_arg_closed
+ | SCM_IDENTIFIER
| bare_number
| FRACTION
| lyric_element
+ | STRING
;
simple_element post_events {
// Let the rhythmic music iterator sort this mess out.
if (scm_is_pair ($2)) {
- if (unsmob_pitch ($1)) {
- Music *n = MY_MAKE_MUSIC ("NoteEvent", @1);
- n->set_property ("pitch", $1);
- n->set_property ("duration",
- parser->default_duration_.smobbed_copy ());
- $$ = n->unprotect ();
- }
- unsmob_music ($$)->set_property ("articulations",
- scm_reverse_x ($2, SCM_EOL));
+ $$ = make_music_from_simple (parser, @1, $1);
+ if (unsmob_music ($$))
+ unsmob_music ($$)->set_property ("articulations",
+ scm_reverse_x ($2, SCM_EOL));
+ else
+ parser->parser_error (@1, _("music expected"));
}
}
| simple_chord_elements post_events {
t->set_property ("text", $1);
$$ = t->unprotect ();
}
- | simple_string {
+ | STRING {
Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
t->set_property ("text",
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);
+ if (m && m->is_mus_type ("post-event"))
+ $$ = $1;
+ else if (Text_interface::is_markup ($1)) {
+ Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
+ t->set_property ("text", $1);
+ $$ = t->unprotect ();
+ } else
+ parser->parser_error (@1, _ ("not an articulation"));
+ }
;
fingering:
UNSIGNED { $$ = $1; }
| STRING { $$ = $1; }
| full_markup { $$ = $1; }
+ | embedded_scm_bare
+ {
+ // as an integer, it needs to be non-negative, and otherwise
+ // it needs to be suitable as a markup.
+ if (scm_is_integer ($1)
+ ? scm_is_true (scm_negative_p ($1))
+ : !Text_interface::is_markup ($1))
+ {
+ parser->parser_error (@1, _ ("bass number expected"));
+ $$ = SCM_INUM0;
+ }
+ }
;
figured_bass_alteration:
| LYRICS_STRING {
$$ = $1;
}
+ | LYRIC_ELEMENT
;
-lyric_element_arg:
- lyric_element
- | lyric_element multiplied_duration post_events {
- $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
- if (scm_is_pair ($3))
- unsmob_music ($$)->set_property
- ("articulations", scm_reverse_x ($3, SCM_EOL));
- }
- | lyric_element post_event post_events {
- $$ = MAKE_SYNTAX ("lyric-event", @$, $1,
- parser->default_duration_.smobbed_copy ());
- unsmob_music ($$)->set_property
- ("articulations", scm_cons ($2, scm_reverse_x ($3, SCM_EOL)));
- }
- | LYRIC_ELEMENT optional_notemode_duration post_events {
- $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
- if (scm_is_pair ($3))
- unsmob_music ($$)->set_property
- ("articulations", scm_reverse_x ($3, SCM_EOL));
- }
- ;
-
-
lyric_element_music:
lyric_element optional_notemode_duration post_events {
$$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
*/
lyric_markup:
- LYRIC_MARKUP_IDENTIFIER {
- $$ = $1;
- }
- | LYRIC_MARKUP
+ LYRIC_MARKUP
{ parser->lexer_->push_markup_state (); }
markup_top {
$$ = $3;
;
full_markup_list:
- MARKUPLIST_IDENTIFIER {
- $$ = $1;
- }
- | MARKUPLIST
+ MARKUPLIST
{ parser->lexer_->push_markup_state (); }
markup_list {
$$ = $3;
;
full_markup:
- MARKUP_IDENTIFIER {
- $$ = $1;
- }
- | MARKUP
+ MARKUP
{ parser->lexer_->push_markup_state (); }
markup_top {
$$ = $3;
markup_list:
- MARKUPLIST_IDENTIFIER {
- $$ = $1;
- }
- | markup_composed_list {
+ markup_composed_list {
$$ = $1;
}
| markup_braced_list {
STRING {
$$ = make_simple_markup ($1);
}
- | MARKUP_IDENTIFIER {
- $$ = $1;
- }
- | LYRIC_MARKUP_IDENTIFIER {
- $$ = $1;
- }
- | STRING_IDENTIFIER {
- $$ = $1;
- }
| SCORE {
SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
parser->lexer_->push_note_state (nn);
int
Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
{
- if (scm_is_string (sid)) {
- *destination = sid;
- return STRING_IDENTIFIER;
- } else if (unsmob_book (sid)) {
+ if (unsmob_book (sid)) {
Book *book = unsmob_book (sid)->clone ();
*destination = book->self_scm ();
book->unprotect ();
*destination = unsmob_context_mod (sid)->smobbed_copy ();
return CONTEXT_MOD_IDENTIFIER;
- } else if (unsmob_score (sid)) {
- Score *score = new Score (*unsmob_score (sid));
- *destination = score->self_scm ();
-
- score->unprotect ();
- return SCORE_IDENTIFIER;
} else if (Music *mus = unsmob_music (sid)) {
mus = mus->clone ();
*destination = mus->self_scm ();
*destination = p->self_scm ();
p->unprotect ();
return OUTPUT_DEF_IDENTIFIER;
- } else if (Text_interface::is_markup (sid)) {
- *destination = sid;
- if (is_lyric_state ())
- return LYRIC_MARKUP_IDENTIFIER;
- return MARKUP_IDENTIFIER;
- } else if (Text_interface::is_markup_list (sid)) {
- *destination = sid;
- return MARKUPLIST_IDENTIFIER;
}
return -1;
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;
}
return arg;
}
+SCM
+try_string_variants (SCM pred, SCM str)
+{
+ // a matching predicate is always ok
+ if (scm_is_true (scm_call_1 (pred, str)))
+ return str;
+ // a symbol may be interpreted as a list of symbols if it helps
+ if (scm_is_symbol (str)) {
+ str = scm_list_1 (str);
+ if (scm_is_true (scm_call_1 (pred, str)))
+ return str;
+ return SCM_UNDEFINED;
+ }
+
+ // If this cannot be a string representation of a symbol list,
+ // we are through.
+
+ if (!is_regular_identifier (str, true))
+ return SCM_UNDEFINED;
+
+ str = scm_string_split (str, SCM_MAKE_CHAR ('.'));
+ for (SCM p = str; scm_is_pair (p); p = scm_cdr (p))
+ scm_set_car_x (p, scm_string_to_symbol (scm_car (p)));
+
+ // Let's attempt the symbol list interpretation first.
+
+ if (scm_is_true (scm_call_1 (pred, str)))
+ return str;
+
+ // If there is just one symbol in the list, we might interpret
+ // it as a single symbol
+
+ if (scm_is_null (scm_cdr (str)))
+ {
+ str = scm_car (str);
+ if (scm_is_true (scm_call_1 (pred, str)))
+ return str;
+ }
+
+ return SCM_UNDEFINED;
+}
+
bool
-is_regular_identifier (SCM id)
+is_regular_identifier (SCM id, bool multiple)
{
+ if (!scm_is_string (id))
+ return false;
+
string str = ly_scm2string (id);
- char const *s = str.c_str ();
- bool v = true;
-#if 0
- isalpha (*s);
- s++;
-#endif
- while (*s && v)
- {
- v = v && isalnum (*s);
- s++;
- }
- return v;
+ bool middle = false;
+
+ for (string::iterator it=str.begin(); it != str.end (); it++)
+ {
+ int c = *it & 0xff;
+ if ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c > 0x7f)
+ middle = true;
+ else if (middle && (c == '-' || c == '_' || (multiple && c == '.')))
+ middle = false;
+ else
+ return false;
+ }
+ return middle;
+}
+
+SCM
+make_music_from_simple (Lily_parser *parser, Input loc, SCM simple)
+{
+ if (unsmob_music (simple))
+ return simple;
+ if (parser->lexer_->is_note_state ()) {
+ 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);
+ 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);
+ 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,
+ parser->default_duration_.smobbed_copy ());
+ } else if (parser->lexer_->is_chord_state ()) {
+ if (unsmob_pitch (simple))
+ return make_chord_elements (loc, simple,
+ parser->default_duration_.smobbed_copy (),
+ SCM_EOL);
+ }
+ return simple;
}
Music *
return t && t == 1 << intlog2 (t);
}
-void
-set_music_properties (Music *p, SCM a)
-{
- for (SCM k = a; scm_is_pair (k); k = scm_cdr (k))
- p->set_property (scm_caar (k), scm_cdar (k));
-}
-
-
SCM
make_chord_step (SCM step_scm, Rational alter)
{