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