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