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