]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/parser.yy
Replace WORD token in parser and lexer with SYMBOL
[lilypond.git] / lily / parser.yy
index 1695aea6259d838f12655f412692210e251eeb4e..f81dc69e9b56faa2e82b4052f86448b492c1a347 100644 (file)
@@ -229,12 +229,14 @@ 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 disp = SCM_UNDEFINED);
 SCM make_music_from_simple (Lily_parser *parser, Input loc, SCM pitch);
-SCM loc_on_music (Lily_parser *parser, Input loc, SCM arg);
+SCM loc_on_copy (Lily_parser *parser, 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);
 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);
 
@@ -346,7 +348,6 @@ If we give names, Bison complains.
 %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
@@ -374,6 +375,7 @@ If we give names, Bison complains.
 %token STRING
 %token SYMBOL_LIST
 %token TONICNAME_PITCH
+%token SYMBOL
 
 %left '-' '+'
 
@@ -409,10 +411,8 @@ lilypond:  /* empty */ { $$ = SCM_UNSPECIFIED; }
 
 
 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");
@@ -475,6 +475,12 @@ toplevel_expression:
                                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"));
        }
@@ -497,8 +503,8 @@ lookup:
        LOOKUP_IDENTIFIER
        | LOOKUP_IDENTIFIER '.' symbol_list_rev
        {
-               $$ = loc_on_music (parser, @$,
-                                  nested_property ($1, scm_reverse_x ($3, SCM_EOL)));
+               $$ = loc_on_copy (parser, @$,
+                                 nested_property ($1, scm_reverse_x ($3, SCM_EOL)));
        }
        ;
 
@@ -526,6 +532,7 @@ embedded_scm_bare_arg:
        | partial_markup
        | full_markup_list
        | context_modification
+       | header_block
        | score_block
        | context_def_spec_block
        | book_block
@@ -634,8 +641,15 @@ lilypond_header_body:
        | 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"));
        }
        ;
 
@@ -645,11 +659,20 @@ lilypond_header:
        }
        ;
 
+header_block:
+       {
+               parser->lexer_->add_scope (get_header (parser));
+       } lilypond_header {
+               $$ = $2;
+       }
+       ;
+
 /*
        DECLARATIONS
 */
 assignment_id:
-       STRING          { $$ = $1; }
+       STRING
+       | SYMBOL
        ;
 
 assignment:
@@ -706,7 +729,8 @@ identifier_init:
        ;
 
 identifier_init_nonumber:
-       score_block
+       header_block
+       | score_block
        | book_block
        | bookpart_block
        | output_def
@@ -955,16 +979,15 @@ book_body:
                        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"));
        }
@@ -1036,16 +1059,16 @@ bookpart_body:
                        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"));
        }
@@ -1144,6 +1167,22 @@ score_items:
                                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"));
        }
@@ -1458,14 +1497,6 @@ context_modification:
                 parser->lexer_->pop_state ();
                 $$ = $4;
         }
-        | WITH CONTEXT_MOD_IDENTIFIER
-        {
-                $$ = $2;
-        }
-        | CONTEXT_MOD_IDENTIFIER
-        {
-                $$ = $1;
-        }
        | WITH context_modification_arg
        {
                if (unsmob<Music> ($2)) {
@@ -1475,7 +1506,10 @@ context_modification:
                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 ();
                }
        }
@@ -1486,16 +1520,40 @@ context_modification_arg:
        | 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 ();
@@ -1504,58 +1562,34 @@ context_mod_list:
                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);
        }
        ;
 
@@ -1584,7 +1618,7 @@ basic_music:
        }
        | LYRICSTO symbol '=' simple_string lyric_mode_music
        {
-               $$ = MAKE_SYNTAX (lyric_combine, @$, $3, $2, $4);
+               $$ = MAKE_SYNTAX (lyric_combine, @$, $4, $2, $5);
        }
        ;
 
@@ -1709,38 +1743,41 @@ symbol_list_rev:
        }
        ;
 
-// 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);
        }
@@ -1897,6 +1934,23 @@ function_arglist_nonbackup_reparse:
                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;
@@ -1962,7 +2016,7 @@ function_arglist_backup:
                                $$ = scm_cons ($$, $3);
                        else
                        {
-                               $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                               $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                                MYBACKUP (SCM_ARG, $4, @4);
                        }
                }
