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