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