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