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