]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.yy
Merge branch 'master' into translation
[lilypond.git] / lily / parser.yy
1 /* -*- mode: c++; c-file-style: "linux"; indent-tabs-mode: t -*- */
2 /*
3   This file is part of LilyPond, the GNU music typesetter.
4
5   Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
6                  Jan Nieuwenhuizen <janneke@gnu.org>
7
8   LilyPond is free software: you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation, either version 3 of the License, or
11   (at your option) any later version.
12
13   LilyPond is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* Mode and indentation are at best a rough approximation based on TAB
23  * formatting (reasonable for compatibility with unspecific editor
24  * modes as Bison modes are hard to find) and need manual correction
25  * frequently.  Without a reasonably dependable way of formatting a
26  * Bison file sensibly, there is little point in trying to fix the
27  * inconsistent state of indentation.
28  */
29
30 %{
31
32 #define yyerror Lily_parser::parser_error
33
34 /* We use custom location type: Input objects */
35 #define YYLTYPE Input
36 #define YYSTYPE SCM
37 #define YYLLOC_DEFAULT(Current,Rhs,N) \
38         ((Current).set_location ((Rhs)[1], (Rhs)[N]))
39
40 #define YYPRINT(file, type, value)                                      \
41         do {                                                            \
42                 if (scm_is_eq (value, SCM_UNSPECIFIED))                 \
43                         break;                                          \
44                 SCM s = Display::value_to_lily_string (value);          \
45                 char *p = scm_to_locale_string (s);                     \
46                 fputs (p, file);                                        \
47                 free (p);                                               \
48         } while (0)
49
50 %}
51
52 %parse-param {Lily_parser *parser}
53 %parse-param {SCM *retval}
54 %lex-param {Lily_parser *parser}
55 %error-verbose
56 %debug
57
58 /* We use SCMs to do strings, because it saves us the trouble of
59 deleting them.  Let's hope that a stack overflow doesn't trigger a move
60 of the parse stack onto the heap. */
61
62 %left PREC_BOT
63 %nonassoc REPEAT
64 %nonassoc ALTERNATIVE
65
66 /* The above precedences tackle the shift/reduce problem
67
68 1.  \repeat
69         \repeat .. \alternative
70
71     \repeat { \repeat .. \alternative }
72
73 or
74
75     \repeat { \repeat } \alternative
76 */
77
78 %nonassoc COMPOSITE
79 %left ADDLYRICS
80
81 %right ':' UNSIGNED REAL E_UNSIGNED EVENT_IDENTIFIER EVENT_FUNCTION '^' '_'
82        HYPHEN EXTENDER DURATION_IDENTIFIER '!'
83
84  /* The above are needed for collecting tremoli and other items (that
85     could otherwise be interpreted as belonging to the next function
86     argument) greedily, and together with the next rule will serve to
87     join numbers and units greedily instead of allowing them into
88     separate function arguments
89  */
90
91 %nonassoc NUMBER_IDENTIFIER
92
93 %left PREC_TOP
94
95
96
97
98 %pure-parser
99 %locations
100
101
102
103 %{ // -*-Fundamental-*-
104
105 /*
106 FIXME:
107
108    * The rules for who is protecting what are very shady.  Uniformise
109      this.
110
111    * There are too many lexical modes?
112 */
113
114 #include "config.hh"
115
116 #include <cctype>
117 #include <cstdlib>
118 #include <cstdio>
119 using namespace std;
120
121 #include "book.hh"
122 #include "context-def.hh"
123 #include "context-mod.hh"
124 #include "dimensions.hh"
125 #include "file-path.hh"
126 #include "input.hh"
127 #include "international.hh"
128 #include "lily-guile.hh"
129 #include "lily-lexer.hh"
130 #include "lily-parser.hh"
131 #include "ly-module.hh"
132 #include "main.hh"
133 #include "misc.hh"
134 #include "music.hh"
135 #include "output-def.hh"
136 #include "paper-book.hh"
137 #include "scm-hash.hh"
138 #include "score.hh"
139 #include "text-interface.hh"
140 #include "warn.hh"
141 #include "lily-imports.hh"
142
143 void
144 Lily_parser::parser_error (Input const *i, Lily_parser *parser, SCM *, const string &s)
145 {
146         parser->parser_error (*i, s);
147 }
148
149 // The following are somewhat precarious constructs as they may change
150 // the value of the lookahead token.  That implies that the lookahead
151 // token must not yet have made an impact on the state stack other
152 // than causing the reduction of the current rule, or switching the
153 // lookahead token while Bison is mulling it over will cause trouble.
154
155 #define MYBACKUP(Token, Value, Location)                                \
156         do {                                                            \
157                 if (yychar != YYEMPTY)                                  \
158                         parser->lexer_->push_extra_token                \
159                                 (yylloc, yychar, yylval);               \
160                 if (Token)                                              \
161                         parser->lexer_->push_extra_token                \
162                                 (Location, Token, Value);               \
163                 parser->lexer_->push_extra_token (Location, BACKUP);    \
164                 yychar = YYEMPTY;                                       \
165         } while (0)
166
167
168 #define MYREPARSE(Location, Pred, Token, Value)                         \
169         do {                                                            \
170                 if (yychar != YYEMPTY)                                  \
171                         parser->lexer_->push_extra_token                \
172                                 (yylloc, yychar, yylval);               \
173                 parser->lexer_->push_extra_token                        \
174                         (Location, Token, Value);                       \
175                 parser->lexer_->push_extra_token                        \
176                         (Location, REPARSE, Pred);                      \
177                 yychar = YYEMPTY;                                       \
178         } while (0)
179
180 %}
181
182
183 %{
184
185 #define MY_MAKE_MUSIC(x, spot) \
186         make_music_with_input (ly_symbol2scm (x), \
187                                parser->lexer_->override_input (spot))
188
189 /* ES TODO:
190 - delay application of the function
191 */
192
193 #define LOWLEVEL_MAKE_SYNTAX(location, proc, ...)                       \
194         with_location                                                   \
195                 (parser->lexer_->override_input (location).smobbed_copy (), \
196                  proc,                                                  \
197                  ##__VA_ARGS__)
198
199 /* Syntactic Sugar. */
200 #define MAKE_SYNTAX(name, location, ...)                                \
201         LOWLEVEL_MAKE_SYNTAX (location, Syntax::name, ##__VA_ARGS__)
202
203 #define START_MAKE_SYNTAX(name, ...)                                    \
204         scm_list_n (Syntax::name, ##__VA_ARGS__, SCM_UNDEFINED)
205
206 #define FINISH_MAKE_SYNTAX(start, location, ...)                        \
207         LOWLEVEL_MAKE_SYNTAX                                            \
208                 (location,                                              \
209                  Guile_user::apply,                                     \
210                  scm_car (start),                                       \
211                  scm_append_x                                           \
212                  (scm_list_2 (scm_cdr (start),                          \
213                               scm_list_n (__VA_ARGS__, SCM_UNDEFINED))))
214
215 SCM get_next_unique_context_id ();
216 SCM get_next_unique_lyrics_context_id ();
217
218 #undef _
219 #if !HAVE_GETTEXT
220 #define _(x) x
221 #else
222 #include <libintl.h>
223 #define _(x) gettext (x)
224 #endif
225
226
227 static Music *make_music_with_input (SCM name, Input where);
228 SCM check_scheme_arg (Lily_parser *parser, Input loc,
229                       SCM arg, SCM args, SCM pred, SCM disp = SCM_UNDEFINED);
230 SCM make_music_from_simple (Lily_parser *parser, Input loc, SCM pitch);
231 SCM loc_on_music (Lily_parser *parser, Input loc, SCM arg);
232 SCM make_chord_elements (Input loc, SCM pitch, SCM dur, SCM modification_list);
233 SCM make_chord_step (SCM step, Rational alter);
234 SCM make_simple_markup (SCM a);
235 SCM make_duration (SCM t, int dots = 0);
236 bool is_regular_identifier (SCM id, bool multiple=false);
237 SCM try_string_variants (SCM pred, SCM str);
238 int yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser);
239
240 %}
241
242 /* The third option is an alias that will be used to display the
243    syntax error.  Bison CVS now correctly handles backslash escapes.
244
245    FIXME: Bison needs to translate some of these, eg, STRING.
246
247 */
248
249 /* Keyword tokens with plain escaped name.  */
250 %token END_OF_FILE 0 "end of input"
251 %token ACCEPTS "\\accepts"
252 %token ADDLYRICS "\\addlyrics"
253 %token ALIAS "\\alias"
254 %token ALTERNATIVE "\\alternative"
255 %token BOOK "\\book"
256 %token BOOKPART "\\bookpart"
257 %token CHANGE "\\change"
258 %token CHORDMODE "\\chordmode"
259 %token CHORDS "\\chords"
260 %token CONSISTS "\\consists"
261 %token CONTEXT "\\context"
262 %token DEFAULT "\\default"
263 %token DEFAULTCHILD "\\defaultchild"
264 %token DENIES "\\denies"
265 %token DESCRIPTION "\\description"
266 %token DRUMMODE "\\drummode"
267 %token DRUMS "\\drums"
268 %token ETC "\\etc"
269 %token FIGUREMODE "\\figuremode"
270 %token FIGURES "\\figures"
271 %token HEADER "\\header"
272 %token INVALID "\\version-error"
273 %token LAYOUT "\\layout"
274 %token LYRICMODE "\\lyricmode"
275 %token LYRICS "\\lyrics"
276 %token LYRICSTO "\\lyricsto"
277 %token MARKUP "\\markup"
278 %token MARKUPLIST "\\markuplist"
279 %token MIDI "\\midi"
280 %token NAME "\\name"
281 %token NOTEMODE "\\notemode"
282 %token OVERRIDE "\\override"
283 %token PAPER "\\paper"
284 %token REMOVE "\\remove"
285 %token REPEAT "\\repeat"
286 %token REST "\\rest"
287 %token REVERT "\\revert"
288 %token SCORE "\\score"
289 %token SCORELINES "\\score-lines"
290 %token SEQUENTIAL "\\sequential"
291 %token SET "\\set"
292 %token SIMULTANEOUS "\\simultaneous"
293 %token TEMPO "\\tempo"
294 %token TYPE "\\type"
295 %token UNSET "\\unset"
296 %token WITH "\\with"
297
298 /* Keyword token exceptions.  */
299 %token NEWCONTEXT "\\new"
300
301
302 /* Other string tokens.  */
303
304 %token CHORD_BASS "/+"
305 %token CHORD_CARET "^"
306 %token CHORD_COLON ":"
307 %token CHORD_MINUS "-"
308 %token CHORD_SLASH "/"
309 %token ANGLE_OPEN "<"
310 %token ANGLE_CLOSE ">"
311 %token DOUBLE_ANGLE_OPEN "<<"
312 %token DOUBLE_ANGLE_CLOSE ">>"
313 %token E_BACKSLASH "\\"
314 %token E_EXCLAMATION "\\!"
315 %token E_PLUS "\\+"
316 %token EXTENDER "__"
317
318 /*
319 If we give names, Bison complains.
320 */
321 %token FIGURE_CLOSE /* "\\>" */
322 %token FIGURE_OPEN /* "\\<" */
323 %token FIGURE_SPACE "_"
324 %token HYPHEN "--"
325
326 %token MULTI_MEASURE_REST
327
328
329 %token E_UNSIGNED
330 %token UNSIGNED
331
332 /* Artificial tokens, for more generic function syntax */
333 %token EXPECT_MARKUP "markup?"
334 %token EXPECT_SCM "scheme?"
335 %token BACKUP "(backed-up?)"
336 %token REPARSE "(reparsed?)"
337 %token EXPECT_MARKUP_LIST "markup-list?"
338 %token EXPECT_OPTIONAL "optional?"
339 /* After the last argument. */
340 %token EXPECT_NO_MORE_ARGS;
341
342 /* An artificial token for parsing embedded Lilypond */
343 %token EMBEDDED_LILY "#{"
344
345 %token BOOK_IDENTIFIER
346 %token CHORD_MODIFIER
347 %token CHORD_REPETITION
348 %token CONTEXT_MOD_IDENTIFIER
349 %token DRUM_PITCH
350 %token PITCH_IDENTIFIER
351 %token DURATION_IDENTIFIER
352 %token EVENT_IDENTIFIER
353 %token EVENT_FUNCTION
354 %token FRACTION
355 %token LYRIC_ELEMENT
356 %token MARKUP_FUNCTION
357 %token MARKUP_LIST_FUNCTION
358 %token MARKUP_IDENTIFIER
359 %token MARKUPLIST_IDENTIFIER
360 %token MUSIC_FUNCTION
361 %token MUSIC_IDENTIFIER
362 %token NOTENAME_PITCH
363 %token NUMBER_IDENTIFIER
364 %token REAL
365 %token RESTNAME
366 %token SCM_ARG
367 %token SCM_FUNCTION
368 %token SCM_IDENTIFIER
369 %token SCM_TOKEN
370 %token STRING
371 %token SYMBOL_LIST
372 %token TONICNAME_PITCH
373
374 %left '-' '+'
375
376 /* We don't assign precedence to / and *, because we might need varied
377 prec levels in different prods */
378
379 %left UNARY_MINUS
380
381 %%
382
383 start_symbol:
384         lilypond
385         | EMBEDDED_LILY {
386                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
387                 parser->lexer_->push_note_state (nn);
388         } embedded_lilypond {
389                 parser->lexer_->pop_state ();
390                 *retval = $3;
391         }
392         ;
393
394 lilypond:       /* empty */ { $$ = SCM_UNSPECIFIED; }
395         | lilypond toplevel_expression {
396         }
397         | lilypond assignment {
398         }
399         | lilypond error {
400                 parser->error_level_ = 1;
401         }
402         | lilypond INVALID      {
403                 parser->error_level_ = 1;
404         }
405         ;
406
407
408 toplevel_expression:
409         {
410                 parser->lexer_->add_scope (get_header (parser));
411         } lilypond_header {
412                 parser->lexer_->set_identifier (ly_symbol2scm ("$defaultheader"), $2);
413         }
414         | book_block {
415                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-book-handler");
416                 scm_call_1 (proc, $1);
417         }
418         | bookpart_block {
419                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-bookpart-handler");
420                 scm_call_1 (proc, $1);
421         }
422         | BOOK_IDENTIFIER {
423                 SCM proc = parser->lexer_->lookup_identifier
424                         (unsmob<Book>($1)->paper_
425                          ? "toplevel-book-handler"
426                          : "toplevel-bookpart-handler");
427                 scm_call_1 (proc, $1);
428         }
429         | score_block {
430                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-score-handler");
431                 scm_call_1 (proc, $1);
432         }
433         | composite_music {
434                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-music-handler");
435                 scm_call_1 (proc, $1);
436         }
437         | full_markup {
438                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
439                 scm_call_1 (proc, scm_list_1 ($1));
440         }
441         | full_markup_list {
442                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
443                 scm_call_1 (proc, $1);
444         }
445         | SCM_TOKEN {
446                 // Evaluate and ignore #xxx, as opposed to \xxx
447                 parser->lexer_->eval_scm_token ($1, @1);
448         }
449         | embedded_scm_active
450         {
451                 SCM out = SCM_UNDEFINED;
452                 if (Text_interface::is_markup ($1))
453                         out = scm_list_1 ($1);
454                 else if (Text_interface::is_markup_list ($1))
455                         out = $1;
456                 if (scm_is_pair (out))
457                 {
458                         SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
459                         scm_call_1 (proc, out);
460                 } else if (unsmob<Score> ($1))
461                 {
462                         SCM proc = parser->lexer_->lookup_identifier ("toplevel-score-handler");
463                         scm_call_1 (proc, $1);
464                 } else if (Output_def * od = unsmob<Output_def> ($1)) {
465                         SCM id = SCM_EOL;
466
467                         if (to_boolean (od->c_variable ("is-paper")))
468                                 id = ly_symbol2scm ("$defaultpaper");
469                         else if (to_boolean (od->c_variable ("is-midi")))
470                                 id = ly_symbol2scm ("$defaultmidi");
471                         else if (to_boolean (od->c_variable ("is-layout")))
472                                 id = ly_symbol2scm ("$defaultlayout");
473
474                         parser->lexer_->set_identifier (id, $1);
475                 } else if (!scm_is_eq ($1, SCM_UNSPECIFIED))
476                         parser->parser_error (@1, _("bad expression type"));
477         }
478         | output_def {
479                 SCM id = SCM_EOL;
480                 Output_def * od = unsmob<Output_def> ($1);
481
482                 if (to_boolean (od->c_variable ("is-paper")))
483                         id = ly_symbol2scm ("$defaultpaper");
484                 else if (to_boolean (od->c_variable ("is-midi")))
485                         id = ly_symbol2scm ("$defaultmidi");
486                 else if (to_boolean (od->c_variable ("is-layout")))
487                         id = ly_symbol2scm ("$defaultlayout");
488
489                 parser->lexer_->set_identifier (id, $1);
490         }
491         ;
492
493 embedded_scm_bare:
494         SCM_TOKEN
495         {
496                 $$ = parser->lexer_->eval_scm_token ($1, @1);
497         }
498         | SCM_IDENTIFIER
499         ;
500
501 embedded_scm_active:
502         SCM_IDENTIFIER
503         | scm_function_call
504         ;
505
506 embedded_scm_bare_arg:
507         SCM_ARG
508         | SCM_TOKEN
509         {
510                 $$ = parser->lexer_->eval_scm_token ($1, @1);
511         }
512         | FRACTION
513         | partial_markup
514         | full_markup_list
515         | context_modification
516         | score_block
517         | context_def_spec_block
518         | book_block
519         | bookpart_block
520         | output_def
521         ;
522
523 /* The generic version may end in music, or not */
524
525 embedded_scm:
526         embedded_scm_bare
527         | scm_function_call
528         ;
529
530 /* embedded_scm_arg is _not_ casting pitches to music by default, this
531  * has to be done by the function itself.  Note that this may cause
532  * the results of scm_function_call or embedded_scm_bare_arg to be
533  * turned into music from pitches as well.  Note that this creates a
534  * distinctly awkward situation for calculated drum pitches.  Those
535  * are at the current point of time rejected as music constituents as
536  * they can't be distinguished from "proper" symbols.
537  */
538
539 embedded_scm_arg:
540         embedded_scm_bare_arg
541         | scm_function_call
542         | music_assign
543         ;
544
545 scm_function_call:
546         SCM_FUNCTION function_arglist {
547                 $$ = MAKE_SYNTAX (music_function, @$,
548                                   $1, $2);
549         }
550         ;
551
552 embedded_lilypond_number:
553         '-' embedded_lilypond_number
554         {
555                 $$ = scm_difference ($2, SCM_UNDEFINED);
556         }
557         | bare_number_common
558         | UNSIGNED NUMBER_IDENTIFIER
559         {
560                 $$ = scm_product ($1, $2);
561         }
562         ;
563
564 embedded_lilypond:
565         /* empty */
566         {
567                 // FIXME: @$ does not contain a useful source location
568                 // for empty rules, and the only token in the whole
569                 // production, EMBEDDED_LILY, is synthetic and also
570                 // contains no source location.
571                 $$ = MAKE_SYNTAX (void_music, @$);
572         }
573         | identifier_init_nonumber
574         | embedded_lilypond_number
575         | post_event post_events
576         {
577                 $$ = scm_reverse_x ($2, SCM_EOL);
578                 if (Music *m = unsmob<Music> ($1))
579                 {
580                         if (m->is_mus_type ("post-event-wrapper"))
581                                 $$ = scm_append
582                                         (scm_list_2 (m->get_property ("elements"),
583                                                      $$));
584                         else
585                                 $$ = scm_cons ($1, $$);
586                 }
587                 if (scm_is_pair ($$)
588                     && scm_is_null (scm_cdr ($$)))
589                         $$ = scm_car ($$);
590                 else
591                 {
592                         Music * m = MY_MAKE_MUSIC ("PostEvents", @$);
593                         m->set_property ("elements", $$);
594                         $$ = m->unprotect ();
595                 }
596         }
597         | multiplied_duration
598         | music_embedded music_embedded music_list {
599                 $3 = scm_reverse_x ($3, SCM_EOL);
600                 if (unsmob<Music> ($2))
601                         $3 = scm_cons ($2, $3);
602                 if (unsmob<Music> ($1))
603                         $3 = scm_cons ($1, $3);
604                 $$ = MAKE_SYNTAX (sequential_music, @$, $3);
605         }
606         | error {
607                 parser->error_level_ = 1;
608                 $$ = SCM_UNSPECIFIED;
609         }
610         | INVALID embedded_lilypond {
611                 parser->error_level_ = 1;
612                 $$ = $2;
613         }
614         ;
615
616
617 lilypond_header_body:
618         /* empty */ { $$ = SCM_UNSPECIFIED; }
619         | lilypond_header_body assignment  {
620
621         }
622         | lilypond_header_body embedded_scm  {
623
624         }
625         ;
626
627 lilypond_header:
628         HEADER '{' lilypond_header_body '}'     {
629                 $$ = parser->lexer_->remove_scope ();
630         }
631         ;
632
633 /*
634         DECLARATIONS
635 */
636 assignment_id:
637         STRING          { $$ = $1; }
638         ;
639
640 assignment:
641         assignment_id '=' identifier_init  {
642                 parser->lexer_->set_identifier ($1, $3);
643                 $$ = SCM_UNSPECIFIED;
644         }
645         | assignment_id property_path '=' identifier_init {
646                 SCM path = scm_cons (scm_string_to_symbol ($1), $2);
647                 parser->lexer_->set_identifier (path, $4);
648                 $$ = SCM_UNSPECIFIED;
649         }
650         | assignment_id '.' property_path '=' identifier_init {
651                 SCM path = scm_cons (scm_string_to_symbol ($1), $3);
652                 parser->lexer_->set_identifier (path, $5);
653                 $$ = SCM_UNSPECIFIED;
654         }
655         ;
656
657
658 identifier_init:
659         identifier_init_nonumber
660         | number_expression
661         | post_event_nofinger post_events
662         {
663                 $$ = scm_reverse_x ($2, SCM_EOL);
664                 if (Music *m = unsmob<Music> ($1))
665                 {
666                         if (m->is_mus_type ("post-event-wrapper"))
667                                 $$ = scm_append
668                                         (scm_list_2 (m->get_property ("elements"),
669                                                      $$));
670                         else
671                                 $$ = scm_cons ($1, $$);
672                 }
673                 if (scm_is_pair ($$)
674                     && scm_is_null (scm_cdr ($$)))
675                         $$ = scm_car ($$);
676                 else
677                 {
678                         Music * m = MY_MAKE_MUSIC ("PostEvents", @$);
679                         m->set_property ("elements", $$);
680                         $$ = m->unprotect ();
681                 }
682         }
683         ;
684
685 identifier_init_nonumber:
686         score_block
687         | book_block
688         | bookpart_block
689         | output_def
690         | context_def_spec_block
691         | music_assign
692         | pitch_or_music
693         | FRACTION
694         | string
695         | embedded_scm
696         | partial_markup
697         | full_markup_list
698         | context_modification
699         | partial_function ETC
700         {
701                 $$ = MAKE_SYNTAX (partial_music_function, @$,
702                                   scm_reverse_x ($1, SCM_EOL));
703         }
704         ;
705
706 // Partial functions
707 partial_function:
708         MUSIC_FUNCTION function_arglist_partial
709         {
710                 $$ = scm_acons ($1, $2, SCM_EOL);
711         }
712         | EVENT_FUNCTION function_arglist_partial
713         {
714                 $$ = scm_acons ($1, $2, SCM_EOL);
715         }
716         | SCM_FUNCTION function_arglist_partial
717         {
718                 $$ = scm_acons ($1, $2, SCM_EOL);
719         }
720         | OVERRIDE grob_prop_path '='
721         {
722                 if (SCM_UNBNDP ($2))
723                         $$ = scm_list_1 (SCM_BOOL_F);
724                 else
725                         $$ = scm_cons
726                                 (scm_list_3 (Syntax::property_override_function,
727                                              scm_cdr ($2), scm_car ($2)),
728                                  SCM_EOL);
729         }
730         | SET context_prop_spec '='
731         {
732                 if (SCM_UNBNDP ($2))
733                         $$ = scm_list_1 (SCM_BOOL_F);
734                 else
735                         $$ = scm_cons
736                                 (scm_list_3 (Syntax::property_set_function,
737                                              scm_cadr ($2), scm_car ($2)),
738                                  SCM_EOL);
739         }
740         | MUSIC_FUNCTION EXPECT_SCM function_arglist_optional partial_function
741         {
742                 $$ = scm_acons ($1, $3, $4);
743         }
744         | EVENT_FUNCTION EXPECT_SCM function_arglist_optional partial_function
745         {
746                 $$ = scm_acons ($1, $3, $4);
747         }
748         | SCM_FUNCTION EXPECT_SCM function_arglist_optional partial_function
749         {
750                 $$ = scm_acons ($1, $3, $4);
751         }
752         | OVERRIDE grob_prop_path '=' partial_function
753         {
754                 if (SCM_UNBNDP ($2))
755                         $$ = scm_list_1 (SCM_BOOL_F);
756                 else
757                         $$ = scm_cons
758                                 (scm_list_3 (Syntax::property_override_function,
759                                              scm_cdr ($2), scm_car ($2)),
760                                  $4);
761         }
762         | SET context_prop_spec '=' partial_function
763         {
764                 if (SCM_UNBNDP ($2))
765                         $$ = scm_list_1 (SCM_BOOL_F);
766                 else
767                         $$ = scm_cons
768                                 (scm_list_3 (Syntax::property_set_function,
769                                              scm_cadr ($2), scm_car ($2)),
770                                  $4);
771         }
772         | MUSIC_FUNCTION EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup partial_function
773         {
774                 $$ = scm_acons ($1, $4, $5);
775         }
776         | EVENT_FUNCTION EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup partial_function
777         {
778                 $$ = scm_acons ($1, $4, $5);
779         }
780         | SCM_FUNCTION EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup partial_function
781         {
782                 $$ = scm_acons ($1, $4, $5);
783         }
784         ;
785
786 context_def_spec_block:
787         CONTEXT '{' context_def_spec_body '}'
788         {
789                 $$ = $3;
790                 Context_def *td = unsmob<Context_def> ($$);
791                 if (!td) {
792                         $$ = Context_def::make_scm ();
793                         td = unsmob<Context_def> ($$);
794                 }
795                 td->origin ()->set_spot (@$);
796         }
797         ;
798
799 context_mod_arg:
800         embedded_scm
801         |
802         {
803                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
804                 parser->lexer_->push_note_state (nn);
805         }
806         composite_music
807         {
808                 parser->lexer_->pop_state ();
809                 $$ = $2;
810         }
811         ;
812
813
814 context_def_spec_body:
815         /**/ {
816                 $$ = SCM_UNSPECIFIED;
817         }
818         | context_def_spec_body context_mod {
819                 if (!SCM_UNBNDP ($2)) {
820                         Context_def *td = unsmob<Context_def> ($$);
821                         if (!td) {
822                                 $$ = Context_def::make_scm ();
823                                 td = unsmob<Context_def> ($$);
824                         }
825                         unsmob<Context_def> ($$)->add_context_mod ($2);
826                 }
827         }
828         | context_def_spec_body context_modification {
829                 Context_def *td = unsmob<Context_def> ($$);
830                 if (!td) {
831                         $$ = Context_def::make_scm ();
832                         td = unsmob<Context_def> ($$);
833                 }
834                 SCM new_mods = unsmob<Context_mod> ($2)->get_mods ();
835                 for (SCM m = new_mods; scm_is_pair (m); m = scm_cdr (m)) {
836                     td->add_context_mod (scm_car (m));
837                 }
838         }
839         | context_def_spec_body context_mod_arg {
840                 Context_def *td = unsmob<Context_def> ($1);
841                 if (scm_is_eq ($2, SCM_UNSPECIFIED))
842                         ;
843                 else if (!td && unsmob<Context_def> ($2))
844                         $$ = $2;
845                 else {
846                         if (!td) {
847                                 $$ = Context_def::make_scm ();
848                                 td = unsmob<Context_def> ($$);
849                         }
850                         if (unsmob<Music> ($2)) {
851                                 SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler");
852                                 $2 = scm_call_1 (proc, $2);
853                         }
854                         if (Context_mod *cm = unsmob<Context_mod> ($2)) {
855                                 for (SCM m = cm->get_mods (); scm_is_pair (m); m = scm_cdr (m)) {
856                                         td->add_context_mod (scm_car (m));
857                                 }
858                         } else
859                                 parser->parser_error (@2, _ ("not a context mod"));
860                 }
861         }
862         ;
863
864
865
866 book_block:
867         BOOK '{' book_body '}'  {
868                 $$ = $3;
869                 unsmob<Book> ($$)->origin ()->set_spot (@$);
870                 pop_paper (parser);
871                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-book"), SCM_BOOL_F);
872         }
873         ;
874
875 /* FIXME:
876    * Use 'handlers' like for toplevel-* stuff?
877    * grok \layout and \midi?  */
878 book_body:
879         {
880                 Book *book = new Book;
881                 init_papers (parser);
882                 book->paper_ = dynamic_cast<Output_def*> (unsmob<Output_def> (parser->lexer_->lookup_identifier ("$defaultpaper"))->clone ());
883                 book->paper_->unprotect ();
884                 push_paper (parser, book->paper_);
885                 book->header_ = get_header (parser);
886                 $$ = book->unprotect ();
887                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-book"), $$);
888         }
889         | BOOK_IDENTIFIER {
890                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-book"), $1);
891         }
892         | book_body paper_block {
893                 unsmob<Book> ($1)->paper_ = unsmob<Output_def> ($2);
894                 set_paper (parser, unsmob<Output_def> ($2));
895         }
896         | book_body bookpart_block {
897                 SCM proc = parser->lexer_->lookup_identifier ("book-bookpart-handler");
898                 scm_call_2 (proc, $1, $2);
899         }
900         | book_body score_block {
901                 SCM proc = parser->lexer_->lookup_identifier ("book-score-handler");
902                 scm_call_2 (proc, $1, $2);
903         }
904         | book_body composite_music {
905                 SCM proc = parser->lexer_->lookup_identifier ("book-music-handler");
906                 scm_call_2 (proc, $1, $2);
907         }
908         | book_body full_markup {
909                 SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
910                 scm_call_2 (proc, $1, scm_list_1 ($2));
911         }
912         | book_body full_markup_list {
913                 SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
914                 scm_call_2 (proc, $1, $2);
915         }
916         | book_body SCM_TOKEN {
917                 // Evaluate and ignore #xxx, as opposed to \xxx
918                 parser->lexer_->eval_scm_token ($2, @2);
919         }
920         | book_body embedded_scm_active
921         {
922                 SCM out = SCM_UNDEFINED;
923                 if (Text_interface::is_markup ($2))
924                         out = scm_list_1 ($2);
925                 else if (Text_interface::is_markup_list ($2))
926                         out = $2;
927                 if (scm_is_pair (out))
928                 {
929                         SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
930                         scm_call_2 (proc, $1, out);
931                 } else if (unsmob<Score> ($2))
932                 {
933                         SCM proc = parser->lexer_->lookup_identifier ("book-score-handler");
934                         scm_call_2 (proc, $1, $2);
935                 } else if (Output_def *od = unsmob<Output_def> ($2)) {
936                         SCM id = SCM_EOL;
937
938                         if (to_boolean (od->c_variable ("is-paper")))
939                                 id = ly_symbol2scm ("$defaultpaper");
940                         else if (to_boolean (od->c_variable ("is-midi")))
941                                 id = ly_symbol2scm ("$defaultmidi");
942                         else if (to_boolean (od->c_variable ("is-layout")))
943                                 id = ly_symbol2scm ("$defaultlayout");
944
945                         parser->lexer_->set_identifier (id, $2);
946                 } else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
947                         parser->parser_error (@2, _("bad expression type"));
948         }
949         | book_body
950         {
951                 parser->lexer_->add_scope (unsmob<Book> ($1)->header_);
952         } lilypond_header
953         | book_body error {
954                 Book *book = unsmob<Book> ($1);
955                 book->paper_ = 0;
956                 book->scores_ = SCM_EOL;
957                 book->bookparts_ = SCM_EOL;
958         }
959         ;
960
961 bookpart_block:
962         BOOKPART '{' bookpart_body '}' {
963                 $$ = $3;
964                 unsmob<Book> ($$)->origin ()->set_spot (@$);
965                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-bookpart"), SCM_BOOL_F);
966         }
967         ;
968
969 bookpart_body:
970         {
971                 Book *book = new Book;
972                 $$ = book->unprotect ();
973                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-bookpart"), $$);
974         }
975         | BOOK_IDENTIFIER {
976                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-bookpart"), $1);
977         }
978         | bookpart_body paper_block {
979                 unsmob<Book> ($$)->paper_ = unsmob<Output_def> ($2);
980         }
981         | bookpart_body score_block {
982                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-score-handler");
983                 scm_call_2 (proc, $1, $2);
984         }
985         | bookpart_body composite_music {
986                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-music-handler");
987                 scm_call_2 (proc, $1, $2);
988         }
989         | bookpart_body full_markup {
990                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
991                 scm_call_2 (proc, $1, scm_list_1 ($2));
992         }
993         | bookpart_body full_markup_list {
994                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
995                 scm_call_2 (proc, $1, $2);
996         }
997         | bookpart_body SCM_TOKEN {
998                 // Evaluate and ignore #xxx, as opposed to \xxx
999                 parser->lexer_->eval_scm_token ($2, @2);
1000         }
1001         | bookpart_body embedded_scm_active
1002         {
1003                 SCM out = SCM_UNDEFINED;
1004                 if (Text_interface::is_markup ($2))
1005                         out = scm_list_1 ($2);
1006                 else if (Text_interface::is_markup_list ($2))
1007                         out = $2;
1008                 if (scm_is_pair (out))
1009                 {
1010                         SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
1011                         scm_call_2 (proc, $1, out);
1012                 } else if (unsmob<Score> ($2))
1013                 {
1014                         SCM proc = parser->lexer_->lookup_identifier ("bookpart-score-handler");
1015                         scm_call_2 (proc, $1, $2);
1016                 } else if (Output_def *od = unsmob<Output_def> ($2)) {
1017                         SCM id = SCM_EOL;
1018
1019                         if (to_boolean (od->c_variable ("is-paper")))
1020                                 id = ly_symbol2scm ("$defaultpaper");
1021                         else if (to_boolean (od->c_variable ("is-midi")))
1022                                 id = ly_symbol2scm ("$defaultmidi");
1023                         else if (to_boolean (od->c_variable ("is-layout")))
1024                                 id = ly_symbol2scm ("$defaultlayout");
1025
1026                         parser->lexer_->set_identifier (id, $2);
1027                 } else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
1028                         parser->parser_error (@2, _("bad expression type"));
1029         }
1030         | bookpart_body
1031         {
1032                 Book *book = unsmob<Book> ($1);
1033                 if (!ly_is_module (book->header_))
1034                         book->header_ = ly_make_module (false);
1035                 parser->lexer_->add_scope (book->header_);
1036         } lilypond_header
1037         | bookpart_body error {
1038                 Book *book = unsmob<Book> ($1);
1039                 book->paper_ = 0;
1040                 book->scores_ = SCM_EOL;
1041         }
1042         ;
1043
1044 score_block:
1045         SCORE '{' score_body '}'        {
1046                 unsmob<Score> ($3)->origin ()->set_spot (@$);
1047                 $$ = $3;
1048         }
1049         ;
1050
1051 score_body:
1052         score_items {
1053                 if (!unsmob<Score> ($1)) {
1054                         parser->parser_error (@1, _("Missing music in \\score"));
1055                         $$ = (new Score)->unprotect ();
1056                         if (scm_is_pair ($1) && ly_is_module (scm_car ($1)))
1057                         {
1058                                 unsmob<Score> ($$)->set_header (scm_car ($1));
1059                                 $1 = scm_cdr ($1);
1060                         }
1061                         for (SCM p = scm_reverse_x ($1, SCM_EOL);
1062                              scm_is_pair (p); p = scm_cdr (p))
1063                         {
1064                                 unsmob<Score> ($$)->
1065                                         add_output_def (unsmob<Output_def> (scm_car (p)));
1066                         }
1067                 }
1068         }
1069         | score_body error {
1070                 unsmob<Score> ($$)->error_found_ = true;
1071         }
1072         ;
1073
1074 score_item:
1075         embedded_scm
1076         | music
1077         | output_def
1078         ;
1079
1080 score_items:
1081         /* empty */
1082         {
1083                 $$ = SCM_EOL;
1084         }
1085         | score_items score_item
1086         {
1087                 Output_def *od = unsmob<Output_def> ($2);
1088                 if (od) {
1089                         if (to_boolean (od->lookup_variable (ly_symbol2scm ("is-paper"))))
1090                         {
1091                                 parser->parser_error (@2, _("\\paper cannot be used in \\score, use \\layout instead"));
1092                                 od = 0;
1093                                 $2 = SCM_UNSPECIFIED;
1094                         }
1095                 } else if (!unsmob<Score> ($$)) {
1096                         if (unsmob<Music> ($2)) {
1097                                 $2 = Lily::scorify_music ($2);
1098                         }
1099                         if (unsmob<Score> ($2))
1100                         {
1101                                 $$ = $2;
1102                                 $2 = SCM_UNSPECIFIED;
1103                         }
1104                 }
1105                 Score *score = unsmob<Score> ($$);
1106                 if (score && scm_is_pair ($1)) {
1107                         if (ly_is_module (scm_car ($1)))
1108                         {
1109                                 score->set_header (scm_car ($1));
1110                                 $1 = scm_cdr ($1);
1111                         }
1112                         for (SCM p = scm_reverse_x ($1, SCM_EOL);
1113                              scm_is_pair (p); p = scm_cdr (p))
1114                         {
1115                                 score->add_output_def (unsmob<Output_def> (scm_car (p)));
1116                         }
1117                 }
1118                 if (od) {
1119                         if (score)
1120                                 score->add_output_def (od);
1121                         else if (scm_is_pair ($$) && ly_is_module (scm_car ($$)))
1122                                 scm_set_cdr_x ($$, scm_cons ($2, scm_cdr ($$)));
1123                         else
1124                                 $$ = scm_cons ($2, $$);
1125                 } else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
1126                         parser->parser_error (@2, _("Spurious expression in \\score"));
1127         }
1128         | score_items
1129         {
1130                 if (Score *score = unsmob<Score> ($1)) {
1131                         if (!ly_is_module (score->get_header ()))
1132                                 score->set_header (ly_make_module (false));
1133                         parser->lexer_->add_scope (score->get_header ());
1134                 } else {
1135                         if (!scm_is_pair ($1) || !ly_is_module (scm_car ($1)))
1136                                 $1 = scm_cons (ly_make_module (false), $1);
1137                         parser->lexer_->add_scope (scm_car ($1));
1138                 }
1139         } lilypond_header
1140         {
1141                 $$ = $1;
1142         }
1143         ;
1144
1145
1146 /*
1147         OUTPUT DEF
1148 */
1149
1150 paper_block:
1151         output_def {
1152                 Output_def *od = unsmob<Output_def> ($1);
1153
1154                 if (!to_boolean (od->lookup_variable (ly_symbol2scm ("is-paper"))))
1155                 {
1156                         parser->parser_error (@1, _ ("need \\paper for paper block"));
1157                         $$ = get_paper (parser)->unprotect ();
1158                 }
1159         }
1160         ;
1161
1162
1163 output_def:
1164         output_def_body '}' {
1165                 if (scm_is_pair ($1))
1166                         $$ = scm_car ($1);
1167
1168                 parser->lexer_->remove_scope ();
1169                 parser->lexer_->pop_state ();
1170         }
1171         ;
1172
1173 output_def_head:
1174         PAPER {
1175                 Output_def *p = get_paper (parser);
1176                 p->input_origin_ = @$;
1177                 parser->lexer_->add_scope (p->scope_);
1178                 $$ = p->unprotect ();
1179         }
1180         | MIDI    {
1181                 Output_def *p = get_midi (parser);
1182                 $$ = p->unprotect ();
1183                 parser->lexer_->add_scope (p->scope_);
1184         }
1185         | LAYOUT        {
1186                 Output_def *p = get_layout (parser);
1187
1188                 parser->lexer_->add_scope (p->scope_);
1189                 $$ = p->unprotect ();
1190         }
1191         ;
1192
1193 output_def_head_with_mode_switch:
1194         output_def_head {
1195                 parser->lexer_->push_initial_state ();
1196                 $$ = $1;
1197         }
1198         ;
1199
1200 // We need this weird nonterminal because both music as well as a
1201 // context definition can start with \context and the difference is
1202 // only apparent after looking at the next token.  If it is '{', there
1203 // is still time to escape from notes mode.
1204
1205 music_or_context_def:
1206         music_assign
1207         | context_def_spec_block
1208         ;
1209
1210 output_def_body:
1211         output_def_head_with_mode_switch '{' {
1212                 unsmob<Output_def> ($1)->input_origin_.set_spot (@$);
1213                 // This is a stupid trick to mark the beginning of the
1214                 // body for deciding whether to allow
1215                 // embedded_scm_active to have an output definition
1216                 $$ = scm_list_1 ($1);
1217         }
1218         | output_def_body assignment  {
1219                 if (scm_is_pair ($1))
1220                         $$ = scm_car ($1);
1221         }
1222         | output_def_body embedded_scm_active
1223         {
1224                 // We don't switch into note mode for Scheme functions
1225                 // here.  Does not seem warranted/required in output
1226                 // definitions.
1227                 if (scm_is_pair ($1))
1228                 {
1229                         Output_def *o = unsmob<Output_def> ($2);
1230                         if (o) {
1231                                 o->input_origin_.set_spot (@$);
1232                                 $1 = o->self_scm ();
1233                                 parser->lexer_->remove_scope ();
1234                                 parser->lexer_->add_scope (o->scope_);
1235                                 $2 = SCM_UNSPECIFIED;
1236                         } else
1237                                 $1 = scm_car ($1);
1238                 }
1239                 if (unsmob<Context_def> ($2))
1240                         assign_context_def (unsmob<Output_def> ($1), $2);
1241                 // Seems unlikely, but let's be complete:
1242                 else if (unsmob<Music> ($2))
1243                 {
1244                         SCM proc = parser->lexer_->lookup_identifier
1245                                 ("output-def-music-handler");
1246                         scm_call_2 (proc, $1, $2);
1247                 } else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
1248                         parser->parser_error (@2, _("bad expression type"));
1249                 $$ = $1;
1250         }
1251         | output_def_body SCM_TOKEN {
1252                 if (scm_is_pair ($1))
1253                         $$ = scm_car ($1);
1254                 // Evaluate and ignore #xxx, as opposed to \xxx
1255                 parser->lexer_->eval_scm_token ($2, @2);
1256         }
1257         | output_def_body
1258         {
1259                 if (scm_is_pair ($1))
1260                         $1 = scm_car ($1);
1261                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
1262                 parser->lexer_->push_note_state (nn);
1263         } music_or_context_def
1264         {
1265                 parser->lexer_->pop_state ();
1266                 if (unsmob<Context_def> ($3))
1267                         assign_context_def (unsmob<Output_def> ($1), $3);
1268                 else {
1269
1270                         SCM proc = parser->lexer_->lookup_identifier
1271                                      ("output-def-music-handler");
1272                         scm_call_2 (proc, $1, $3);
1273                 }
1274                 $$ = $1;
1275         }
1276         | output_def_body error {
1277
1278         }
1279         ;
1280
1281 tempo_event:
1282         TEMPO steno_duration '=' tempo_range    {
1283                 $$ = MAKE_SYNTAX (tempo, @$, SCM_EOL, $2, $4);
1284         }
1285         | TEMPO text steno_duration '=' tempo_range     {
1286                 $$ = MAKE_SYNTAX (tempo, @$, $2, $3, $5);
1287         }
1288         | TEMPO text {
1289                 $$ = MAKE_SYNTAX (tempo, @$, $2);
1290         } %prec ':'
1291         ;
1292
1293 /*
1294 The representation of a  list is reversed to have efficient append.  */
1295
1296 music_list:
1297         /* empty */ {
1298                 $$ = SCM_EOL;
1299         }
1300         | music_list music_embedded {
1301                 if (unsmob<Music> ($2))
1302                         $$ = scm_cons ($2, $1);
1303         }
1304         | music_list error {
1305                 Music *m = MY_MAKE_MUSIC("Music", @$);
1306                 // ugh. code dup
1307                 m->set_property ("error-found", SCM_BOOL_T);
1308                 $$ = scm_cons (m->self_scm (), $1);
1309                 m->unprotect (); /* UGH */
1310         }
1311         ;
1312
1313 braced_music_list:
1314         '{' music_list '}'
1315         {
1316                 $$ = scm_reverse_x ($2, SCM_EOL);
1317         }
1318         ;
1319
1320 music:  music_assign
1321         | lyric_element_music
1322         | pitch_as_music
1323         ;
1324
1325 pitch_as_music:
1326         pitch_or_music
1327         {
1328                 $$ = make_music_from_simple (parser, @1, $1);
1329                 if (!unsmob<Music> ($$))
1330                 {
1331                         parser->parser_error (@1, _ ("music expected"));
1332                         $$ = MAKE_SYNTAX (void_music, @$);
1333                 }
1334         }
1335         ;
1336
1337 music_embedded:
1338         music
1339         {
1340                 if (unsmob<Music> ($1)->is_mus_type ("post-event")) {
1341                         parser->parser_error (@1, _ ("unexpected post-event"));
1342                         $$ = SCM_UNSPECIFIED;
1343                 }
1344         }
1345         | music_embedded_backup
1346         {
1347                 $$ = $1;
1348         }
1349         | music_embedded_backup BACKUP lyric_element_music
1350         {
1351                 $$ = $3;
1352         }
1353         | multiplied_duration post_events
1354         {
1355                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
1356
1357                 parser->default_duration_ = *unsmob<Duration> ($1);
1358                 n->set_property ("duration", $1);
1359
1360                 if (scm_is_pair ($2))
1361                         n->set_property ("articulations",
1362                                          scm_reverse_x ($2, SCM_EOL));
1363                 $$ = n->unprotect ();
1364         }
1365         ;
1366
1367 music_embedded_backup:
1368         embedded_scm
1369         {
1370                 if (scm_is_eq ($1, SCM_UNSPECIFIED))
1371                         $$ = $1;
1372                 else if (Music *m = unsmob<Music> ($1)) {
1373                         if (m->is_mus_type ("post-event")) {
1374                                 parser->parser_error
1375                                         (@1, _ ("unexpected post-event"));
1376                                 $$ = SCM_UNSPECIFIED;
1377                         } else
1378                                 $$ = $1;
1379                 } else if (parser->lexer_->is_lyric_state ()
1380                            && Text_interface::is_markup ($1))
1381                         MYBACKUP (LYRIC_ELEMENT, $1, @1);
1382                 else {
1383                         @$.warning (_ ("Ignoring non-music expression"));
1384                         $$ = $1;
1385                 }
1386         }
1387         ;
1388
1389 // music_assign does not need to contain lyrics: there are no
1390 // assignments in lyricmode.
1391 music_assign:
1392         simple_music
1393         | composite_music %prec COMPOSITE
1394         ;
1395
1396 repeated_music:
1397         REPEAT simple_string unsigned_number music
1398         {
1399                 $$ = MAKE_SYNTAX (repeat, @$, $2, $3, $4, SCM_EOL);
1400         }
1401         | REPEAT simple_string unsigned_number music ALTERNATIVE braced_music_list
1402         {
1403                 $$ = MAKE_SYNTAX (repeat, @$, $2, $3, $4, $6);
1404         }
1405         ;
1406
1407 sequential_music:
1408         SEQUENTIAL braced_music_list {
1409                 $$ = MAKE_SYNTAX (sequential_music, @$, $2);
1410         }
1411         | braced_music_list {
1412                 $$ = MAKE_SYNTAX (sequential_music, @$, $1);
1413         }
1414         ;
1415
1416 simultaneous_music:
1417         SIMULTANEOUS braced_music_list {
1418                 $$ = MAKE_SYNTAX (simultaneous_music, @$, $2);
1419         }
1420         | DOUBLE_ANGLE_OPEN music_list DOUBLE_ANGLE_CLOSE       {
1421                 $$ = MAKE_SYNTAX (simultaneous_music, @$, scm_reverse_x ($2, SCM_EOL));
1422         }
1423         ;
1424
1425 simple_music:
1426         event_chord
1427         | music_property_def
1428         | context_change
1429         ;
1430
1431 context_modification:
1432         WITH
1433         {
1434                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
1435                 parser->lexer_->push_note_state (nn);
1436         } '{' context_mod_list '}'
1437         {
1438                 parser->lexer_->pop_state ();
1439                 $$ = $4;
1440         }
1441         | WITH CONTEXT_MOD_IDENTIFIER
1442         {
1443                 $$ = $2;
1444         }
1445         | CONTEXT_MOD_IDENTIFIER
1446         {
1447                 $$ = $1;
1448         }
1449         | WITH context_modification_arg
1450         {
1451                 if (unsmob<Music> ($2)) {
1452                         SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler");
1453                         $2 = scm_call_1 (proc, $2);
1454                 }
1455                 if (unsmob<Context_mod> ($2))
1456                         $$ = $2;
1457                 else {
1458                         parser->parser_error (@2, _ ("not a context mod"));
1459                         $$ = Context_mod ().smobbed_copy ();
1460                 }
1461         }
1462         ;
1463
1464 context_modification_arg:
1465         embedded_scm
1466         | MUSIC_IDENTIFIER
1467         ;
1468
1469 optional_context_mod:
1470         /**/ {
1471             $$ = SCM_EOL;
1472         }
1473         | context_modification
1474         {
1475               $$ = $1;
1476         }
1477         ;
1478
1479 context_mod_list:
1480         /**/ {
1481             $$ = Context_mod ().smobbed_copy ();
1482         }
1483         | context_mod_list context_mod  {
1484                 if (!SCM_UNBNDP ($2))
1485                         unsmob<Context_mod> ($1)->add_context_mod ($2);
1486         }
1487         | context_mod_list CONTEXT_MOD_IDENTIFIER {
1488                  Context_mod *md = unsmob<Context_mod> ($2);
1489                  if (md)
1490                      unsmob<Context_mod> ($1)->add_context_mods (md->get_mods ());
1491         }
1492         | context_mod_list context_mod_arg {
1493                 if (scm_is_eq ($2, SCM_UNSPECIFIED))
1494                         ;
1495                 else if (unsmob<Music> ($2)) {
1496                         SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler");
1497                         $2 = scm_call_1 (proc, $2);
1498                 }
1499                 if (unsmob<Context_mod> ($2))
1500                         unsmob<Context_mod> ($$)->add_context_mods
1501                                 (unsmob<Context_mod> ($2)->get_mods ());
1502                 else {
1503                         parser->parser_error (@2, _ ("not a context mod"));
1504                 }
1505         }
1506         ;
1507
1508 context_prefix:
1509         CONTEXT symbol optional_id optional_context_mod {
1510                 Context_mod *ctxmod = unsmob<Context_mod> ($4);
1511                 SCM mods = SCM_EOL;
1512                 if (ctxmod)
1513                         mods = ctxmod->get_mods ();
1514                 $$ = START_MAKE_SYNTAX (context_specification, $2, $3, mods, SCM_BOOL_F);
1515         }
1516         | NEWCONTEXT symbol optional_id optional_context_mod {
1517                 Context_mod *ctxmod = unsmob<Context_mod> ($4);
1518                 SCM mods = SCM_EOL;
1519                 if (ctxmod)
1520                         mods = ctxmod->get_mods ();
1521                 $$ = START_MAKE_SYNTAX (context_specification, $2, $3, mods, SCM_BOOL_T);
1522         }
1523         ;
1524
1525 new_lyrics:
1526         ADDLYRICS optional_context_mod lyric_mode_music {
1527                 Context_mod *ctxmod = unsmob<Context_mod> ($2);
1528                 SCM mods = SCM_EOL;
1529                 if (ctxmod)
1530                         mods = ctxmod->get_mods ();
1531                 $$ = scm_acons ($3, mods, SCM_EOL);
1532         }
1533         | new_lyrics ADDLYRICS optional_context_mod lyric_mode_music {
1534                 Context_mod *ctxmod = unsmob<Context_mod> ($3);
1535                 SCM mods = SCM_EOL;
1536                 if (ctxmod)
1537                         mods = ctxmod->get_mods ();
1538                 $$ = scm_acons ($4, mods, $1);
1539         }
1540         ;
1541
1542 /* basic_music is basically the same as composite_music but with
1543  * context-prefixed music and lyricized music explicitly removed.  The
1544  * reason is that in a sequence
1545  *
1546  *   \new Staff \new Voice { ... } \addlyrics { ... } \addlyrics { ... }
1547  *
1548  * we need to group both \addlyrics together (as they go with the same
1549  * voice) but then combine them with \new Voice { ... }, meaning that
1550  * combining \new Voice { ... } needs higher priority than
1551  * { ... } \addlyrics, and *not* have \new Staff \new Voice { ... }
1552  * combine before combining \new Voice { ... } \addlyrics: only one
1553  * layer of context-prefixed music should assemble before \addlyrics
1554  * is integrated.  Total mess, and we sort this mess out with explicit
1555  * rules preferring a single context-prefix.
1556  */
1557
1558 basic_music:
1559         music_function_call
1560         | repeated_music
1561         | music_bare
1562         | LYRICSTO simple_string lyric_mode_music {
1563                 $$ = MAKE_SYNTAX (lyric_combine, @$, $2, SCM_EOL, $3);
1564         }
1565         | LYRICSTO symbol '=' simple_string lyric_mode_music
1566         {
1567                 $$ = MAKE_SYNTAX (lyric_combine, @$, $3, $2, $4);
1568         }
1569         ;
1570
1571 contextable_music:
1572         basic_music
1573         | pitch_as_music
1574         | event_chord
1575         ;
1576
1577 contexted_basic_music:
1578         context_prefix contextable_music new_lyrics
1579         {
1580                 Input i;
1581                 i.set_location (@1, @2);
1582                 $$ = FINISH_MAKE_SYNTAX ($1, i, $2);
1583                 $$ = MAKE_SYNTAX (add_lyrics, @$, $$, scm_reverse_x ($3, SCM_EOL));
1584         } %prec COMPOSITE
1585         | context_prefix contextable_music
1586         {
1587                 $$ = FINISH_MAKE_SYNTAX ($1, @$, $2);
1588         } %prec COMPOSITE
1589         | context_prefix contexted_basic_music
1590         {
1591                 $$ = FINISH_MAKE_SYNTAX ($1, @$, $2);
1592         }
1593         ;
1594
1595 composite_music:
1596         basic_music %prec COMPOSITE
1597         | contexted_basic_music
1598         | basic_music new_lyrics
1599         {
1600                 $$ = MAKE_SYNTAX (add_lyrics, @$, $1, scm_reverse_x ($2, SCM_EOL));
1601         } %prec COMPOSITE
1602         ;
1603
1604 music_bare:
1605         mode_changed_music
1606         | MUSIC_IDENTIFIER
1607         | grouped_music_list
1608         ;
1609
1610 grouped_music_list:
1611         simultaneous_music              { $$ = $1; }
1612         | sequential_music              { $$ = $1; }
1613         ;
1614
1615 /* Function argument lists are arguably the most complex part in the
1616  * parser.  They are pretty tricky to understand because of the way
1617  * they are processed, and because of optional arguments that can be
1618  * omitted.  When there are several optional arguments in a row,
1619  * omitting one automatically omits all following arguments.  Optional
1620  * arguments can only be omitted when either
1621  *
1622  * a) the omission is explicitly started with \default
1623  * b) the omission is implicitly started by an argument not matching
1624  *    its predicate, and there is a mandatory argument later that can
1625  *    "catch" the argument that does not fit.
1626  *
1627  * When argument parsing starts, the lexer pushes EXPECT_SCM tokens
1628  * (corresponding to mandatory arguments and having a predicate
1629  * function as semantic value) or EXPECT_OPTIONAL EXPECT_SCM (where
1630  * the semantic value of the EXPECT_OPTIONAL token is the default to
1631  * use when the optional argument is omitted, and EXPECT_SCM again has
1632  * the argument predicate as semantic value) in reverse order to the
1633  * parser, followed by EXPECT_NO_MORE_ARGS.  The argument list is then
1634  * processed inside-out while actual tokens are consumed.
1635  *
1636  * This means that the argument list tokens determine the actions
1637  * taken as they arrive.  The structure of the argument list is known
1638  * to the parser and stored in its parse stack when the first argument
1639  * is being parsed.  What the parser does not know is which predicates
1640  * will match and whether or not \default will be appearing in the
1641  * argument list, and where.
1642  *
1643  * Sequences of 0 or more optional arguments are scanned using either
1644  * function_arglist_backup or function_arglist_nonbackup.  The first
1645  * is used when optional arguments are followed by at least one
1646  * mandatory argument: in that case optional arguments may be skipped
1647  * by either a false predicate (in which case the expression will be
1648  * pushed back as one or more tokens, preceded by a BACKUP token) or
1649  * by using \default.
1650  *
1651  * If optional arguments are at the end of the argument list, they are
1652  * instead scanned using function_arglist_nonbackup: here the only
1653  * manner to enter into skipping of optional arguments is the use of
1654  * \default.
1655  *
1656  * The argument list of a normal function call is parsed using
1657  * function_arglist.  The part of an argument list before a mandatory
1658  * argument is parsed using function_arglist_optional.
1659  *
1660  * The difference is that leading optional arguments are scanned using
1661  * function_arglist_nonbackup and function_arglist_backup,
1662  * respectively.
1663  *
1664  * Most other details are obvious in the rules themselves.
1665  *
1666  */
1667
1668 symbol_list_arg:
1669         SYMBOL_LIST
1670         | SYMBOL_LIST '.' symbol_list_rev
1671         {
1672                 $$ = scm_append (scm_list_2 ($1, scm_reverse_x ($3, SCM_EOL)));
1673         }
1674         ;
1675
1676 symbol_list_rev:
1677         symbol_list_part
1678         | symbol_list_rev '.' symbol_list_part
1679         {
1680                 $$ = scm_append_x (scm_list_2 ($3, $1));
1681         }
1682         ;
1683
1684 // symbol_list_part delivers elements in reverse copy.
1685
1686 symbol_list_part:
1687         symbol_list_element
1688         {
1689                 $$ = try_string_variants (Lily::symbol_list_p, $1);
1690                 if (SCM_UNBNDP ($$)) {
1691                         parser->parser_error (@1, _("not a symbol"));
1692                         $$ = SCM_EOL;
1693                 } else
1694                         $$ = scm_reverse ($$);
1695         }
1696         ;
1697
1698
1699 symbol_list_element:
1700         STRING
1701         | embedded_scm_bare
1702         ;
1703
1704
1705 function_arglist_nonbackup:
1706         function_arglist_common
1707         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup post_event_nofinger
1708         {
1709                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1710         }
1711         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup '-' UNSIGNED
1712         {
1713                 SCM n = scm_difference ($5, SCM_UNDEFINED);
1714                 if (scm_is_true (scm_call_1 ($2, n)))
1715                         $$ = scm_cons (n, $3);
1716                 else {
1717                         Music *t = MY_MAKE_MUSIC ("FingeringEvent", @5);
1718                         t->set_property ("digit", $5);
1719                         $$ = check_scheme_arg (parser, @4, t->unprotect (),
1720                                                $3, $2, n);
1721                 }
1722         }
1723         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup '-' REAL
1724         {
1725                 $$ = check_scheme_arg (parser, @4,
1726                                        scm_difference ($5, SCM_UNDEFINED),
1727                                        $3, $2);
1728         }
1729         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup '-' NUMBER_IDENTIFIER
1730         {
1731                 $$ = check_scheme_arg (parser, @4,
1732                                        scm_difference ($5, SCM_UNDEFINED),
1733                                        $3, $2);
1734         }
1735         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup embedded_scm_arg
1736         {
1737                 if (scm_is_true (scm_call_1 ($2, $4)))
1738                         $$ = scm_cons ($4, $3);
1739                 else
1740                         $$ = check_scheme_arg (parser, @4,
1741                                                make_music_from_simple
1742                                                (parser, @4, $4),
1743                                                $3, $2);
1744         }
1745         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup bare_number_common
1746         {
1747                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1748         }
1749         | function_arglist_nonbackup_reparse REPARSE pitch_or_music
1750         {
1751                 if (scm_is_true (scm_call_1 ($2, $3)))
1752                         $$ = scm_cons ($3, $1);
1753                 else
1754                         $$ = check_scheme_arg (parser, @3,
1755                                                make_music_from_simple
1756                                                (parser, @3, $3),
1757                                                $1, $2);
1758         }
1759         | function_arglist_nonbackup_reparse REPARSE duration_length
1760         {
1761                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
1762         }
1763         | function_arglist_nonbackup_reparse REPARSE bare_number_common
1764         {
1765                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
1766         }
1767         | function_arglist_nonbackup_reparse REPARSE SCM_ARG
1768         {
1769                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
1770         }
1771         | function_arglist_nonbackup_reparse REPARSE lyric_element_music
1772         {
1773                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
1774         }
1775         | function_arglist_nonbackup_reparse REPARSE symbol_list_arg
1776         {
1777                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
1778         }
1779         ;
1780
1781 function_arglist_nonbackup_reparse:
1782         EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup SCM_IDENTIFIER
1783         {
1784                 $$ = $3;
1785                 SCM res = try_string_variants ($2, $4);
1786                 if (!SCM_UNBNDP (res))
1787                         if (scm_is_pair (res))
1788                                 MYREPARSE (@4, $2, SYMBOL_LIST, res);
1789                         else
1790                                 MYREPARSE (@4, $2, SCM_ARG, res);
1791                 else if (scm_is_true
1792                          (scm_call_1
1793                           ($2, make_music_from_simple
1794                            (parser, @4, $4))))
1795                         MYREPARSE (@4, $2, STRING, $4);
1796                 else
1797                         MYREPARSE (@4, $2, SCM_ARG, $4);
1798         }
1799         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup pitch
1800         {
1801                 $$ = $3;
1802                 if (scm_is_true
1803                     (scm_call_1
1804                      ($2, make_music_from_simple
1805                       (parser, @4, $4))))
1806                         MYREPARSE (@4, $2, PITCH_IDENTIFIER, $4);
1807                 else
1808                         MYREPARSE (@4, $2, SCM_ARG, $4);
1809         }
1810         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup steno_tonic_pitch
1811         {
1812                 $$ = $3;
1813                 if (scm_is_true
1814                     (scm_call_1
1815                      ($2, make_music_from_simple
1816                       (parser, @4, $4))))
1817                         MYREPARSE (@4, $2, TONICNAME_PITCH, $4);
1818                 else
1819                         MYREPARSE (@4, $2, SCM_ARG, $4);
1820         }
1821         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup STRING
1822         {
1823                 $$ = $3;
1824                 SCM res = try_string_variants ($2, $4);
1825                 if (!SCM_UNBNDP (res))
1826                         if (scm_is_pair (res))
1827                                 MYREPARSE (@4, $2, SYMBOL_LIST, res);
1828                         else
1829                                 MYREPARSE (@4, $2, SCM_ARG, res);
1830                 else if (scm_is_true
1831                          (scm_call_1
1832                           ($2, make_music_from_simple
1833                            (parser, @4, $4))))
1834                         MYREPARSE (@4, $2, STRING, $4);
1835                 else
1836                         MYREPARSE (@4, $2, SCM_ARG, $4);
1837         }
1838         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup full_markup
1839         {
1840                 $$ = $3;
1841                 if (scm_is_true (scm_call_1 ($2, $4)))
1842                         MYREPARSE (@4, $2, SCM_ARG, $4);
1843                 else if (scm_is_true
1844                          (scm_call_1
1845                           ($2, make_music_from_simple
1846                            (parser, @4, $4))))
1847                         MYREPARSE (@4, $2, STRING, $4);
1848                 else
1849                         MYREPARSE (@4, $2, SCM_ARG, $4);
1850         }
1851         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup UNSIGNED
1852         {
1853                 $$ = $3;
1854                 if (scm_is_true (scm_call_1 ($2, $4)))
1855                         MYREPARSE (@4, $2, REAL, $4);
1856                 else {
1857                         SCM d = make_duration ($4);
1858                         if (SCM_UNBNDP (d) || scm_is_false (scm_call_1 ($2, d)))
1859                                 MYREPARSE (@4, $2, REAL, $4); // trigger error
1860                         else
1861                                 MYREPARSE (@4, $2, DURATION_IDENTIFIER, d);
1862                 }
1863         }
1864         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup DURATION_IDENTIFIER {
1865                 $$ = $3;
1866                 MYREPARSE (@4, $2, DURATION_IDENTIFIER, $4);
1867         }
1868         ;
1869
1870
1871 // function_arglist_backup can't occur at the end of an argument
1872 // list.
1873 function_arglist_backup:
1874         function_arglist_common
1875         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup embedded_scm_arg
1876         {
1877                 if (scm_is_true (scm_call_1 ($2, $4)))
1878                         $$ = scm_cons ($4, $3);
1879                 else {
1880                         $$ = make_music_from_simple (parser, @4, $4);
1881                         if (scm_is_true (scm_call_1 ($2, $$)))
1882                                 $$ = scm_cons ($$, $3);
1883                         else
1884                         {
1885                                 $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1886                                 MYBACKUP (SCM_ARG, $4, @4);
1887                         }
1888                 }
1889         }
1890         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup post_event_nofinger
1891         {
1892                 if (scm_is_true (scm_call_1 ($2, $4)))
1893                 {
1894                         $$ = scm_cons ($4, $3);
1895                 } else {
1896                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1897                         MYBACKUP (EVENT_IDENTIFIER, $4, @4);
1898                 }
1899         }
1900         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup pitch
1901         {
1902                 if (scm_is_true
1903                     (scm_call_1
1904                      ($2, make_music_from_simple
1905                       (parser, @4, $4))))
1906                 {
1907                         $$ = $3;
1908                         MYREPARSE (@4, $2, PITCH_IDENTIFIER, $4);
1909                 } else if (scm_is_true (scm_call_1 ($2, $4)))
1910                         $$ = scm_cons ($4, $3);
1911                 else {
1912                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1913                         MYBACKUP (PITCH_IDENTIFIER, $4, @4);
1914                 }
1915         }
1916         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup steno_tonic_pitch
1917         {
1918                 if (scm_is_true
1919                     (scm_call_1
1920                      ($2, make_music_from_simple
1921                       (parser, @4, $4))))
1922                 {
1923                         $$ = $3;
1924                         MYREPARSE (@4, $2, TONICNAME_PITCH, $4);
1925                 } else if (scm_is_true (scm_call_1 ($2, $4)))
1926                         $$ = scm_cons ($4, $3);
1927                 else {
1928                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1929                         MYBACKUP (TONICNAME_PITCH, $4, @4);
1930                 }
1931         }
1932         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup full_markup
1933         {
1934                 if (scm_is_true (scm_call_1 ($2, $4)))
1935                         $$ = scm_cons ($4, $3);
1936                 else {
1937                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1938                         MYBACKUP (SCM_IDENTIFIER, $4, @4);
1939                 }
1940         }
1941         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup UNSIGNED
1942         {
1943                 if (scm_is_true (scm_call_1 ($2, $4)))
1944                 {
1945                         MYREPARSE (@4, $2, REAL, $4);
1946                         $$ = $3;
1947                 } else {
1948                         SCM d = make_duration ($4);
1949                         if (SCM_UNBNDP (d) || scm_is_false (scm_call_1 ($2, d)))
1950                         {
1951                                 $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1952                                 MYBACKUP (UNSIGNED, $4, @4);
1953                         } else {
1954                                 MYREPARSE (@4, $2, DURATION_IDENTIFIER, d);
1955                                 $$ = $3;
1956                         }
1957                 }
1958         }
1959         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup REAL
1960         {
1961                 if (scm_is_true (scm_call_1 ($2, $4)))
1962                 {
1963                         $$ = $3;
1964                         MYREPARSE (@4, $2, REAL, $4);
1965                 } else {
1966                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1967                         MYBACKUP (REAL, $4, @4);
1968                 }
1969         }
1970         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup NUMBER_IDENTIFIER
1971         {
1972                 if (scm_is_true (scm_call_1 ($2, $4)))
1973                 {
1974                         $$ = scm_cons ($4, $3);
1975                 } else {
1976                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1977                         MYBACKUP (NUMBER_IDENTIFIER, $4, @4);
1978                 }
1979         }
1980         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup '-' UNSIGNED
1981         {
1982                 SCM n = scm_difference ($5, SCM_UNDEFINED);
1983                 if (scm_is_true (scm_call_1 ($2, n))) {
1984                         $$ = $3;
1985                         MYREPARSE (@5, $2, REAL, n);
1986                 } else {
1987                         Music *t = MY_MAKE_MUSIC ("FingeringEvent", @5);
1988                         t->set_property ("digit", $5);
1989                         $$ = t->unprotect ();
1990                         if (scm_is_true (scm_call_1 ($2, $$)))
1991                                 $$ = scm_cons ($$, $3);
1992                         else {
1993                                 $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
1994                                 MYBACKUP (UNSIGNED, $5, @5);
1995                                 parser->lexer_->push_extra_token (@4, '-');
1996                         }
1997                 }
1998         }
1999         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup '-' REAL
2000         {
2001                 SCM n = scm_difference ($5, SCM_UNDEFINED);
2002                 if (scm_is_true (scm_call_1 ($2, n))) {
2003                         MYREPARSE (@5, $2, REAL, n);
2004                         $$ = $3;
2005                 } else {
2006                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
2007                         MYBACKUP (REAL, n, @5);
2008                 }
2009         }
2010         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup '-' NUMBER_IDENTIFIER
2011         {
2012                 SCM n = scm_difference ($5, SCM_UNDEFINED);
2013                 if (scm_is_true (scm_call_1 ($2, n))) {
2014                         $$ = scm_cons (n, $3);
2015                 } else {
2016                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
2017                         MYBACKUP (NUMBER_IDENTIFIER, n, @5);
2018                 }
2019         }
2020         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup DURATION_IDENTIFIER
2021         {
2022                 if (scm_is_true (scm_call_1 ($2, $4)))
2023                 {
2024                         MYREPARSE (@4, $2, DURATION_IDENTIFIER, $4);
2025                         $$ = $3;
2026                 } else {
2027                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
2028                         MYBACKUP (DURATION_IDENTIFIER, $4, @4);
2029                 }
2030         }
2031         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup SCM_IDENTIFIER
2032         {
2033                 SCM res = try_string_variants ($2, $4);
2034                 if (!SCM_UNBNDP (res))
2035                         if (scm_is_pair (res)) {
2036                                 $$ = $3;
2037                                 MYREPARSE (@4, $2, SYMBOL_LIST, res);
2038                         }
2039                         else
2040                                 $$ = scm_cons (res, $3);
2041                 else {
2042                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
2043                         MYBACKUP (SCM_IDENTIFIER, $4, @4);
2044                 }
2045         }
2046         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup STRING
2047         {
2048                 SCM res = try_string_variants ($2, $4);
2049                 if (!SCM_UNBNDP (res))
2050                         if (scm_is_pair (res)) {
2051                                 $$ = $3;
2052                                 MYREPARSE (@4, $2, SYMBOL_LIST, res);
2053                         }
2054                         else
2055                                 $$ = scm_cons (res, $3);
2056                 else {
2057                         $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
2058                         MYBACKUP (STRING, $4, @4);
2059                 }
2060         }
2061         | function_arglist_backup REPARSE pitch_or_music
2062         {
2063                 if (scm_is_true (scm_call_1 ($2, $3)))
2064                         $$ = scm_cons ($3, $1);
2065                 else
2066                         $$ = check_scheme_arg (parser, @3,
2067                                                make_music_from_simple
2068                                                (parser, @3, $3),
2069                                                $1, $2);
2070         }
2071         | function_arglist_backup REPARSE bare_number_common
2072         {
2073                 $$ = check_scheme_arg (parser, @3,
2074                                        $3, $1, $2);
2075         }
2076         | function_arglist_backup REPARSE duration_length
2077         {
2078                 $$ = check_scheme_arg (parser, @3,
2079                                        $3, $1, $2);
2080         }
2081         | function_arglist_backup REPARSE symbol_list_arg
2082         {
2083                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
2084         }
2085         ;
2086
2087 function_arglist:
2088         function_arglist_nonbackup
2089         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_nonbackup DEFAULT
2090         {
2091                 $$ = scm_cons (loc_on_music (parser, @4, $1), $3);
2092         }
2093         ;
2094
2095 function_arglist_skip_nonbackup:
2096         function_arglist_nonbackup
2097         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_nonbackup
2098         {
2099                 $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
2100         }
2101         ;
2102
2103 // Partial function arglists are returned just in their incomplete
2104 // state: when combined with the music function, the missing parts of
2105 // the signature can be reconstructed
2106 //
2107 // To serve as a partial arglist, the argument list must absolutely
2108 // _not_ be in "skipping optional arguments" mode since then there is
2109 // some backup token that has nowhere to go before \etc.
2110 //
2111 // So we can skim off an arbitrary number of arguments from the end of
2112 // the argument list.  The argument list remaining afterwards has to
2113 // be in not-skipping-optional-arguments mode.
2114
2115 function_arglist_partial:
2116         EXPECT_SCM function_arglist_optional
2117         {
2118                 $$ = $2;
2119         }
2120         | EXPECT_SCM function_arglist_partial_optional
2121         {
2122                 $$ = $2;
2123         }
2124         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup
2125         {
2126                 $$ = $3;
2127         }
2128         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_partial
2129         {
2130                 $$ = $3;
2131         }
2132         ;
2133
2134 function_arglist_partial_optional:
2135         EXPECT_SCM function_arglist_optional
2136         {
2137                 $$ = $2;
2138         }
2139         | EXPECT_SCM function_arglist_partial_optional
2140         {
2141                 $$ = $2;
2142         }
2143         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup
2144         {
2145                 $$ = $3;
2146         }
2147         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_partial_optional
2148         {
2149                 $$ = $3;
2150         }
2151         ;
2152
2153 function_arglist_common:
2154         EXPECT_NO_MORE_ARGS {
2155                 $$ = SCM_EOL;
2156         }
2157         | EXPECT_SCM function_arglist_optional embedded_scm_arg
2158         {
2159                 if (scm_is_true (scm_call_1 ($1, $3)))
2160                         $$ = scm_cons ($3, $2);
2161                 else
2162                         $$ = check_scheme_arg (parser, @3,
2163                                                make_music_from_simple
2164                                                (parser, @3, $3),
2165                                                $2, $1);
2166         }
2167         | EXPECT_SCM function_arglist_optional bare_number_common
2168         {
2169                 $$ = check_scheme_arg (parser, @3,
2170                                        $3, $2, $1);
2171         }
2172         | EXPECT_SCM function_arglist_optional post_event_nofinger
2173         {
2174                 $$ = check_scheme_arg (parser, @3,
2175                                        $3, $2, $1);
2176         }
2177         | EXPECT_SCM function_arglist_optional '-' NUMBER_IDENTIFIER
2178         {
2179                 SCM n = scm_difference ($4, SCM_UNDEFINED);
2180                 $$ = check_scheme_arg (parser, @4, n, $2, $1);
2181         }
2182         | function_arglist_common_reparse REPARSE SCM_ARG
2183         {
2184                 $$ = check_scheme_arg (parser, @3,
2185                                        $3, $1, $2);
2186         }
2187         | function_arglist_common_reparse REPARSE lyric_element_music
2188         {
2189                 $$ = check_scheme_arg (parser, @3,
2190                                        $3, $1, $2);
2191         }
2192         | function_arglist_common_reparse REPARSE pitch_or_music
2193         {
2194                 if (scm_is_true (scm_call_1 ($2, $3)))
2195                         $$ = scm_cons ($3, $1);
2196                 else
2197                         $$ = check_scheme_arg (parser, @3,
2198                                                make_music_from_simple
2199                                                (parser, @3, $3),
2200                                                $1, $2);
2201         }
2202         | function_arglist_common_reparse REPARSE bare_number_common
2203         {
2204                 $$ = check_scheme_arg (parser, @3,
2205                                        $3, $1, $2);
2206         }
2207         | function_arglist_common_reparse REPARSE duration_length
2208         {
2209                 $$ = check_scheme_arg (parser, @3,
2210                                        $3, $1, $2);
2211         }
2212         | function_arglist_common_reparse REPARSE symbol_list_arg
2213         {
2214                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
2215         }
2216         ;
2217
2218 function_arglist_common_reparse:
2219         EXPECT_SCM function_arglist_optional SCM_IDENTIFIER
2220         {
2221                 $$ = $2;
2222                 SCM res = try_string_variants ($1, $3);
2223                 if (!SCM_UNBNDP (res))
2224                         if (scm_is_pair (res))
2225                                 MYREPARSE (@3, $1, SYMBOL_LIST, res);
2226                         else
2227                                 MYREPARSE (@3, $1, SCM_ARG, res);
2228                 else if (scm_is_true
2229                          (scm_call_1
2230                           ($1, make_music_from_simple (parser, @3, $3))))
2231                         MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
2232                 else
2233                         // This is going to flag a syntax error, we
2234                         // know the predicate to be false.
2235                         MYREPARSE (@3, $1, SCM_ARG, $3);
2236         }
2237         | EXPECT_SCM function_arglist_optional pitch
2238         {
2239                 $$ = $2;
2240                 if (scm_is_true
2241                     (scm_call_1
2242                      ($1, make_music_from_simple
2243                       (parser, @3, $3))))
2244                         MYREPARSE (@3, $1, PITCH_IDENTIFIER, $3);
2245                 else
2246                         MYREPARSE (@3, $1, SCM_ARG, $3);
2247         }
2248         | EXPECT_SCM function_arglist_optional steno_tonic_pitch
2249         {
2250                 $$ = $2;
2251                 if (scm_is_true
2252                     (scm_call_1
2253                      ($1, make_music_from_simple
2254                       (parser, @3, $3))))
2255                         MYREPARSE (@3, $1, TONICNAME_PITCH, $3);
2256                 else
2257                         MYREPARSE (@3, $1, SCM_ARG, $3);
2258         }
2259         | EXPECT_SCM function_arglist_optional STRING
2260         {
2261                 $$ = $2;
2262                 SCM res = try_string_variants ($1, $3);
2263                 if (!SCM_UNBNDP (res))
2264                         if (scm_is_pair (res))
2265                                 MYREPARSE (@3, $1, SYMBOL_LIST, res);
2266                         else
2267                                 MYREPARSE (@3, $1, SCM_ARG, res);
2268                 else if (scm_is_true
2269                          (scm_call_1
2270                           ($1, make_music_from_simple (parser, @3, $3))))
2271                         MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
2272                 else
2273                         // This is going to flag a syntax error, we
2274                         // know the predicate to be false.
2275                         MYREPARSE (@3, $1, SCM_ARG, $3);
2276         }
2277         | EXPECT_SCM function_arglist_optional full_markup
2278         {
2279                 $$ = $2;
2280                 if (scm_is_true (scm_call_1 ($1, $3)))
2281                         MYREPARSE (@3, $1, SCM_ARG, $3);
2282                 else if (scm_is_true
2283                          (scm_call_1
2284                           ($1, make_music_from_simple (parser, @3, $3))))
2285                         MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
2286                 else
2287                         // This is going to flag a syntax error, we
2288                         // know the predicate to be false.
2289                         MYREPARSE (@3, $1, SCM_ARG, $3);
2290         }
2291         | EXPECT_SCM function_arglist_optional UNSIGNED
2292         {
2293                 $$ = $2;
2294                 if (scm_is_true (scm_call_1 ($1, $3)))
2295                         MYREPARSE (@3, $1, REAL, $3);
2296                 else {
2297                         SCM d = make_duration ($3);
2298                         if (SCM_UNBNDP (d) || scm_is_false (scm_call_1 ($1, d)))
2299                                 MYREPARSE (@3, $1, REAL, $3);
2300                         else
2301                                 MYREPARSE (@3, $1, DURATION_IDENTIFIER, d);
2302                 }
2303         }
2304         | EXPECT_SCM function_arglist_optional DURATION_IDENTIFIER
2305         {
2306                 $$ = $2;
2307                 MYREPARSE (@3, $1, DURATION_IDENTIFIER, $3);
2308         }
2309         | EXPECT_SCM function_arglist_optional '-' UNSIGNED
2310         {
2311                 $$ = $2;
2312                 SCM n = scm_difference ($4, SCM_UNDEFINED);
2313                 if (scm_is_true (scm_call_1 ($1, n)))
2314                         MYREPARSE (@4, $1, REAL, n);
2315                 else {
2316                         Music *t = MY_MAKE_MUSIC ("FingeringEvent", @4);
2317                         t->set_property ("digit", $4);
2318                         SCM m = t->unprotect ();
2319                         if (scm_is_true (scm_call_1 ($1, m)))
2320                                 MYREPARSE (@4, $1, SCM_ARG, m);
2321                         else
2322                                 MYREPARSE (@4, $1, SCM_ARG, $4);
2323                 }
2324         }
2325         | EXPECT_SCM function_arglist_optional '-' REAL
2326         {
2327                 $$ = $2;
2328                 SCM n = scm_difference ($4, SCM_UNDEFINED);
2329                 MYREPARSE (@4, $1, REAL, n);
2330         }
2331         ;
2332
2333 function_arglist_optional:
2334         function_arglist_backup
2335         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_backup DEFAULT
2336         {
2337                 $$ = scm_cons (loc_on_music (parser, @4, $1), $3);
2338         }
2339         | function_arglist_skip_backup BACKUP
2340         ;
2341
2342 function_arglist_skip_backup:
2343         function_arglist_backup
2344         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_backup
2345         {
2346                 $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
2347         }
2348         ;
2349
2350 music_function_call:
2351         MUSIC_FUNCTION function_arglist {
2352                 $$ = MAKE_SYNTAX (music_function, @$,
2353                                   $1, $2);
2354         }
2355         ;
2356
2357
2358 optional_id:
2359         /**/ { $$ = SCM_EOL; }
2360         | '=' simple_string {
2361                 $$ = $2;
2362         }
2363         ;
2364
2365 // We must not have lookahead tokens parsed in lyric mode.  In order
2366 // to save confusion, we take almost the same set as permitted with
2367 // \lyricmode and/or \lyrics.  However, music identifiers are also
2368 // allowed, and they obviously do not require switching into lyrics
2369 // mode for parsing.
2370
2371 lyric_mode_music:
2372         {
2373                 parser->lexer_->push_lyric_state ();
2374         } grouped_music_list
2375         {
2376                 parser->lexer_->pop_state ();
2377                 $$ = $2;
2378         }
2379         | MUSIC_IDENTIFIER
2380         ;
2381
2382 mode_changed_music:
2383         mode_changing_head grouped_music_list {
2384                 if (scm_is_eq ($1, ly_symbol2scm ("chords")))
2385                 {
2386                   $$ = MAKE_SYNTAX (unrelativable_music, @$, $2);
2387                 }
2388                 else
2389                 {
2390                   $$ = $2;
2391                 }
2392                 parser->lexer_->pop_state ();
2393         }
2394         | mode_changing_head_with_context optional_context_mod grouped_music_list {
2395                 Context_mod *ctxmod = unsmob<Context_mod> ($2);
2396                 SCM mods = SCM_EOL;
2397                 if (ctxmod)
2398                         mods = ctxmod->get_mods ();
2399                 $$ = MAKE_SYNTAX (context_specification, @$, $1, SCM_EOL, mods, SCM_BOOL_T, $3);
2400                 if (scm_is_eq ($1, ly_symbol2scm ("ChordNames")))
2401                 {
2402                   $$ = MAKE_SYNTAX (unrelativable_music, @$, $$);
2403                 }
2404                 parser->lexer_->pop_state ();
2405         }
2406         ;
2407
2408 mode_changing_head:
2409         NOTEMODE {
2410                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
2411                 parser->lexer_->push_note_state (nn);
2412
2413                 $$ = ly_symbol2scm ("notes");
2414         }
2415         | DRUMMODE
2416                 {
2417                 SCM nn = parser->lexer_->lookup_identifier ("drumPitchNames");
2418                 parser->lexer_->push_note_state (nn);
2419
2420                 $$ = ly_symbol2scm ("drums");
2421         }
2422         | FIGUREMODE {
2423                 parser->lexer_->push_figuredbass_state ();
2424
2425                 $$ = ly_symbol2scm ("figures");
2426         }
2427         | CHORDMODE {
2428                 SCM nn = parser->lexer_->lookup_identifier ("chordmodifiers");
2429                 parser->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
2430                 nn = parser->lexer_->lookup_identifier ("pitchnames");
2431                 parser->lexer_->push_chord_state (nn);
2432                 $$ = ly_symbol2scm ("chords");
2433
2434         }
2435         | LYRICMODE
2436                 { parser->lexer_->push_lyric_state ();
2437                 $$ = ly_symbol2scm ("lyrics");
2438         }
2439         ;
2440
2441 mode_changing_head_with_context:
2442         DRUMS {
2443                 SCM nn = parser->lexer_->lookup_identifier ("drumPitchNames");
2444                 parser->lexer_->push_note_state (nn);
2445
2446                 $$ = ly_symbol2scm ("DrumStaff");
2447         }
2448         | FIGURES {
2449                 parser->lexer_->push_figuredbass_state ();
2450
2451                 $$ = ly_symbol2scm ("FiguredBass");
2452         }
2453         | CHORDS {
2454                 SCM nn = parser->lexer_->lookup_identifier ("chordmodifiers");
2455                 parser->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
2456                 nn = parser->lexer_->lookup_identifier ("pitchnames");
2457                 parser->lexer_->push_chord_state (nn);
2458                 $$ = ly_symbol2scm ("ChordNames");
2459         }
2460         | LYRICS
2461                 { parser->lexer_->push_lyric_state ();
2462                 $$ = ly_symbol2scm ("Lyrics");
2463         }
2464         ;
2465
2466 context_change:
2467         CHANGE symbol '=' simple_string  {
2468                 $$ = MAKE_SYNTAX (context_change, @$, $2, $4);
2469         }
2470         ;
2471
2472
2473 property_path:
2474         symbol_list_rev  {
2475                 $$ = scm_reverse_x ($1, SCM_EOL);
2476         }
2477         | symbol_list_rev property_path {
2478                 $$ = scm_reverse_x ($1, $2);
2479         }
2480         ;
2481
2482 property_operation:
2483         symbol '=' scalar {
2484                 $$ = scm_list_3 (ly_symbol2scm ("assign"), $1, $3);
2485         }
2486         | UNSET symbol {
2487                 $$ = scm_list_2 (ly_symbol2scm ("unset"), $2);
2488         }
2489         | OVERRIDE property_path '=' scalar {
2490                 if (scm_ilength ($2) < 2) {
2491                         parser->parser_error (@2, _("bad grob property path"));
2492                         $$ = SCM_UNDEFINED;
2493                 } else {
2494                         $$ = scm_cons (ly_symbol2scm ("push"),
2495                                        scm_cons2 (scm_car ($2),
2496                                                   $4,
2497                                                   scm_cdr ($2)));
2498                 }
2499         }
2500         | REVERT revert_arg {
2501                 $$ = scm_cons (ly_symbol2scm ("pop"), $2);
2502         }
2503         ;
2504
2505 // This is all quite awkward for the sake of substantial backward
2506 // compatibility while at the same time allowing a more "natural" form
2507 // of specification not separating grob specification from grob
2508 // property path.  The purpose of this definition of revert_arg is to
2509 // allow the symbol list which specifies grob and property to revert
2510 // to be optionally be split into two parts after the grob (which in
2511 // this case is just the first element of the list).  symbol_list_part
2512 // is only one path component, but it can be parsed without lookahead,
2513 // so we can follow it with a synthetic BACKUP token when needed.  If
2514 // the first symbol_list_part already contains multiple elements (only
2515 // possible if a Scheme expression provides them), we just parse for
2516 // additional elements introduced by '.', which is what the
2517 // SYMBOL_LIST backup in connection with the immediately following
2518 // rule using symbol_list_arg does.
2519 //
2520 // As long as we don't have our coffers filled with both grob and at
2521 // least one grob property specification, the rest of the required
2522 // symbol list chain may be provided either with or without a leading
2523 // dot.  This is for both allowing the traditional
2524 // \revert Accidental #'color
2525 // as well as well as the "naive" form
2526 // \revert Accidental.color
2527
2528 revert_arg:
2529         revert_arg_backup BACKUP symbol_list_arg
2530         {
2531                 $$ = $3;
2532         }
2533         ;
2534
2535 revert_arg_backup:
2536         revert_arg_part
2537         {
2538                 if (scm_is_null ($1)
2539                     || scm_is_null (scm_cdr ($1)))
2540                         MYBACKUP (SCM_ARG, $1, @1);
2541                 else
2542                         MYBACKUP (SYMBOL_LIST, scm_reverse_x ($1, SCM_EOL), @1);
2543         }
2544         ;
2545
2546 // revert_arg_part delivers results in reverse
2547 revert_arg_part:
2548         symbol_list_part
2549         | revert_arg_backup BACKUP SCM_ARG '.' symbol_list_part
2550         {
2551                 $$ = scm_append_x (scm_list_2 ($5, $3));
2552         }
2553         | revert_arg_backup BACKUP SCM_ARG symbol_list_part
2554         {
2555                 $$ = scm_append_x (scm_list_2 ($4, $3));
2556         }
2557         ;
2558
2559 context_def_mod:
2560         CONSISTS { $$ = ly_symbol2scm ("consists"); }
2561         | REMOVE { $$ = ly_symbol2scm ("remove"); }
2562
2563         | ACCEPTS { $$ = ly_symbol2scm ("accepts"); }
2564         | DEFAULTCHILD { $$ = ly_symbol2scm ("default-child"); }
2565         | DENIES { $$ = ly_symbol2scm ("denies"); }
2566
2567         | ALIAS { $$ = ly_symbol2scm ("alias"); }
2568         | TYPE { $$ = ly_symbol2scm ("translator-type"); }
2569         | DESCRIPTION { $$ = ly_symbol2scm ("description"); }
2570         | NAME { $$ = ly_symbol2scm ("context-name"); }
2571         ;
2572
2573 context_mod:
2574         property_operation { $$ = $1; }
2575         | context_def_mod STRING {
2576                 $$ = scm_list_2 ($1, $2);
2577         }
2578         | context_def_mod embedded_scm
2579         {
2580                 if (!scm_is_string ($2)
2581                     && ly_symbol2scm ("consists") != $1
2582                     && ly_symbol2scm ("remove") != $1)
2583                 {
2584                         $$ = SCM_EOL;
2585                         parser->parser_error (@1, _ ("only \\consists and \\remove take non-string argument."));
2586                 }
2587                 else
2588                 {
2589                         $$ = scm_list_2 ($1, $2);
2590                 }
2591         }
2592         ;
2593
2594 // If defined, at least two members.
2595 grob_prop_spec:
2596         symbol_list_rev
2597         {
2598                 SCM l = scm_reverse_x ($1, SCM_EOL);
2599                 if (scm_is_pair (l)
2600                     && to_boolean
2601                     (scm_object_property (scm_car (l),
2602                                           ly_symbol2scm ("is-grob?"))))
2603                         l = scm_cons (ly_symbol2scm ("Bottom"), l);
2604                 if (scm_is_null (l) || scm_is_null (scm_cdr (l))) {
2605                         parser->parser_error (@1, _ ("bad grob property path"));
2606                         l = SCM_UNDEFINED;
2607                 }
2608                 $$ = l;
2609         }
2610         ;
2611
2612 // If defined, at least three members
2613 grob_prop_path:
2614         grob_prop_spec
2615         {
2616                 if (!SCM_UNBNDP ($1) && scm_is_null (scm_cddr ($1)))
2617                 {
2618                         parser->parser_error (@1, _ ("bad grob property path"));
2619                         $$ = SCM_UNDEFINED;
2620                 }
2621         }
2622         | grob_prop_spec property_path
2623         {
2624                 if (!SCM_UNBNDP ($1)) {
2625                         $$ = scm_append_x (scm_list_2 ($1, $2));
2626                         if (scm_is_null (scm_cddr ($$))) {
2627                                 parser->parser_error (@$, _ ("bad grob property path"));
2628                                 $$ = SCM_UNDEFINED;
2629                         }
2630                 }
2631
2632         }
2633         ;
2634
2635 // Exactly two elements or undefined
2636 context_prop_spec:
2637         symbol_list_rev
2638         {
2639                 SCM l = scm_reverse_x ($1, SCM_EOL);
2640                 switch (scm_ilength (l)) {
2641                 case 1:
2642                         l = scm_cons (ly_symbol2scm ("Bottom"), l);
2643                 case 2:
2644                         break;
2645                 default:
2646                         parser->parser_error (@1, _ ("bad context property path"));
2647                         l = SCM_UNDEFINED;
2648                 }
2649                 $$ = l;
2650         }
2651         ;
2652
2653
2654 // This is all quite awkward for the sake of substantial backward
2655 // compatibility while at the same time allowing a more "natural" form
2656 // of specification not separating grob specification from grob
2657 // property path.  The purpose of this definition of
2658 // simple_revert_context is to allow the symbol list which specifies
2659 // grob and property to revert to be optionally be split into two
2660 // parts after the grob (which may be preceded by a context
2661 // specification, a case which we distinguish by checking whether the
2662 // first symbol is a valid grob symbol instead).
2663 //
2664 // See revert_arg above for the main work horse of this arrangement.
2665 // simple_revert_context just caters for the context and delegates the
2666 // rest of the job to revert_arg.
2667
2668 simple_revert_context:
2669         symbol_list_part
2670         {
2671                 $1 = scm_reverse_x ($1, SCM_EOL);
2672                 if (scm_is_null ($1)
2673                     || to_boolean
2674                     (scm_object_property (scm_car ($1),
2675                                           ly_symbol2scm ("is-grob?")))) {
2676                         $$ = ly_symbol2scm ("Bottom");
2677                         parser->lexer_->push_extra_token (@1, SCM_IDENTIFIER, $1);
2678                 } else {
2679                         $$ = scm_car ($1);
2680                         parser->lexer_->push_extra_token (@1, SCM_IDENTIFIER,
2681                                                           scm_cdr ($1));
2682                 }
2683         }
2684         ;
2685
2686 music_property_def:
2687         OVERRIDE grob_prop_path '=' scalar {
2688                 if (SCM_UNBNDP ($2))
2689                         $$ = MAKE_SYNTAX (void_music, @$);
2690                 else
2691                         $$ = MAKE_SYNTAX (property_override, @$,
2692                                           scm_car ($2),
2693                                           scm_cdr ($2),
2694                                           $4);
2695         }
2696         | REVERT simple_revert_context revert_arg {
2697                 $$ = MAKE_SYNTAX (property_revert, @$, $2, $3);
2698         }
2699         | SET context_prop_spec '=' scalar {
2700                 if (SCM_UNBNDP ($2))
2701                         $$ = MAKE_SYNTAX (void_music, @$);
2702                 else
2703                         $$ = MAKE_SYNTAX (property_set, @$,
2704                                           scm_car ($2),
2705                                           scm_cadr ($2),
2706                                           $4);
2707         }
2708         | UNSET context_prop_spec {
2709                 if (SCM_UNBNDP ($2))
2710                         $$ = MAKE_SYNTAX (void_music, @$);
2711                 else
2712                         $$ = MAKE_SYNTAX (property_unset, @$,
2713                                           scm_car ($2),
2714                                           scm_cadr ($2));
2715         }
2716         ;
2717
2718 string:
2719         STRING
2720         | full_markup
2721         ;
2722
2723 text:
2724         STRING
2725         | full_markup
2726         | embedded_scm_bare
2727         {
2728                 if (Text_interface::is_markup ($1)) {
2729                         $$ = $1;
2730                 } else {
2731                         parser->parser_error (@1, (_ ("markup expected")));
2732                         $$ = scm_string (SCM_EOL);
2733                 }
2734         }
2735         ;
2736
2737 simple_string: STRING
2738         | embedded_scm_bare
2739         {
2740                 if (scm_is_string ($1)) {
2741                         $$ = $1;
2742                 } else {
2743                         parser->parser_error (@1, (_ ("simple string expected")));
2744                         $$ = scm_string (SCM_EOL);
2745                 }
2746         }
2747         ;
2748
2749 symbol:
2750         STRING {
2751                 $$ = scm_string_to_symbol ($1);
2752         }
2753         | embedded_scm_bare
2754         {
2755                 // This is a bit of overkill but makes the same
2756                 // routine responsible for all symbol interpretations.
2757                 $$ = try_string_variants (Guile_user::symbol_p, $1);
2758                 if (SCM_UNBNDP ($$))
2759                 {
2760                         parser->parser_error (@1, (_ ("symbol expected")));
2761                         // Generate a unique symbol in case it is used
2762                         // for an assignment or similar
2763                         $$ = scm_make_symbol (ly_string2scm ("undefined"));
2764                 }
2765         }
2766         ;
2767
2768 scalar:
2769         embedded_scm_arg
2770         | pitch_or_music
2771         | SCM_IDENTIFIER
2772         | bare_number
2773         // The following is a rather defensive variant of admitting
2774         // negative numbers: the grammar would permit number_factor or
2775         // even number_expression.  However, function arguments allow
2776         // only this simple kind of negative number, so to have things
2777         // like \tweak and \override behave reasonably similar, it
2778         // makes sense to rule out things like -- which are rather an
2779         // accent in function argument contexts.
2780         | '-' bare_number
2781         {
2782                 $$ = scm_difference ($2, SCM_UNDEFINED);
2783         }
2784         | string
2785         ;
2786
2787 event_chord:
2788         simple_element post_events {
2789                 // Let the rhythmic music iterator sort this mess out.
2790                 if (scm_is_pair ($2)) {
2791                         unsmob<Music> ($$)->set_property ("articulations",
2792                                                          scm_reverse_x ($2, SCM_EOL));
2793                 }
2794         } %prec ':'
2795         | CHORD_REPETITION optional_notemode_duration post_events {
2796                 Input i;
2797                 i.set_location (@1, @3);
2798                 $$ = MAKE_SYNTAX (repetition_chord, i,
2799                                   $2, scm_reverse_x ($3, SCM_EOL));
2800         } %prec ':'
2801         | MULTI_MEASURE_REST optional_notemode_duration post_events {
2802                 Input i;
2803                 i.set_location (@1, @3);
2804                 $$ = MAKE_SYNTAX (multi_measure_rest, i, $2,
2805                                   scm_reverse_x ($3, SCM_EOL));
2806         } %prec ':'
2807         | tempo_event
2808         | note_chord_element
2809         ;
2810
2811
2812 note_chord_element:
2813         chord_body optional_notemode_duration post_events
2814         {
2815                 Music *m = unsmob<Music> ($1);
2816                 SCM dur = unsmob<Duration> ($2)->smobbed_copy ();
2817                 SCM es = m->get_property ("elements");
2818                 SCM postevs = scm_reverse_x ($3, SCM_EOL);
2819
2820                 for (SCM s = es; scm_is_pair (s); s = scm_cdr (s))
2821                   unsmob<Music> (scm_car (s))->set_property ("duration", dur);
2822                 es = ly_append2 (es, postevs);
2823
2824                 m->set_property ("elements", es);
2825                 m->set_spot (parser->lexer_->override_input (@$));
2826                 $$ = m->self_scm ();
2827         } %prec ':'
2828         ;
2829
2830 chord_body:
2831         ANGLE_OPEN chord_body_elements ANGLE_CLOSE
2832         {
2833                 $$ = MAKE_SYNTAX (event_chord, @$, scm_reverse_x ($2, SCM_EOL));
2834         }
2835         | FIGURE_OPEN figure_list FIGURE_CLOSE
2836         {
2837                 $$ = MAKE_SYNTAX (event_chord, @$, scm_reverse_x ($2, SCM_EOL));
2838         }
2839         ;
2840
2841 chord_body_elements:
2842         /* empty */             { $$ = SCM_EOL; }
2843         | chord_body_elements chord_body_element {
2844                 if (!SCM_UNBNDP ($2))
2845                         $$ = scm_cons ($2, $1);
2846         }
2847         ;
2848
2849 chord_body_element:
2850         pitch_or_tonic_pitch exclamations questions octave_check post_events
2851         {
2852                 bool q = to_boolean ($3);
2853                 bool ex = to_boolean ($2);
2854                 SCM check = $4;
2855                 SCM post = $5;
2856
2857                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
2858                 n->set_property ("pitch", $1);
2859                 if (q)
2860                         n->set_property ("cautionary", SCM_BOOL_T);
2861                 if (ex || q)
2862                         n->set_property ("force-accidental", SCM_BOOL_T);
2863
2864                 if (scm_is_pair (post)) {
2865                         SCM arts = scm_reverse_x (post, SCM_EOL);
2866                         n->set_property ("articulations", arts);
2867                 }
2868                 if (scm_is_number (check))
2869                 {
2870                         int q = scm_to_int (check);
2871                         n->set_property ("absolute-octave", scm_from_int (q-1));
2872                 }
2873
2874                 $$ = n->unprotect ();
2875         }
2876         | DRUM_PITCH post_events {
2877                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
2878                 n->set_property ("drum-type", $1);
2879
2880                 if (scm_is_pair ($2)) {
2881                         SCM arts = scm_reverse_x ($2, SCM_EOL);
2882                         n->set_property ("articulations", arts);
2883                 }
2884                 $$ = n->unprotect ();
2885         }
2886         | music_function_chord_body
2887         {
2888                 Music *m = unsmob<Music> ($1);
2889
2890                 while (m && m->is_mus_type ("music-wrapper-music")) {
2891                         $$ = m->get_property ("element");
2892                         m = unsmob<Music> ($$);
2893                 }
2894
2895                 if (!(m && m->is_mus_type ("rhythmic-event"))) {
2896                         parser->parser_error (@$, _ ("not a rhythmic event"));
2897                         $$ = SCM_UNDEFINED;
2898                 }
2899         }
2900         ;
2901
2902 music_function_chord_body:
2903         music_function_call
2904         | MUSIC_IDENTIFIER
2905         | embedded_scm
2906         ;
2907
2908 event_function_event:
2909         EVENT_FUNCTION function_arglist {
2910                 $$ = MAKE_SYNTAX (music_function, @$,
2911                                   $1, $2);
2912         }
2913         ;
2914
2915 post_events:
2916         /* empty */ {
2917                 $$ = SCM_EOL;
2918         }
2919         | post_events post_event {
2920                 $$ = $1;
2921                 if (Music *m = unsmob<Music> ($2))
2922                 {
2923                         if (m->is_mus_type ("post-event-wrapper"))
2924                         {
2925                                 for (SCM p = m->get_property ("elements");
2926                                      scm_is_pair (p);
2927                                      p = scm_cdr (p))
2928                                 {
2929                                         $$ = scm_cons (scm_car (p), $$);
2930                                 }
2931                         } else {
2932                                 m->set_spot (parser->lexer_->override_input (@2));
2933                                 $$ = scm_cons ($2, $$);
2934                         }
2935                 }
2936         }
2937         ;
2938
2939 post_event_nofinger:
2940         direction_less_event {
2941                 $$ = $1;
2942         }
2943         | script_dir music_function_call {
2944                 $$ = $2;
2945                 if (!unsmob<Music> ($2)->is_mus_type ("post-event")) {
2946                         parser->parser_error (@2, _ ("post-event expected"));
2947                         $$ = SCM_UNSPECIFIED;
2948                 } else if (!SCM_UNBNDP ($1))
2949                 {
2950                         unsmob<Music> ($$)->set_property ("direction", $1);
2951                 }
2952         }
2953         | HYPHEN {
2954                 if (!parser->lexer_->is_lyric_state ())
2955                         parser->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
2956                 $$ = MY_MAKE_MUSIC ("HyphenEvent", @$)->unprotect ();
2957         }
2958         | EXTENDER {
2959                 if (!parser->lexer_->is_lyric_state ())
2960                         parser->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
2961                 $$ = MY_MAKE_MUSIC ("ExtenderEvent", @$)->unprotect ();
2962         }
2963         | script_dir direction_reqd_event {
2964                 if (!SCM_UNBNDP ($1))
2965                 {
2966                         Music *m = unsmob<Music> ($2);
2967                         m->set_property ("direction", $1);
2968                 }
2969                 $$ = $2;
2970         }
2971         | script_dir direction_less_event {
2972                 if (!SCM_UNBNDP ($1))
2973                 {
2974                         Music *m = unsmob<Music> ($2);
2975                         m->set_property ("direction", $1);
2976                 }
2977                 $$ = $2;
2978         }
2979         | '^' fingering
2980         {
2981                 $$ = $2;
2982                 unsmob<Music> ($$)->set_property ("direction", scm_from_int (UP));
2983         }
2984         | '_' fingering
2985         {
2986                 $$ = $2;
2987                 unsmob<Music> ($$)->set_property ("direction", scm_from_int (DOWN));
2988         }
2989         ;
2990
2991 post_event:
2992         post_event_nofinger
2993         | '-' fingering {
2994                 $$ = $2;
2995         }
2996         ;
2997
2998 string_number_event:
2999         E_UNSIGNED {
3000                 Music *s = MY_MAKE_MUSIC ("StringNumberEvent", @$);
3001                 s->set_property ("string-number", $1);
3002                 $$ = s->unprotect ();
3003         }
3004         ;
3005
3006 direction_less_event:
3007         string_number_event
3008         | EVENT_IDENTIFIER      {
3009                 $$ = $1;
3010         }
3011         | tremolo_type  {
3012                Music *a = MY_MAKE_MUSIC ("TremoloEvent", @$);
3013                a->set_property ("tremolo-type", $1);
3014                $$ = a->unprotect ();
3015         }
3016         | event_function_event
3017         ;
3018
3019 direction_reqd_event:
3020         gen_text_def {
3021                 $$ = $1;
3022         }
3023         | script_abbreviation {
3024                 SCM s = parser->lexer_->lookup_identifier ("dash" + ly_scm2string ($1));
3025                 if (scm_is_string (s)) {
3026                         Music *a = MY_MAKE_MUSIC ("ArticulationEvent", @$);
3027                         a->set_property ("articulation-type", s);
3028                         $$ = a->unprotect ();
3029                 } else {
3030                         Music *original = unsmob<Music> (s);
3031                         if (original && original->is_mus_type ("post-event")) {
3032                                 Music *a = original->clone ();
3033                                 a->set_spot (parser->lexer_->override_input (@$));
3034                                 $$ = a->unprotect ();
3035                         } else {
3036                                 parser->parser_error (@1, _ ("expecting string or post-event as script definition"));
3037                                 $$ = MY_MAKE_MUSIC ("PostEvents", @$)->unprotect ();
3038                         }
3039                 }
3040         }
3041         ;
3042
3043 octave_check:
3044         /**/ { $$ = SCM_EOL; }
3045         | '=' quotes { $$ = $2; }
3046         ;
3047
3048 quotes:
3049         /* empty */
3050         {
3051                 $$ = SCM_INUM0;
3052         }
3053         | sub_quotes
3054         | sup_quotes
3055         ;
3056
3057 sup_quotes:
3058         '\'' {
3059                 $$ = scm_from_int (1);
3060         }
3061         | sup_quotes '\'' {
3062                 $$ = scm_oneplus ($1);
3063         }
3064         ;
3065
3066 sub_quotes:
3067         ',' {
3068                 $$ = scm_from_int (-1);
3069         }
3070         | sub_quotes ',' {
3071                 $$ = scm_oneminus ($1);
3072         }
3073         ;
3074
3075 steno_pitch:
3076         NOTENAME_PITCH quotes {
3077                 if (!scm_is_eq (SCM_INUM0, $2))
3078                 {
3079                         Pitch p = *unsmob<Pitch> ($1);
3080                         p = p.transposed (Pitch (scm_to_int ($2), 0));
3081                         $$ = p.smobbed_copy ();
3082                 }
3083         }
3084         ;
3085
3086 /*
3087 ugh. duplication
3088 */
3089
3090 steno_tonic_pitch:
3091         TONICNAME_PITCH quotes {
3092                 if (!scm_is_eq (SCM_INUM0, $2))
3093                 {
3094                         Pitch p = *unsmob<Pitch> ($1);
3095                         p = p.transposed (Pitch (scm_to_int ($2), 0));
3096                         $$ = p.smobbed_copy ();
3097                 }
3098         }
3099         ;
3100
3101 pitch:
3102         steno_pitch
3103         | PITCH_IDENTIFIER quotes {
3104                 if (!scm_is_eq (SCM_INUM0, $2))
3105                 {
3106                         Pitch p = *unsmob<Pitch> ($1);
3107                         p = p.transposed (Pitch (scm_to_int ($2), 0));
3108                         $$ = p.smobbed_copy ();
3109                 }
3110         }
3111         ;
3112
3113 pitch_or_tonic_pitch:
3114         pitch
3115         | steno_tonic_pitch
3116         ;
3117
3118 gen_text_def:
3119         full_markup {
3120                 Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
3121                 t->set_property ("text", $1);
3122                 $$ = t->unprotect ();
3123         }
3124         | STRING {
3125                 Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
3126                 t->set_property ("text",
3127                         make_simple_markup ($1));
3128                 $$ = t->unprotect ();
3129         }
3130         | embedded_scm
3131         {
3132                 Music *m = unsmob<Music> ($1);
3133                 if (m && m->is_mus_type ("post-event"))
3134                         $$ = $1;
3135                 else if (Text_interface::is_markup ($1)) {
3136                         Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
3137                         t->set_property ("text", $1);
3138                         $$ = t->unprotect ();
3139                 } else
3140                         parser->parser_error (@1, _ ("not an articulation"));
3141         }
3142         ;
3143
3144 fingering:
3145         UNSIGNED {
3146                 Music *t = MY_MAKE_MUSIC ("FingeringEvent", @$);
3147                 t->set_property ("digit", $1);
3148                 $$ = t->unprotect ();
3149         }
3150         ;
3151
3152 script_abbreviation:
3153         '^'             {
3154                 $$ = scm_from_ascii_string ("Hat");
3155         }
3156         | '+'           {
3157                 $$ = scm_from_ascii_string ("Plus");
3158         }
3159         | '-'           {
3160                 $$ = scm_from_ascii_string ("Dash");
3161         }
3162         | '!'           {
3163                 $$ = scm_from_ascii_string ("Bang");
3164         }
3165         | ANGLE_CLOSE   {
3166                 $$ = scm_from_ascii_string ("Larger");
3167         }
3168         | '.'           {
3169                 $$ = scm_from_ascii_string ("Dot");
3170         }
3171         | '_' {
3172                 $$ = scm_from_ascii_string ("Underscore");
3173         }
3174         ;
3175
3176 script_dir:
3177         '_'     { $$ = scm_from_int (DOWN); }
3178         | '^'   { $$ = scm_from_int (UP); }
3179         | '-'   { $$ = SCM_UNDEFINED; }
3180         ;
3181
3182 duration_length:
3183         multiplied_duration {
3184                 $$ = $1;
3185         }
3186         ;
3187
3188 maybe_notemode_duration:
3189         {
3190                 $$ = SCM_UNDEFINED;
3191         } %prec ':'
3192         | multiplied_duration   {
3193                 $$ = $1;
3194                 parser->default_duration_ = *unsmob<Duration> ($$);
3195         }
3196 ;
3197
3198
3199 optional_notemode_duration:
3200         maybe_notemode_duration
3201         {
3202                 if (SCM_UNBNDP ($$))
3203                         $$ = parser->default_duration_.smobbed_copy ();
3204         }
3205         ;
3206
3207 steno_duration:
3208         UNSIGNED dots           {
3209                 $$ = make_duration ($1, scm_to_int ($2));
3210                 if (SCM_UNBNDP ($$))
3211                 {
3212                         parser->parser_error (@1, _ ("not a duration"));
3213                         $$ = Duration ().smobbed_copy ();
3214                 }
3215         }
3216         | DURATION_IDENTIFIER dots      {
3217                 Duration *d = unsmob<Duration> ($1);
3218                 Duration k (d->duration_log (),
3219                             d->dot_count () + scm_to_int ($2));
3220                 k = k.compressed (d->factor ());
3221                 scm_remember_upto_here_1 ($1);
3222                 $$ = k.smobbed_copy ();
3223         }
3224         ;
3225
3226 multiplied_duration:
3227         steno_duration {
3228                 $$ = $1;
3229         }
3230         | multiplied_duration '*' UNSIGNED {
3231                 $$ = unsmob<Duration> ($$)->compressed (scm_to_int ($3)).smobbed_copy ();
3232         }
3233         | multiplied_duration '*' FRACTION {
3234                 Rational  m (scm_to_int (scm_car ($3)), scm_to_int (scm_cdr ($3)));
3235
3236                 $$ = unsmob<Duration> ($$)->compressed (m).smobbed_copy ();
3237         }
3238         ;
3239
3240 dots:
3241         /* empty */     {
3242                 $$ = SCM_INUM0;
3243         }
3244         | dots '.' {
3245                 $$ = scm_oneplus ($1);
3246         }
3247         ;
3248
3249 tremolo_type:
3250         ':'     {
3251                 $$ = scm_from_int (parser->default_tremolo_type_);
3252         }
3253         | ':' UNSIGNED {
3254                 if (SCM_UNBNDP (make_duration ($2))) {
3255                         parser->parser_error (@2, _ ("not a duration"));
3256                         $$ = scm_from_int (parser->default_tremolo_type_);
3257                 } else {
3258                         $$ = $2;
3259                         parser->default_tremolo_type_ = scm_to_int ($2);
3260                 }
3261         }
3262         ;
3263
3264 bass_number:
3265         UNSIGNED { $$ = $1; }
3266         | STRING { $$ = $1; }
3267         | full_markup { $$ = $1; }
3268         | embedded_scm_bare
3269         {
3270                 // as an integer, it needs to be non-negative, and otherwise
3271                 // it needs to be suitable as a markup.
3272                 if (scm_is_integer ($1)
3273                     ? scm_is_true (scm_negative_p ($1))
3274                     : !Text_interface::is_markup ($1))
3275                 {
3276                         parser->parser_error (@1, _ ("bass number expected"));
3277                         $$ = SCM_INUM0;
3278                 }
3279         }
3280         ;
3281
3282 figured_bass_alteration:
3283         '-'     { $$ = ly_rational2scm (FLAT_ALTERATION); }
3284         | '+'   { $$ = ly_rational2scm (SHARP_ALTERATION); }
3285         | '!'   { $$ = scm_from_int (0); }
3286         ;
3287
3288 bass_figure:
3289         FIGURE_SPACE {
3290                 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent", @$);
3291                 $$ = bfr->unprotect ();
3292         }
3293         | bass_number  {
3294                 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent", @$);
3295                 $$ = bfr->self_scm ();
3296
3297                 if (scm_is_number ($1))
3298                         bfr->set_property ("figure", $1);
3299                 else if (Text_interface::is_markup ($1))
3300                         bfr->set_property ("text", $1);
3301
3302                 bfr->unprotect ();
3303         }
3304         | bass_figure ']' {
3305                 $$ = $1;
3306                 unsmob<Music> ($1)->set_property ("bracket-stop", SCM_BOOL_T);
3307         }
3308         | bass_figure figured_bass_alteration {
3309                 Music *m = unsmob<Music> ($1);
3310                 if (scm_to_double ($2)) {
3311                         SCM salter = m->get_property ("alteration");
3312                         SCM alter = scm_is_number (salter) ? salter : scm_from_int (0);
3313                         m->set_property ("alteration",
3314                                          scm_sum (alter, $2));
3315                 } else {
3316                         m->set_property ("alteration", scm_from_int (0));
3317                 }
3318         }
3319         | bass_figure figured_bass_modification  {
3320                 Music *m = unsmob<Music> ($1);
3321                 m->set_property ($2, SCM_BOOL_T);
3322         }
3323         ;
3324
3325
3326 figured_bass_modification:
3327         E_PLUS          {
3328                 $$ = ly_symbol2scm ("augmented");
3329         }
3330         | E_EXCLAMATION {
3331                 $$ = ly_symbol2scm ("no-continuation");
3332         }
3333         | '/'           {
3334                 $$ = ly_symbol2scm ("diminished");
3335         }
3336         | E_BACKSLASH {
3337                 $$ = ly_symbol2scm ("augmented-slash");
3338         }
3339         ;
3340
3341 br_bass_figure:
3342         bass_figure {
3343                 $$ = $1;
3344         }
3345         | '[' bass_figure {
3346                 $$ = $2;
3347                 unsmob<Music> ($$)->set_property ("bracket-start", SCM_BOOL_T);
3348         }
3349         ;
3350
3351 figure_list:
3352         /**/            {
3353                 $$ = SCM_EOL;
3354         }
3355         | figure_list br_bass_figure {
3356                 $$ = scm_cons ($2, $1);
3357         }
3358         ;
3359
3360 optional_rest:
3361         /**/   { $$ = SCM_BOOL_F; }
3362         | REST { $$ = SCM_BOOL_T; }
3363         ;
3364
3365 pitch_or_music:
3366         pitch exclamations questions octave_check maybe_notemode_duration optional_rest post_events {
3367                 if (!parser->lexer_->is_note_state ())
3368                         parser->parser_error (@1, _ ("have to be in Note mode for notes"));
3369                 if (!SCM_UNBNDP ($2)
3370                     || !SCM_UNBNDP ($3)
3371                     || scm_is_number ($4)
3372                     || !SCM_UNBNDP ($5)
3373                     || scm_is_true ($6)
3374                     || scm_is_pair ($7))
3375                 {
3376                         Music *n = 0;
3377                         if (scm_is_true ($6))
3378                                 n = MY_MAKE_MUSIC ("RestEvent", @$);
3379                         else
3380                                 n = MY_MAKE_MUSIC ("NoteEvent", @$);
3381
3382                         n->set_property ("pitch", $1);
3383                         if (SCM_UNBNDP ($5))
3384                                 n->set_property ("duration",
3385                                                  parser->default_duration_.smobbed_copy ());
3386                         else
3387                                 n->set_property ("duration", $5);
3388
3389                         if (scm_is_number ($4))
3390                         {
3391                                 int q = scm_to_int ($4);
3392                                 n->set_property ("absolute-octave", scm_from_int (q-1));
3393                         }
3394
3395                         if (to_boolean ($3))
3396                                 n->set_property ("cautionary", SCM_BOOL_T);
3397                         if (to_boolean ($2) || to_boolean ($3))
3398                                 n->set_property ("force-accidental", SCM_BOOL_T);
3399                         if (scm_is_pair ($7))
3400                                 n->set_property ("articulations",
3401                                                  scm_reverse_x ($7, SCM_EOL));
3402                         $$ = n->unprotect ();
3403                 }
3404         } %prec ':'
3405         | new_chord post_events {
3406                 if (!parser->lexer_->is_chord_state ())
3407                         parser->parser_error (@1, _ ("have to be in Chord mode for chords"));
3408                 if (scm_is_pair ($2)) {
3409                         if (unsmob<Pitch> ($1))
3410                                 $1 = make_chord_elements (@1,
3411                                                           $1,
3412                                                           parser->default_duration_.smobbed_copy (),
3413                                                           SCM_EOL);
3414
3415                         SCM elts = ly_append2 ($1, scm_reverse_x ($2, SCM_EOL));
3416
3417                         $$ = MAKE_SYNTAX (event_chord, @1, elts);
3418                 } else if (!unsmob<Pitch> ($1))
3419                         $$ = MAKE_SYNTAX (event_chord, @1, $1);
3420                 // A mere pitch drops through.
3421         } %prec ':'
3422         ;
3423
3424 simple_element:
3425         DRUM_PITCH optional_notemode_duration {
3426                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
3427                 n->set_property ("duration", $2);
3428                 n->set_property ("drum-type", $1);
3429
3430                 $$ = n->unprotect ();
3431         }
3432         | RESTNAME optional_notemode_duration           {
3433                 Music *ev = 0;
3434                 if (ly_scm2string ($1) == "s") {
3435                         /* Space */
3436                         ev = MY_MAKE_MUSIC ("SkipEvent", @$);
3437                   }
3438                 else {
3439                         ev = MY_MAKE_MUSIC ("RestEvent", @$);
3440
3441                     }
3442                 ev->set_property ("duration", $2);
3443                 $$ = ev->unprotect ();
3444         }
3445         ;
3446
3447 lyric_element:
3448         full_markup {
3449                 if (!parser->lexer_->is_lyric_state ())
3450                         parser->parser_error (@1, _ ("markup outside of text script or \\lyricmode"));
3451                 $$ = $1;
3452         }
3453         | STRING {
3454                 if (!parser->lexer_->is_lyric_state ())
3455                         parser->parser_error (@1, _ ("unrecognized string, not in text script or \\lyricmode"));
3456                 $$ = $1;
3457         }
3458         | LYRIC_ELEMENT
3459         ;
3460
3461 lyric_element_music:
3462         lyric_element optional_notemode_duration post_events {
3463                 $$ = MAKE_SYNTAX (lyric_event, @$, $1, $2);
3464                 if (scm_is_pair ($3))
3465                         unsmob<Music> ($$)->set_property
3466                                 ("articulations", scm_reverse_x ($3, SCM_EOL));
3467         } %prec ':'
3468         ;
3469
3470 // Can return a single pitch rather than a list.
3471 new_chord:
3472         steno_tonic_pitch maybe_notemode_duration   {
3473                 if (SCM_UNBNDP ($2))
3474                         $$ = $1;
3475                 else
3476                         $$ = make_chord_elements (@$, $1, $2, SCM_EOL);
3477         }
3478         | steno_tonic_pitch optional_notemode_duration chord_separator chord_items {
3479                 SCM its = scm_reverse_x ($4, SCM_EOL);
3480                 $$ = make_chord_elements (@$, $1, $2, scm_cons ($3, its));
3481         } %prec ':'
3482         ;
3483
3484 chord_items:
3485         /**/ {
3486                 $$ = SCM_EOL;
3487         }
3488         | chord_items chord_item {
3489                 $$ = scm_cons ($2, $$);
3490         }
3491         ;
3492
3493 chord_separator:
3494         CHORD_COLON {
3495                 $$ = ly_symbol2scm ("chord-colon");
3496         }
3497         | CHORD_CARET {
3498                 $$ = ly_symbol2scm ("chord-caret");
3499         }
3500         | CHORD_SLASH steno_tonic_pitch {
3501                 $$ = scm_list_2 (ly_symbol2scm ("chord-slash"), $2);
3502         }
3503         | CHORD_BASS steno_tonic_pitch {
3504                 $$ = scm_list_2 (ly_symbol2scm ("chord-bass"), $2);
3505         }
3506         ;
3507
3508 chord_item:
3509         chord_separator {
3510                 $$ = $1;
3511         }
3512         | step_numbers {
3513                 $$ = scm_reverse_x ($1, SCM_EOL);
3514         }
3515         | CHORD_MODIFIER  {
3516                 $$ = $1;
3517         }
3518         ;
3519
3520 step_numbers:
3521         step_number { $$ = scm_cons ($1, SCM_EOL); }
3522         | step_numbers '.' step_number {
3523                 $$ = scm_cons ($3, $$);
3524         }
3525         ;
3526
3527 step_number:
3528         UNSIGNED {
3529                 $$ = make_chord_step ($1, 0);
3530         }
3531         | UNSIGNED '+' {
3532                 $$ = make_chord_step ($1, SHARP_ALTERATION);
3533         }
3534         | UNSIGNED CHORD_MINUS {
3535                 $$ = make_chord_step ($1, FLAT_ALTERATION);
3536         }
3537         ;
3538
3539 tempo_range:
3540         unsigned_number {
3541                 $$ = $1;
3542         } %prec ':'
3543         | unsigned_number '-' unsigned_number {
3544                 $$ = scm_cons ($1, $3);
3545         }
3546         ;
3547
3548 /*
3549         UTILITIES
3550
3551 TODO: should deprecate in favor of Scheme?
3552
3553  */
3554 number_expression:
3555         number_expression '+' number_term {
3556                 $$ = scm_sum ($1, $3);
3557         }
3558         | number_expression '-' number_term {
3559                 $$ = scm_difference ($1, $3);
3560         }
3561         | number_term
3562         ;
3563
3564 number_term:
3565         number_factor {
3566                 $$ = $1;
3567         }
3568         | number_factor '*' number_factor {
3569                 $$ = scm_product ($1, $3);
3570         }
3571         | number_factor '/' number_factor {
3572                 $$ = scm_divide ($1, $3);
3573         }
3574         ;
3575
3576 number_factor:
3577         '-'  number_factor { /* %prec UNARY_MINUS */
3578                 $$ = scm_difference ($2, SCM_UNDEFINED);
3579         }
3580         | bare_number
3581         ;
3582
3583 bare_number_common:
3584         REAL
3585         | NUMBER_IDENTIFIER
3586         | REAL NUMBER_IDENTIFIER
3587         {
3588                 $$ = scm_product ($1, $2);
3589         }
3590         ;
3591
3592 bare_number:
3593         bare_number_common
3594         | UNSIGNED
3595         | UNSIGNED NUMBER_IDENTIFIER    {
3596                 $$ = scm_product ($1, $2);
3597         }
3598         ;
3599
3600 unsigned_number:
3601         UNSIGNED
3602         | NUMBER_IDENTIFIER
3603         {
3604                 if (!scm_is_integer ($1)
3605                     || scm_is_true (scm_negative_p ($1)))
3606                 {
3607                         parser->parser_error (@1, _("not an unsigned integer"));
3608                         $$ = SCM_INUM0;
3609                 }
3610         }
3611         | embedded_scm
3612         {
3613                 if (!scm_is_integer ($1)
3614                     || scm_is_true (scm_negative_p ($1)))
3615                 {
3616                         parser->parser_error (@1, _("not an unsigned integer"));
3617                         $$ = SCM_INUM0;
3618                 }
3619         }
3620         ;
3621
3622 exclamations:
3623                 { $$ = SCM_UNDEFINED; }
3624         | exclamations '!'
3625         {
3626                 if (SCM_UNBNDP ($1))
3627                         $$ = SCM_BOOL_T;
3628                 else
3629                         $$ = scm_not ($1);
3630         }
3631         ;
3632
3633 questions:
3634 // This precedence rule is rather weird.  It triggers when '!' is
3635 // encountered after a pitch, and is used for deciding whether to save
3636 // this instead for a figure modification.  This should not actually
3637 // occur in practice as pitches and figures are generated in different
3638 // modes.  Using a greedy (%right) precedence makes sure that we don't
3639 // get stuck in a wrong interpretation.
3640         { $$ = SCM_UNDEFINED; } %prec ':'
3641         | questions '?'
3642         {
3643                 if (SCM_UNBNDP ($1))
3644                         $$ = SCM_BOOL_T;
3645                 else
3646                         $$ = scm_not ($1);
3647         }
3648         ;
3649
3650 full_markup_list:
3651         MARKUPLIST
3652                 { parser->lexer_->push_markup_state (); }
3653         markup_list {
3654                 $$ = $3;
3655                 parser->lexer_->pop_state ();
3656         }
3657         ;
3658
3659 markup_mode:
3660         MARKUP
3661         {
3662                 parser->lexer_->push_markup_state ();
3663         }
3664         ;
3665
3666 full_markup:
3667         markup_mode markup_top {
3668                 $$ = $2;
3669                 parser->lexer_->pop_state ();
3670         }
3671         ;
3672
3673 partial_markup:
3674         markup_mode markup_partial_function ETC
3675         {
3676                 $$ = MAKE_SYNTAX (partial_markup, @2, $2);
3677                 parser->lexer_->pop_state ();
3678         }
3679         ;
3680
3681 markup_top:
3682         markup_list {
3683                 $$ = scm_list_2 (Lily::line_markup,  $1);
3684         }
3685         | markup_head_1_list simple_markup
3686         {
3687                 $$ = scm_car (MAKE_SYNTAX (composed_markup_list,
3688                                            @2, $1, scm_list_1 ($2)));
3689         }
3690         | simple_markup {
3691                 $$ = $1;
3692         }
3693         ;
3694
3695 markup_scm:
3696         embedded_scm
3697         {
3698                 if (Text_interface::is_markup ($1))
3699                         MYBACKUP (MARKUP_IDENTIFIER, $1, @1);
3700                 else if (Text_interface::is_markup_list ($1))
3701                         MYBACKUP (MARKUPLIST_IDENTIFIER, $1, @1);
3702                 else {
3703                         parser->parser_error (@1, _ ("not a markup"));
3704                         MYBACKUP (MARKUP_IDENTIFIER, scm_string (SCM_EOL), @1);
3705                 }
3706         } BACKUP
3707         ;
3708
3709
3710 markup_list:
3711         markup_composed_list {
3712                 $$ = $1;
3713         }
3714         | markup_uncomposed_list
3715         ;
3716
3717 markup_uncomposed_list:
3718         markup_braced_list {
3719                 $$ = $1;
3720         }
3721         | markup_command_list {
3722                 $$ = scm_list_1 ($1);
3723         }
3724         | markup_scm MARKUPLIST_IDENTIFIER
3725         {
3726                 $$ = $2;
3727         }
3728         | SCORELINES {
3729                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
3730                 parser->lexer_->push_note_state (nn);
3731         } '{' score_body '}' {
3732                 Score *sc = unsmob<Score> ($4);
3733                 sc->origin ()->set_spot (@$);
3734                 if (sc->defs_.empty ()) {
3735                         Output_def *od = get_layout (parser);
3736                         sc->add_output_def (od);
3737                         od->unprotect ();
3738                 }
3739                 $$ = scm_list_1 (scm_list_2 (Lily::score_lines_markup_list, $4));
3740                 parser->lexer_->pop_state ();
3741         }
3742         ;
3743
3744 markup_composed_list:
3745         markup_head_1_list markup_uncomposed_list {
3746                 $$ = MAKE_SYNTAX (composed_markup_list,
3747                                   @2, $1, $2);
3748         }
3749         ;
3750
3751 markup_braced_list:
3752         '{' markup_braced_list_body '}' {
3753                 $$ = scm_reverse_x ($2, SCM_EOL);
3754         }
3755         ;
3756
3757 markup_braced_list_body:
3758         /* empty */     {  $$ = SCM_EOL; }
3759         | markup_braced_list_body markup {
3760                 $$ = scm_cons ($2, $1);
3761         }
3762         | markup_braced_list_body markup_list {
3763                 $$ = scm_reverse_x ($2, $1);
3764         }
3765         ;
3766
3767 markup_command_list:
3768         MARKUP_LIST_FUNCTION markup_command_list_arguments {
3769           $$ = scm_cons ($1, scm_reverse_x($2, SCM_EOL));
3770         }
3771         ;
3772
3773 markup_command_basic_arguments:
3774         EXPECT_MARKUP_LIST markup_command_list_arguments markup_list {
3775           $$ = scm_cons ($3, $2);
3776         }
3777         | EXPECT_SCM markup_command_list_arguments embedded_scm {
3778           $$ = check_scheme_arg (parser, @3, $3, $2, $1);
3779         }
3780         | EXPECT_NO_MORE_ARGS {
3781           $$ = SCM_EOL;
3782         }
3783         ;
3784
3785 markup_command_list_arguments:
3786         markup_command_basic_arguments { $$ = $1; }
3787         | EXPECT_MARKUP markup_command_list_arguments markup {
3788           $$ = scm_cons ($3, $2);
3789         }
3790         ;
3791
3792 markup_partial_function:
3793         MARKUP_FUNCTION markup_arglist_partial
3794         {
3795                 $$ = scm_list_1 (scm_cons ($1, scm_reverse_x ($2, SCM_EOL)));
3796         }
3797         | markup_head_1_list MARKUP_FUNCTION markup_arglist_partial
3798         {
3799                 $$ = scm_cons (scm_cons ($2, scm_reverse_x ($3, SCM_EOL)),
3800                                $1);
3801         }
3802         ;
3803
3804 markup_arglist_partial:
3805         EXPECT_MARKUP markup_arglist_partial
3806         {
3807                 $$ = $2;
3808         }
3809         | EXPECT_SCM markup_arglist_partial
3810         {
3811                 $$= $2;
3812         }
3813         | EXPECT_MARKUP markup_command_list_arguments
3814         {
3815                 $$ = $2;
3816         }
3817         | EXPECT_SCM markup_command_list_arguments
3818         {
3819                 $$ = $2;
3820         }
3821         ;
3822
3823 markup_head_1_item:
3824         MARKUP_FUNCTION EXPECT_MARKUP markup_command_list_arguments {
3825           $$ = scm_cons ($1, scm_reverse_x ($3, SCM_EOL));
3826         }
3827         ;
3828
3829 markup_head_1_list:
3830         markup_head_1_item      {
3831                 $$ = scm_list_1 ($1);
3832         }
3833         | markup_head_1_list markup_head_1_item {
3834                 $$ = scm_cons ($2, $1);
3835         }
3836         ;
3837
3838 simple_markup:
3839         STRING {
3840                 $$ = make_simple_markup ($1);
3841         }
3842         | SCORE {
3843                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
3844                 parser->lexer_->push_note_state (nn);
3845         } '{' score_body '}' {
3846                 Score *sc = unsmob<Score> ($4);
3847                 sc->origin ()->set_spot (@$);
3848                 if (sc->defs_.empty ()) {
3849                         Output_def *od = get_layout (parser);
3850                         sc->add_output_def (od);
3851                         od->unprotect ();
3852                 }
3853                 $$ = scm_list_2 (Lily::score_markup, $4);
3854                 parser->lexer_->pop_state ();
3855         }
3856         | MARKUP_FUNCTION markup_command_basic_arguments {
3857                 $$ = scm_cons ($1, scm_reverse_x ($2, SCM_EOL));
3858         }
3859         | markup_scm MARKUP_IDENTIFIER
3860         {
3861                 $$ = $2;
3862         }
3863         ;
3864
3865 markup:
3866         markup_head_1_list simple_markup
3867         {
3868                 $$ = scm_car (MAKE_SYNTAX (composed_markup_list,
3869                                            @2, $1, scm_list_1 ($2)));
3870         }
3871         | simple_markup {
3872                 $$ = $1;
3873         }
3874         ;
3875
3876 %%
3877
3878 void
3879 Lily_parser::set_yydebug (bool x)
3880 {
3881         yydebug = x;
3882 }
3883
3884 SCM
3885 Lily_parser::do_yyparse ()
3886 {
3887         return scm_c_with_fluid (Lily::f_parser,
3888                                  self_scm (),
3889                                  do_yyparse_trampoline,
3890                                  static_cast <void *>(this));
3891 }
3892
3893 SCM
3894 Lily_parser::do_yyparse_trampoline (void *parser)
3895 {
3896         SCM retval = SCM_UNDEFINED;
3897         yyparse (static_cast <Lily_parser *>(parser), &retval);
3898         return retval;
3899 }
3900
3901
3902
3903 /*
3904
3905 It is a little strange to have this function in this file, but
3906 otherwise, we have to import music classes into the lexer.
3907
3908 */
3909 int
3910 Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
3911 {
3912         if (unsmob<Book> (sid)) {
3913                 Book *book =  unsmob<Book> (sid)->clone ();
3914                 *destination = book->self_scm ();
3915                 book->unprotect ();
3916
3917                 return BOOK_IDENTIFIER;
3918         } else if (scm_is_number (sid)) {
3919                 *destination = sid;
3920                 return NUMBER_IDENTIFIER;
3921         } else if (unsmob<Context_def> (sid))
3922         {
3923                 *destination = unsmob<Context_def> (sid)->clone ()->unprotect ();
3924                 return SCM_IDENTIFIER;
3925         } else if (unsmob<Context_mod> (sid)) {
3926                 *destination = unsmob<Context_mod> (sid)->smobbed_copy ();
3927                 return CONTEXT_MOD_IDENTIFIER;
3928         } else if (Music *mus = unsmob<Music> (sid)) {
3929                 mus = mus->clone ();
3930                 *destination = mus->self_scm ();
3931                 bool is_event = mus->is_mus_type ("post-event");
3932                 mus->unprotect ();
3933                 return is_event ? EVENT_IDENTIFIER : MUSIC_IDENTIFIER;
3934         } else if (unsmob<Pitch> (sid)) {
3935                 *destination = unsmob<Pitch> (sid)->smobbed_copy ();
3936                 return PITCH_IDENTIFIER;
3937         } else if (unsmob<Duration> (sid)) {
3938                 *destination = unsmob<Duration> (sid)->smobbed_copy ();
3939                 return DURATION_IDENTIFIER;
3940         } else if (unsmob<Output_def> (sid)) {
3941                 *destination = unsmob<Output_def> (sid)->clone ()->unprotect ();
3942                 return SCM_IDENTIFIER;
3943         } else if (unsmob<Score> (sid)) {
3944                 *destination = unsmob<Score> (sid)->clone ()->unprotect ();
3945                 return SCM_IDENTIFIER;
3946         }
3947
3948         return -1;
3949 }
3950
3951 SCM
3952 get_next_unique_context_id ()
3953 {
3954         return scm_from_ascii_string ("$uniqueContextId");
3955 }
3956
3957
3958 SCM
3959 get_next_unique_lyrics_context_id ()
3960 {
3961         static int new_context_count;
3962         char s[128];
3963         snprintf (s, sizeof (s)-1, "uniqueContext%d", new_context_count++);
3964         return scm_from_ascii_string (s);
3965 }
3966
3967 // check_scheme_arg checks one argument with a given predicate for use
3968 // in an argument list and throws a syntax error if it is unusable.
3969 // The argument is prepended to the argument list in any case.  After
3970 // throwing a syntax error, the argument list is terminated with #f as
3971 // its last cdr in order to mark it as uncallable while not losing
3972 // track of its total length.
3973 //
3974 // There are a few special considerations: if optional argument disp
3975 // is given (otherwise it defaults to SCM_UNDEFINED), it will be used
3976 // instead of arg in a prospective error message.  This is useful if
3977 // arg is not the actual argument but rather a transformation of it.
3978 //
3979 // If arg itself is SCM_UNDEFINED, the predicate is considered false
3980 // and an error message using disp is produced unconditionally.
3981
3982 SCM check_scheme_arg (Lily_parser *parser, Input loc,
3983                       SCM arg, SCM args, SCM pred, SCM disp)
3984 {
3985         if (SCM_UNBNDP (arg))
3986                 args = scm_cons (disp, args);
3987         else {
3988                 args = scm_cons (arg, args);
3989                 if (scm_is_true (scm_call_1 (pred, arg)))
3990                         return args;
3991         }
3992         scm_set_cdr_x (scm_last_pair (args), SCM_EOL);
3993         MAKE_SYNTAX (argument_error, loc, scm_length (args), pred,
3994                      SCM_UNBNDP (disp) ? arg : disp);
3995         scm_set_cdr_x (scm_last_pair (args), SCM_BOOL_F);
3996         return args;
3997 }
3998
3999 SCM loc_on_music (Lily_parser *parser, Input loc, SCM arg)
4000 {
4001         if (Music *m = unsmob<Music> (arg))
4002         {
4003                 m = m->clone ();
4004                 m->set_spot (parser->lexer_->override_input (loc));
4005                 return m->unprotect ();
4006         }
4007         return arg;
4008 }
4009
4010 SCM
4011 try_string_variants (SCM pred, SCM str)
4012 {
4013         // a matching predicate is always ok
4014         if (scm_is_true (scm_call_1 (pred, str)))
4015                 return str;
4016         // a symbol may be interpreted as a list of symbols if it helps
4017         if (scm_is_symbol (str)) {
4018                 str = scm_list_1 (str);
4019                 if (scm_is_true (scm_call_1 (pred, str)))
4020                         return str;
4021                 return SCM_UNDEFINED;
4022         }
4023
4024         // If this cannot be a string representation of a symbol list,
4025         // we are through.
4026
4027         if (!is_regular_identifier (str, true))
4028                 return SCM_UNDEFINED;
4029
4030         str = scm_string_split (str, SCM_MAKE_CHAR ('.'));
4031         for (SCM p = str; scm_is_pair (p); p = scm_cdr (p))
4032                 scm_set_car_x (p, scm_string_to_symbol (scm_car (p)));
4033
4034         // Let's attempt the symbol list interpretation first.
4035
4036         if (scm_is_true (scm_call_1 (pred, str)))
4037                 return str;
4038
4039         // If there is just one symbol in the list, we might interpret
4040         // it as a single symbol
4041
4042         if (scm_is_null (scm_cdr (str)))
4043         {
4044                 str = scm_car (str);
4045                 if (scm_is_true (scm_call_1 (pred, str)))
4046                         return str;
4047         }
4048
4049         return SCM_UNDEFINED;
4050 }
4051
4052 bool
4053 is_regular_identifier (SCM id, bool multiple)
4054 {
4055   if (!scm_is_string (id))
4056           return false;
4057
4058   string str = ly_scm2string (id);
4059
4060   bool middle = false;
4061
4062   for (string::iterator it=str.begin(); it != str.end (); it++)
4063   {
4064           int c = *it & 0xff;
4065           if ((c >= 'a' && c <= 'z')
4066               || (c >= 'A' && c <= 'Z')
4067               || c > 0x7f)
4068                   middle = true;
4069           else if (middle && (c == '-' || c == '_' || (multiple && c == '.')))
4070                   middle = false;
4071           else
4072                   return false;
4073   }
4074   return middle;
4075 }
4076
4077 SCM
4078 make_music_from_simple (Lily_parser *parser, Input loc, SCM simple)
4079 {
4080         if (unsmob<Music> (simple))
4081                 return simple;
4082         if (parser->lexer_->is_note_state ()) {
4083                 if (scm_is_symbol (simple)) {
4084                         Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
4085                         n->set_property ("duration", parser->default_duration_.smobbed_copy ());
4086                         n->set_property ("drum-type", simple);
4087                         return n->unprotect ();
4088                 }
4089                 if (unsmob<Pitch> (simple)) {
4090                         Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
4091                         n->set_property ("duration", parser->default_duration_.smobbed_copy ());
4092                         n->set_property ("pitch", simple);
4093                         return n->unprotect ();
4094                 }
4095                 return simple;
4096         } else if (parser->lexer_->is_lyric_state ()) {
4097                 if (Text_interface::is_markup (simple))
4098                         return MAKE_SYNTAX (lyric_event, loc, simple,
4099                                             parser->default_duration_.smobbed_copy ());
4100         } else if (parser->lexer_->is_chord_state ()) {
4101                 if (unsmob<Pitch> (simple))
4102                         return MAKE_SYNTAX
4103                                 (event_chord,
4104                                  loc,
4105                                  make_chord_elements (loc, simple,
4106                                                       parser->default_duration_.smobbed_copy (),
4107                                                       SCM_EOL));
4108         }
4109         return simple;
4110 }
4111
4112 Music *
4113 make_music_with_input (SCM name, Input where)
4114 {
4115        Music *m = make_music_by_name (name);
4116        m->set_spot (where);
4117        return m;
4118 }
4119
4120 SCM
4121 make_simple_markup (SCM a)
4122 {
4123         return a;
4124 }
4125
4126 SCM
4127 make_duration (SCM d, int dots)
4128 {
4129         int t = scm_to_int (d);
4130         if (t > 0 && (t & (t-1)) == 0)
4131                 return Duration (intlog2 (t), dots).smobbed_copy ();
4132         else
4133                 return SCM_UNDEFINED;
4134 }
4135
4136 SCM
4137 make_chord_step (SCM step_scm, Rational alter)
4138 {
4139         Pitch m (0, scm_to_int (step_scm) - 1, alter);
4140
4141         // Notename/octave are normalized
4142         if (m.get_notename () == 6)
4143                 m = m.transposed (Pitch (0, 0, FLAT_ALTERATION));
4144
4145         return m.smobbed_copy ();
4146 }
4147
4148
4149 SCM
4150 make_chord_elements (Input loc, SCM pitch, SCM dur, SCM modification_list)
4151 {
4152         SCM res = Lily::construct_chord_elements (pitch, dur, modification_list);
4153         for (SCM s = res; scm_is_pair (s); s = scm_cdr (s))
4154         {
4155                 unsmob<Music> (scm_car (s))->set_spot (loc);
4156         }
4157         return res;
4158 }
4159
4160 int
4161 yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser)
4162 {
4163         Lily_lexer *lex = parser->lexer_;
4164
4165         lex->lexval_ = s;
4166         lex->lexloc_ = loc;
4167         int tok = lex->pop_extra_token ();
4168         if (tok >= 0)
4169                 return tok;
4170         lex->prepare_for_next_token ();
4171         return lex->yylex ();
4172 }