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