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