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