@@ -1973,7 +2027,7 @@ function_arglist_backup:
                {
                        $$ = scm_cons ($4, $3);
                } else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (EVENT_IDENTIFIER, $4, @4);
                }
        }
@@ -1989,7 +2043,7 @@ function_arglist_backup:
                } else if (scm_is_true (scm_call_1 ($2, $4)))
                        $$ = scm_cons ($4, $3);
                else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (PITCH_IDENTIFIER, $4, @4);
                }
        }
@@ -2005,7 +2059,7 @@ function_arglist_backup:
                } else if (scm_is_true (scm_call_1 ($2, $4)))
                        $$ = scm_cons ($4, $3);
                else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (TONICNAME_PITCH, $4, @4);
                }
        }
@@ -2014,7 +2068,7 @@ function_arglist_backup:
                if (scm_is_true (scm_call_1 ($2, $4)))
                        $$ = scm_cons ($4, $3);
                else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (SCM_IDENTIFIER, $4, @4);
                }
        }
@@ -2036,11 +2090,11 @@ function_arglist_backup:
                                          ($2, make_music_from_simple (parser, @4, d))))
                                        MYREPARSE (@4, $2, DURATION_ARG, d);
                                else {
-                                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                                        MYBACKUP (UNSIGNED, $4, @4);
                                }
                        } else {
-                               $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                               $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                                MYBACKUP (UNSIGNED, $4, @4);
                        }
                }
@@ -2052,7 +2106,7 @@ function_arglist_backup:
                        $$ = $3;
                        MYREPARSE (@4, $2, REAL, $4);
                } else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (REAL, $4, @4);
                }
        }
@@ -2062,7 +2116,7 @@ function_arglist_backup:
                {
                        $$ = scm_cons ($4, $3);
                } else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (NUMBER_IDENTIFIER, $4, @4);
                }
        }
@@ -2079,7 +2133,7 @@ function_arglist_backup:
                        if (scm_is_true (scm_call_1 ($2, $$)))
                                $$ = scm_cons ($$, $3);
                        else {
-                               $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                               $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                                MYBACKUP (UNSIGNED, $5, @5);
                                parser->lexer_->push_extra_token (@4, '-');
                        }
@@ -2092,7 +2146,7 @@ function_arglist_backup:
                        MYREPARSE (@5, $2, REAL, n);
                        $$ = $3;
                } else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (REAL, n, @5);
                }
        }
@@ -2102,7 +2156,7 @@ function_arglist_backup:
                if (scm_is_true (scm_call_1 ($2, n))) {
                        $$ = scm_cons (n, $3);
                } else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (NUMBER_IDENTIFIER, n, @5);
                }
        }
@@ -2116,7 +2170,7 @@ function_arglist_backup:
                          ($2, make_music_from_simple (parser, @4, $4))))
                        MYREPARSE (@4, $2, DURATION_ARG, $4);
                else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (DURATION_IDENTIFIER, $4, @4);
                }
        }
@@ -2131,7 +2185,7 @@ function_arglist_backup:
                        else
                                $$ = scm_cons (res, $3);
                else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
                        MYBACKUP (SCM_IDENTIFIER, $4, @4);
                }
        }
@@ -2146,7 +2200,22 @@ function_arglist_backup:
                        else
                                $$ = scm_cons (res, $3);
                else {
-                       $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+                       $$ = scm_cons (loc_on_copy (parser, @3, $1), $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);
                }
        }
@@ -2185,7 +2254,7 @@ function_arglist:
        function_arglist_nonbackup
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_nonbackup DEFAULT
        {
-               $$ = scm_cons (loc_on_music (parser, @4, $1), $3);
+               $$ = scm_cons (loc_on_copy (parser, @4, $1), $3);
        }
        ;
 
@@ -2193,7 +2262,7 @@ function_arglist_skip_nonbackup:
        function_arglist_nonbackup
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_nonbackup
        {
-               $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+               $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
        }
        ;
 
@@ -2376,6 +2445,24 @@ function_arglist_common_reparse:
                        // 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;
@@ -2453,7 +2540,7 @@ function_arglist_optional:
        function_arglist_backup
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_backup DEFAULT
        {
-               $$ = scm_cons (loc_on_music (parser, @4, $1), $3);
+               $$ = scm_cons (loc_on_copy (parser, @4, $1), $3);
        }
        | function_arglist_skip_backup BACKUP
        ;
