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