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