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