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