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