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