SCM make_simple_markup (SCM a);
SCM make_duration (SCM t, int dots = 0, SCM factor = SCM_UNDEFINED);
bool is_regular_identifier (SCM id, bool multiple=false);
+SCM make_reverse_key_list (SCM keys);
+SCM try_word_variants (SCM pred, SCM str);
SCM try_string_variants (SCM pred, SCM str);
int yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser);
%token STRING
%token SYMBOL_LIST
%token TONICNAME_PITCH
+%token SYMBOL
%left '-' '+'
DECLARATIONS
*/
assignment_id:
- STRING { $$ = $1; }
+ STRING
+ | SYMBOL
;
assignment:
}
| LYRICSTO symbol '=' simple_string lyric_mode_music
{
- $$ = MAKE_SYNTAX (lyric_combine, @$, $3, $2, $4);
+ $$ = MAKE_SYNTAX (lyric_combine, @$, $4, $2, $5);
}
;
}
;
-// symbol_list_part delivers elements in reverse copy.
+// symbol_list_part delivers elements in reverse copy, no lookahead
symbol_list_part:
- symbol_list_element
+ symbol_list_part_bare
+ | embedded_scm_bare
{
- $$ = try_string_variants (Lily::key_list_p, $1);
+ $$ = make_reverse_key_list ($1);
if (SCM_UNBNDP ($$)) {
parser->parser_error (@1, _("not a key"));
$$ = SCM_EOL;
- } else
- $$ = scm_reverse ($$);
+ }
}
;
symbol_list_element:
STRING
- | embedded_scm_bare
+ {
+ $$ = scm_string_to_symbol ($1);
+ }
| UNSIGNED
;
+
symbol_list_part_bare:
- STRING
+ SYMBOL
{
- $$ = try_string_variants (Lily::key_list_p, $1);
+ $$ = try_word_variants (Lily::key_list_p, $1);
if (SCM_UNBNDP ($$)) {
parser->parser_error (@1, _("not a key"));
$$ = SCM_EOL;
} else
$$ = scm_reverse ($$);
}
- | UNSIGNED
+ | symbol_list_element
{
$$ = scm_list_1 ($1);
}
else
MYREPARSE (@4, $2, SCM_ARG, $4);
}
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup SYMBOL
+ {
+ $$ = $3;
+ SCM res = try_word_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, STRING, $4);
+ else
+ MYREPARSE (@4, $2, SCM_ARG, $4);
+ }
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup full_markup
{
$$ = $3;
MYBACKUP (STRING, $4, @4);
}
}
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup SYMBOL
+ {
+ SCM res = try_word_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_copy (parser, @3, $1), $3);
+ MYBACKUP (STRING, $4, @4);
+ }
+ }
| function_arglist_backup REPARSE pitch_or_music
{
if (scm_is_true (scm_call_1 ($2, $3)))
// know the predicate to be false.
MYREPARSE (@3, $1, SCM_ARG, $3);
}
+ | EXPECT_SCM function_arglist_optional SYMBOL
+ {
+ $$ = $2;
+ SCM res = try_word_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 full_markup
{
$$ = $2;
| context_def_mod STRING {
$$ = scm_list_2 ($1, $2);
}
+ | context_def_mod SYMBOL {
+ $$ = scm_list_2 ($1, $2);
+ }
| context_def_mod embedded_scm
{
if (!scm_is_string ($2)
- && ly_symbol2scm ("consists") != $1
- && ly_symbol2scm ("remove") != $1)
+ && !scm_is_eq ($1, ly_symbol2scm ("consists"))
+ && !scm_is_eq ($1, ly_symbol2scm ("remove")))
{
$$ = SCM_EOL;
parser->parser_error (@1, _ ("only \\consists and \\remove take non-string argument."));
string:
STRING
+ | SYMBOL
| full_markup
;
text:
STRING
+ | SYMBOL
| full_markup
| embedded_scm_bare
{
;
simple_string: STRING
+ | SYMBOL
| embedded_scm_bare
{
if (scm_is_string ($1)) {
STRING {
$$ = scm_string_to_symbol ($1);
}
+ | SYMBOL
+ {
+ if (!is_regular_identifier ($1, false))
+ parser->parser_error (@1, (_ ("symbol expected")));
+ $$ = scm_string_to_symbol ($1);
+ }
| embedded_scm_bare
{
// This is a bit of overkill but makes the same
make_simple_markup ($1));
$$ = t->unprotect ();
}
+ | SYMBOL {
+ // Flag a warning? could be unintentional
+ Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
+ t->set_property ("text",
+ make_simple_markup ($1));
+ $$ = t->unprotect ();
+ }
| embedded_scm
{
Music *m = unsmob<Music> ($1);
;
bass_number:
- UNSIGNED { $$ = $1; }
- | STRING { $$ = $1; }
- | full_markup { $$ = $1; }
+ UNSIGNED
+ | STRING
+ | SYMBOL
+ | full_markup
| embedded_scm_bare
{
// as an integer, it needs to be non-negative, and otherwise
parser->parser_error (@1, _ ("markup outside of text script or \\lyricmode"));
$$ = $1;
}
+ | SYMBOL {
+ if (!parser->lexer_->is_lyric_state ())
+ parser->parser_error (@1, _f ("not a note name: %s", ly_scm2string ($1)));
+ $$ = $1;
+ }
| STRING {
if (!parser->lexer_->is_lyric_state ())
- parser->parser_error (@1, _ ("unrecognized string, not in text script or \\lyricmode"));
+ parser->parser_error (@1, _ ("string outside of text script or \\lyricmode"));
$$ = $1;
}
| LYRIC_ELEMENT
STRING {
$$ = make_simple_markup ($1);
}
+ | SYMBOL {
+ $$ = make_simple_markup ($1);
+ }
| SCORE {
parser->lexer_->push_note_state (Lily::pitchnames);
} '{' score_body '}' {
return arg;
}
+SCM
+make_reverse_key_list (SCM keys)
+{
+ if (scm_is_true (Lily::key_p (keys)))
+ return scm_list_1 (keys);
+ if (scm_is_string (keys))
+ return scm_list_1 (scm_string_to_symbol (keys));
+ if (!ly_is_list (keys))
+ return SCM_UNDEFINED;
+ SCM res = SCM_EOL;
+ for (; scm_is_pair (keys); keys = scm_cdr (keys))
+ {
+ SCM elt = scm_car (keys);
+ if (scm_is_true (Lily::key_p (elt)))
+ res = scm_cons (elt, res);
+ else if (scm_is_string (elt))
+ res = scm_cons (scm_string_to_symbol (elt), res);
+ else return SCM_UNDEFINED;
+ }
+ return res;
+}
+
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
+ // a key may be interpreted as a list of keys if it helps
if (scm_is_true (Lily::key_p (str))) {
str = scm_list_1 (str);
if (scm_is_true (scm_call_1 (pred, str)))
return SCM_UNDEFINED;
}
+ if (!scm_is_string (str))
+ return SCM_UNDEFINED;
+
+ // Let's attempt the symbol list interpretation first.
+
+ str = scm_string_to_symbol (str);
+
+ SCM lst = scm_list_1 (str);
+
+ if (scm_is_true (scm_call_1 (pred, lst)))
+ return lst;
+
+ // Try the single symbol interpretation
+
+ if (scm_is_true (scm_call_1 (pred, str)))
+ return str;
+
+ return SCM_UNDEFINED;
+}
+
+SCM
+try_word_variants (SCM pred, SCM str)
+{
+ // str is always a string when we come here
+
+ if (scm_is_true (scm_call_1 (pred, str)))
+ return str;
+
// If this cannot be a string representation of a symbol list,
// we are through.
{
if (unsmob<Music> (simple))
return simple;
- if (parser->lexer_->is_note_state ()) {
- if (scm_is_symbol (simple)) {
+
+ if (scm_is_symbol (simple))
+ {
+ SCM out = SCM_UNDEFINED;
+ switch (parser->lexer_->scan_word (out, simple))
+ {
+ case DRUM_PITCH:
+ {
Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
n->set_property ("duration", parser->default_duration_.smobbed_copy ());
- n->set_property ("drum-type", simple);
+ n->set_property ("drum-type", out);
return n->unprotect ();
}
+ case NOTENAME_PITCH:
+ case TONICNAME_PITCH:
+ // Take the parsed pitch
+ simple = out;
+ break;
+ // Don't scan CHORD_MODIFIER etc.
+ }
+ }
+
+ if (parser->lexer_->is_note_state ()) {
if (unsmob<Pitch> (simple)) {
Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
n->set_property ("duration", parser->default_duration_.smobbed_copy ());