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);
%token SCM_FUNCTION
%token SCM_IDENTIFIER
%token SCM_TOKEN
-%token SCORE_IDENTIFIER
%token STRING
%token SYMBOL_LIST
%token TONICNAME_PITCH
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
{
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);
+ $$ = check_scheme_arg (parser, @4,
+ try_string_variants ($2, $4),
+ $3, $2, $4);
}
| 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
{
symbol_list_element
{
SCM sym_l_p = ly_lily_module_constant ("symbol-list?");
- if (scm_is_true (scm_call_1 (sym_l_p, $1)))
- $$ = scm_reverse ($1);
- else {
- $$ = try_string_variants (sym_l_p, $1);
- if (SCM_UNBNDP ($$)) {
- parser->parser_error (@1, _("not a symbol"));
- $$ = SCM_EOL;
- }
- }
+ $$ = try_string_variants (sym_l_p, $1);
+ if (SCM_UNBNDP ($$)) {
+ parser->parser_error (@1, _("not a symbol"));
+ $$ = SCM_EOL;
+ } else
+ $$ = scm_reverse ($$);
}
;
make_simple_markup ($1));
$$ = t->unprotect ();
}
- | embedded_scm_bare
+ | embedded_scm_closed
{
Music *m = unsmob_music ($1);
if (m && m->is_mus_type ("post-event"))
*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 ();
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;
}
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;
- if (scm_is_string (str))
- {
- if (!is_regular_identifier (str))
- return SCM_UNDEFINED;
-
- str = scm_string_to_symbol (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;
- } else if (!scm_is_symbol (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.
- str = scm_list_1 (str);
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;
|| (c >= 'A' && c <= 'Z')
|| c > 0x7f)
middle = true;
- else if (middle && (c == '-' || c == '_'))
+ else if (middle && (c == '-' || c == '_' || (multiple && c == '.')))
middle = false;
else
return false;
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,