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