@@ -2462,7 +2549,7 @@ function_arglist_skip_backup:
        function_arglist_backup
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_backup
        {
-               $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+               $$ = scm_cons (loc_on_copy (parser, @3, $1), $3);
        }
        ;
 
@@ -2510,12 +2597,8 @@ mode_changed_music:
                }
                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, @$, $$);
@@ -2690,11 +2773,14 @@ context_mod:
        | 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."));
@@ -2832,11 +2918,13 @@ music_property_def:
 
 string:
        STRING
+       | SYMBOL
        | full_markup
        ;
 
 text:
        STRING
+       | SYMBOL
        | full_markup
        | embedded_scm_bare
        {
@@ -2850,6 +2938,7 @@ text:
        ;
 
 simple_string: STRING
+       | SYMBOL
        | embedded_scm_bare
        {
                if (scm_is_string ($1)) {
@@ -2865,6 +2954,12 @@ symbol:
        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
@@ -2916,15 +3011,11 @@ event_chord:
                }
        } %prec ':'
        | CHORD_REPETITION optional_notemode_duration post_events {
-               Input i;
-               i.set_location (@1, @3);
-               $$ = MAKE_SYNTAX (repetition_chord, i,
+               $$ = MAKE_SYNTAX (repetition_chord, @$,
                                  $2, scm_reverse_x ($3, SCM_EOL));
        } %prec ':'
        | MULTI_MEASURE_REST optional_notemode_duration post_events {
-               Input i;
-               i.set_location (@1, @3);
-               $$ = MAKE_SYNTAX (multi_measure_rest, i, $2,
+               $$ = MAKE_SYNTAX (multi_measure_rest, @$, $2,
                                  scm_reverse_x ($3, SCM_EOL));
        } %prec ':'
        | tempo_event
@@ -3250,6 +3341,13 @@ gen_text_def:
                        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);
@@ -3388,9 +3486,10 @@ tremolo_type:
        ;
 
 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
@@ -3576,9 +3675,14 @@ lyric_element:
                        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
@@ -3964,6 +4068,9 @@ simple_markup:
        STRING {
                $$ = make_simple_markup ($1);
        }
+       | SYMBOL {
+               $$ = make_simple_markup ($1);
+       }
        | SCORE {
                parser->lexer_->push_note_state (Lily::pitchnames);
        } '{' score_body '}' {
@@ -4048,7 +4155,7 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
                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 ();
@@ -4124,7 +4231,7 @@ SCM check_scheme_arg (Lily_parser *parser, Input loc,
        return args;
 }
 
-SCM loc_on_music (Lily_parser *parser, Input loc, SCM arg)
+SCM loc_on_copy (Lily_parser *parser, Input loc, SCM arg)
 {
        if (Music *m = unsmob<Music> (arg))
        {
@@ -4132,16 +4239,66 @@ SCM loc_on_music (Lily_parser *parser, Input loc, SCM arg)
                m->set_spot (parser->lexer_->override_input (loc));
                return m->unprotect ();
        }
+       if (Book *b = unsmob<Book> (arg))
+       {
+               b = b->clone ();
+               b->origin ()->set_spot (parser->lexer_->override_input (loc));
+               return b->unprotect ();
+       }
+       if (Context_def *cd = unsmob<Context_def> (arg))
+       {
+               cd = cd->clone ();
+               cd->origin ()->set_spot (parser->lexer_->override_input (loc));
+               return cd->unprotect ();
+       }
+       if (Output_def *od = unsmob<Output_def> (arg))
+       {
+               od = od->clone ();
+               od->input_origin_ = parser->lexer_->override_input (loc);
+               return od->unprotect ();
+       }
+       if (Score *s = unsmob<Score> (arg))
+       {
+               s = s->clone ();
+               s->origin ()->set_spot (parser->lexer_->override_input (loc));
+               return s->unprotect ();
+       }
+       if (Context_mod *cm = unsmob<Context_mod> (arg))
+       {
+               return cm->smobbed_copy ();
+       }
        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)))
@@ -4149,6 +4306,34 @@ try_string_variants (SCM pred, SCM 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.
 
@@ -4212,13 +4397,29 @@ 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)) {
+
+       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 ());