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