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