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