]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.yy
parser.yy: remove unused function set_music_properties
[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--2012 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                 char *p = scm_to_locale_string                          \
45                         (scm_simple_format (SCM_BOOL_F,                 \
46                                             scm_from_locale_string ("~S"), \
47                                             scm_list_1 (value)));       \
48                 fputs (p, file);                                        \
49                 free (p);                                               \
50         } while (0)
51
52 %}
53
54 %parse-param {Lily_parser *parser}
55 %parse-param {SCM *retval}
56 %lex-param {Lily_parser *parser}
57 %error-verbose
58 %debug
59
60 /* We use SCMs to do strings, because it saves us the trouble of
61 deleting them.  Let's hope that a stack overflow doesn't trigger a move
62 of the parse stack onto the heap. */
63
64 %left PREC_BOT
65 %nonassoc REPEAT
66 %nonassoc ALTERNATIVE
67
68 /* The above precedences tackle the shift/reduce problem
69
70 1.  \repeat
71         \repeat .. \alternative
72
73     \repeat { \repeat .. \alternative }
74
75 or
76
77     \repeat { \repeat } \alternative
78 */
79
80 %nonassoc COMPOSITE
81 %left ADDLYRICS
82
83  /* ADDLYRICS needs to have lower precedence than argument scanning,
84   * or we won't be able to tell music apart from closed_music without
85   * lookahead in the context of function calls.
86   */
87
88 %nonassoc DEFAULT
89
90  /* \default is only applied after exhausting function arguments */
91
92 %nonassoc FUNCTION_ARGLIST
93
94  /* expressions with units are permitted into argument lists */
95
96 %right PITCH_IDENTIFIER NOTENAME_PITCH TONICNAME_PITCH
97       UNSIGNED REAL DURATION_IDENTIFIER ':'
98
99  /* The above are the symbols that can start optional function arguments
100     that are recognized in the grammar rather than by predicate
101  */
102
103 %nonassoc NUMBER_IDENTIFIER '/'
104
105  /* Number-unit expressions, where permitted, are concatenated into
106   * function arguments, just like fractions and tremoli.  Tremoli must
107   * not have higher precedence than UNSIGNED, or Lilypond will not
108   * join ':' with a following optional number.
109   */
110
111 %left PREC_TOP
112
113
114
115
116 %pure_parser
117 %locations
118
119
120
121 %{ // -*-Fundamental-*-
122
123 /*
124 FIXME:
125
126    * The rules for who is protecting what are very shady.  Uniformise
127      this.
128
129    * There are too many lexical modes?
130 */
131
132 #include "config.hh"
133
134 #include <cctype>
135 #include <cstdlib>
136 #include <cstdio>
137 using namespace std;
138
139 #include "book.hh"
140 #include "context-def.hh"
141 #include "context-mod.hh"
142 #include "dimensions.hh"
143 #include "file-path.hh"
144 #include "input.hh"
145 #include "international.hh"
146 #include "lily-guile.hh"
147 #include "lily-lexer.hh"
148 #include "lily-parser.hh"
149 #include "main.hh"
150 #include "misc.hh"
151 #include "music.hh"
152 #include "output-def.hh"
153 #include "paper-book.hh"
154 #include "scm-hash.hh"
155 #include "score.hh"
156 #include "text-interface.hh"
157 #include "warn.hh"
158
159 void
160 Lily_parser::parser_error (Input const *i, Lily_parser *parser, SCM *, string s)
161 {
162         parser->parser_error (*i, s);
163 }
164
165 #define MYBACKUP(Token, Value, Location)                                \
166 do                                                                      \
167         if (yychar == YYEMPTY)                                          \
168         {                                                               \
169                 if (Token)                                              \
170                         parser->lexer_->push_extra_token (Token, Value); \
171                 parser->lexer_->push_extra_token (BACKUP);              \
172         } else {                                                        \
173                 parser->parser_error                                    \
174                         (Location, _("Too much lookahead"));            \
175         }                                                               \
176 while (0)
177
178
179 #define MYREPARSE(Location, Pred, Token, Value)                         \
180 do                                                                      \
181         if (yychar == YYEMPTY)                                          \
182         {                                                               \
183                 parser->lexer_->push_extra_token (Token, Value);        \
184                 parser->lexer_->push_extra_token (REPARSE,              \
185                                                   Pred);                \
186         } else {                                                        \
187                 parser->parser_error                                    \
188                         (Location, _("Too much lookahead"));            \
189         }                                                               \
190 while (0)
191
192 %}
193
194
195 %{
196
197 #define MY_MAKE_MUSIC(x, spot)  make_music_with_input (ly_symbol2scm (x), spot)
198
199 /* ES TODO:
200 - Don't use lily module, create a new module instead.
201 - delay application of the function
202 */
203 #define LOWLEVEL_MAKE_SYNTAX(proc, args)        \
204   scm_apply_0 (proc, args)
205 /* Syntactic Sugar. */
206 #define MAKE_SYNTAX(name, location, ...)        \
207   LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant (name), scm_list_n (parser->self_scm (), make_input (location) , ##__VA_ARGS__, SCM_UNDEFINED))
208 #define START_MAKE_SYNTAX(name, ...)                                    \
209         scm_list_n (ly_lily_module_constant (name) , ##__VA_ARGS__, SCM_UNDEFINED)
210 #define FINISH_MAKE_SYNTAX(start, location, ...)                        \
211         LOWLEVEL_MAKE_SYNTAX (scm_car (start), scm_cons2 (parser->self_scm (), make_input (location), scm_append_x (scm_list_2 (scm_cdr (start), scm_list_n (__VA_ARGS__, SCM_UNDEFINED)))))
212
213 SCM get_next_unique_context_id ();
214 SCM get_next_unique_lyrics_context_id ();
215
216 #undef _
217 #if !HAVE_GETTEXT
218 #define _(x) x
219 #else
220 #include <libintl.h>
221 #define _(x) gettext (x)
222 #endif
223
224
225 static Music *make_music_with_input (SCM name, Input where);
226 SCM check_scheme_arg (Lily_parser *parser, Input loc,
227                       SCM arg, SCM args, SCM pred);
228 SCM loc_on_music (Input loc, SCM arg);
229 SCM make_chord_elements (Input loc, SCM pitch, SCM dur, SCM modification_list);
230 SCM make_chord_step (SCM step, Rational alter);
231 SCM make_simple_markup (SCM a);
232 bool is_duration (int t);
233 bool is_regular_identifier (SCM id);
234 int yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser);
235
236 %}
237
238 /* The third option is an alias that will be used to display the
239    syntax error.  Bison CVS now correctly handles backslash escapes.
240
241    FIXME: Bison needs to translate some of these, eg, STRING.
242
243 */
244
245 /* Keyword tokens with plain escaped name.  */
246 %token END_OF_FILE 0 "end of input"
247 %token ACCEPTS "\\accepts"
248 %token ADDLYRICS "\\addlyrics"
249 %token ALIAS "\\alias"
250 %token ALTERNATIVE "\\alternative"
251 %token BOOK "\\book"
252 %token BOOKPART "\\bookpart"
253 %token CHANGE "\\change"
254 %token CHORDMODE "\\chordmode"
255 %token CHORDS "\\chords"
256 %token CONSISTS "\\consists"
257 %token CONTEXT "\\context"
258 %token DEFAULT "\\default"
259 %token DEFAULTCHILD "\\defaultchild"
260 %token DENIES "\\denies"
261 %token DESCRIPTION "\\description"
262 %token DRUMMODE "\\drummode"
263 %token DRUMS "\\drums"
264 %token FIGUREMODE "\\figuremode"
265 %token FIGURES "\\figures"
266 %token HEADER "\\header"
267 %token INVALID "\\version-error"
268 %token LAYOUT "\\layout"
269 %token LYRICMODE "\\lyricmode"
270 %token LYRICS "\\lyrics"
271 %token LYRICSTO "\\lyricsto"
272 %token MARKUP "\\markup"
273 %token MARKUPLIST "\\markuplist"
274 %token MIDI "\\midi"
275 %token NAME "\\name"
276 %token NOTEMODE "\\notemode"
277 %token OVERRIDE "\\override"
278 %token PAPER "\\paper"
279 %token REMOVE "\\remove"
280 %token REPEAT "\\repeat"
281 %token REST "\\rest"
282 %token REVERT "\\revert"
283 %token SCORE "\\score"
284 %token SEQUENTIAL "\\sequential"
285 %token SET "\\set"
286 %token SIMULTANEOUS "\\simultaneous"
287 %token TEMPO "\\tempo"
288 %token TYPE "\\type"
289 %token UNSET "\\unset"
290 %token WITH "\\with"
291
292 /* Keyword token exceptions.  */
293 %token NEWCONTEXT "\\new"
294
295
296 /* Other string tokens.  */
297
298 %token CHORD_BASS "/+"
299 %token CHORD_CARET "^"
300 %token CHORD_COLON ":"
301 %token CHORD_MINUS "-"
302 %token CHORD_SLASH "/"
303 %token ANGLE_OPEN "<"
304 %token ANGLE_CLOSE ">"
305 %token DOUBLE_ANGLE_OPEN "<<"
306 %token DOUBLE_ANGLE_CLOSE ">>"
307 %token E_BACKSLASH "\\"
308 %token E_ANGLE_CLOSE "\\>"
309 %token E_CHAR "\\C[haracter]"
310 %token E_CLOSE "\\)"
311 %token E_EXCLAMATION "\\!"
312 %token E_BRACKET_OPEN "\\["
313 %token E_OPEN "\\("
314 %token E_BRACKET_CLOSE "\\]"
315 %token E_ANGLE_OPEN "\\<"
316 %token E_PLUS "\\+"
317 %token E_TILDE "\\~"
318 %token EXTENDER "__"
319
320 /*
321 If we give names, Bison complains.
322 */
323 %token FIGURE_CLOSE /* "\\>" */
324 %token FIGURE_OPEN /* "\\<" */
325 %token FIGURE_SPACE "_"
326 %token HYPHEN "--"
327
328 %token CHORDMODIFIERS
329 %token LYRIC_MARKUP
330 %token MULTI_MEASURE_REST
331
332
333 %token E_UNSIGNED
334 %token UNSIGNED
335
336 /* Artificial tokens, for more generic function syntax */
337 %token EXPECT_MARKUP "markup?"
338 %token EXPECT_PITCH "ly:pitch?"
339 %token EXPECT_DURATION "ly:duration?"
340 %token EXPECT_SCM "scheme?"
341 %token BACKUP "(backed-up?)"
342 %token REPARSE "(reparsed?)"
343 %token EXPECT_MARKUP_LIST "markup-list?"
344 %token EXPECT_OPTIONAL "optional?"
345 /* After the last argument. */
346 %token EXPECT_NO_MORE_ARGS;
347
348 /* An artificial token for parsing embedded Lilypond */
349 %token EMBEDDED_LILY "#{"
350
351 %token BOOK_IDENTIFIER
352 %token CHORDMODIFIER_PITCH
353 %token CHORD_MODIFIER
354 %token CHORD_REPETITION
355 %token CONTEXT_DEF_IDENTIFIER
356 %token CONTEXT_MOD_IDENTIFIER
357 %token DRUM_PITCH
358 %token PITCH_IDENTIFIER
359 %token DURATION_IDENTIFIER
360 %token EVENT_IDENTIFIER
361 %token EVENT_FUNCTION
362 %token FRACTION
363 %token LYRICS_STRING
364 %token LYRIC_ELEMENT
365 %token LYRIC_MARKUP_IDENTIFIER
366 %token MARKUP_FUNCTION
367 %token MARKUP_LIST_FUNCTION
368 %token MARKUP_IDENTIFIER
369 %token MARKUPLIST_IDENTIFIER
370 %token MUSIC_FUNCTION
371 %token MUSIC_IDENTIFIER
372 %token NOTENAME_PITCH
373 %token NUMBER_IDENTIFIER
374 %token OUTPUT_DEF_IDENTIFIER
375 %token REAL
376 %token RESTNAME
377 %token SCM_FUNCTION
378 %token SCM_IDENTIFIER
379 %token SCM_TOKEN
380 %token SCORE_IDENTIFIER
381 %token STRING
382 %token TONICNAME_PITCH
383
384 %left '-' '+'
385
386 /* We don't assign precedence to / and *, because we might need varied
387 prec levels in different prods */
388
389 %left UNARY_MINUS
390
391 %%
392
393 start_symbol:
394         lilypond
395         | EMBEDDED_LILY {
396                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
397                 parser->lexer_->push_note_state (nn);
398         } embedded_lilypond {
399                 parser->lexer_->pop_state ();
400                 *retval = $3;
401         }
402         ;
403
404 lilypond:       /* empty */ { $$ = SCM_UNSPECIFIED; }
405         | lilypond toplevel_expression {
406         }
407         | lilypond assignment {
408         }
409         | lilypond error {
410                 parser->error_level_ = 1;
411         }
412         | lilypond INVALID      {
413                 parser->error_level_ = 1;
414         }
415         ;
416
417
418 toplevel_expression:
419         {
420                 parser->lexer_->add_scope (get_header (parser));
421         } lilypond_header {
422                 parser->lexer_->set_identifier (ly_symbol2scm ("$defaultheader"), $2);
423         }
424         | book_block {
425                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-book-handler");
426                 scm_call_2 (proc, parser->self_scm (), $1);
427         }
428         | bookpart_block {
429                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-bookpart-handler");
430                 scm_call_2 (proc, parser->self_scm (), $1);
431         }
432         | score_block {
433                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-score-handler");
434                 scm_call_2 (proc, parser->self_scm (), $1);
435         }
436         | composite_music {
437                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-music-handler");
438                 scm_call_2 (proc, parser->self_scm (), $1);
439         }
440         | full_markup {
441                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
442                 scm_call_2 (proc, parser->self_scm (), scm_list_1 ($1));
443         }
444         | full_markup_list {
445                 SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
446                 scm_call_2 (proc, parser->self_scm (), $1);
447         }
448         | output_def {
449                 SCM id = SCM_EOL;
450                 Output_def * od = unsmob_output_def ($1);
451
452                 if (od->c_variable ("is-paper") == SCM_BOOL_T)
453                         id = ly_symbol2scm ("$defaultpaper");
454                 else if (od->c_variable ("is-midi") == SCM_BOOL_T)
455                         id = ly_symbol2scm ("$defaultmidi");
456                 else if (od->c_variable ("is-layout") == SCM_BOOL_T)
457                         id = ly_symbol2scm ("$defaultlayout");
458
459                 parser->lexer_->set_identifier (id, $1);
460         }
461         ;
462
463 embedded_scm_bare:
464         SCM_TOKEN
465         {
466                 $$ = parser->lexer_->eval_scm_token ($1);
467         }
468         | SCM_IDENTIFIER
469         ;
470
471 embedded_scm_bare_arg:
472         embedded_scm_bare
473         | STRING
474         | full_markup
475         | full_markup_list
476         | context_modification
477         | score_block
478         | context_def_spec_block
479         | book_block
480         | bookpart_block
481         | output_def
482         ;
483
484 /* The generic version may end in music, or not */
485
486 embedded_scm:
487         embedded_scm_bare
488         | scm_function_call
489         ;
490
491 embedded_scm_arg:
492         embedded_scm_bare_arg
493         | scm_function_call
494         | music_arg
495         ;
496
497 scm_function_call:
498         SCM_FUNCTION function_arglist {
499                 $$ = MAKE_SYNTAX ("music-function", @$,
500                                          $1, $2);
501         }
502         ;
503
504 embedded_lilypond:
505         /* empty */
506         {
507                 $$ = MAKE_SYNTAX ("void-music", @$);
508         }
509         | identifier_init
510         | music_embedded music_embedded music_list {
511                 $3 = scm_reverse_x ($3, SCM_EOL);
512                 if (unsmob_music ($2))
513                         $3 = scm_cons ($2, $3);
514                 if (unsmob_music ($1))
515                         $3 = scm_cons ($1, $3);
516                 $$ = MAKE_SYNTAX ("sequential-music", @$, $3);
517         }
518         | error {
519                 parser->error_level_ = 1;
520                 $$ = SCM_UNSPECIFIED;
521         }
522         | INVALID embedded_lilypond {
523                 parser->error_level_ = 1;
524                 $$ = $2;
525         }
526         ;
527
528
529 lilypond_header_body:
530         /* empty */ { $$ = SCM_UNSPECIFIED; }
531         | lilypond_header_body assignment  {
532
533         }
534         ;
535
536 lilypond_header:
537         HEADER '{' lilypond_header_body '}'     {
538                 $$ = parser->lexer_->remove_scope ();
539         }
540         ;
541
542 /*
543         DECLARATIONS
544 */
545 assignment_id:
546         STRING          { $$ = $1; }
547         | LYRICS_STRING { $$ = $1; }
548         ;
549
550 assignment:
551         assignment_id '=' identifier_init  {
552                 parser->lexer_->set_identifier ($1, $3);
553                 $$ = SCM_UNSPECIFIED;
554         }
555         | assignment_id property_path '=' identifier_init {
556                 SCM path = scm_cons (scm_string_to_symbol ($1), $2);
557                 parser->lexer_->set_identifier (path, $4);
558                 $$ = SCM_UNSPECIFIED;
559         }
560         | embedded_scm { $$ = SCM_UNSPECIFIED; }
561         ;
562
563
564 identifier_init:
565         score_block
566         | book_block
567         | bookpart_block
568         | output_def
569         | context_def_spec_block
570         | music_assign
571         | post_event_nofinger
572         | number_expression
573         | FRACTION
574         | string
575         | embedded_scm
576         | full_markup_list
577         | context_modification
578         ;
579
580 context_def_spec_block:
581         CONTEXT '{' context_def_spec_body '}'
582                 {
583                 $$ = $3;
584         }
585         ;
586
587 context_mod_arg:
588         embedded_scm
589         | composite_music
590         ;
591
592 context_mod_embedded:
593         context_mod_arg
594         {
595                 if (unsmob_music ($1)) {
596                         SCM proc = parser->lexer_->lookup_identifier ("context-mod-music-handler");
597                         $1 = scm_call_2 (proc, parser->self_scm (), $1);
598                 }
599                 if (unsmob_context_mod ($1))
600                         $$ = $1;
601                 else {
602                         parser->parser_error (@1, _ ("not a context mod"));
603                 }
604         }
605         ;
606
607
608 context_def_spec_body:
609         /**/ {
610                 $$ = Context_def::make_scm ();
611                 unsmob_context_def ($$)->origin ()->set_spot (@$);
612         }
613         | CONTEXT_DEF_IDENTIFIER {
614                 $$ = $1;
615                 unsmob_context_def ($$)->origin ()->set_spot (@$);
616         }
617         | context_def_spec_body context_mod {
618                 unsmob_context_def ($$)->add_context_mod ($2);
619         }
620         | context_def_spec_body context_modification {
621                 Context_def *td = unsmob_context_def ($$);
622                 SCM new_mods = unsmob_context_mod ($2)->get_mods ();
623                 for (SCM m = new_mods; scm_is_pair (m); m = scm_cdr (m)) {
624                     td->add_context_mod (scm_car (m));
625                 }
626         }
627         | context_def_spec_body context_mod_embedded {
628                 Context_def *td = unsmob_context_def ($$);
629                 SCM new_mods = unsmob_context_mod ($2)->get_mods ();
630                 for (SCM m = new_mods; scm_is_pair (m); m = scm_cdr (m)) {
631                     td->add_context_mod (scm_car (m));
632                 }
633         }
634         ;
635
636
637
638 book_block:
639         BOOK '{' book_body '}'  {
640                 $$ = $3;
641                 pop_paper (parser);
642                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-book"), SCM_BOOL_F);
643         }
644         ;
645
646 /* FIXME:
647    * Use 'handlers' like for toplevel-* stuff?
648    * grok \layout and \midi?  */
649 book_body:
650         {
651                 Book *book = new Book;
652                 init_papers (parser);
653                 book->origin ()->set_spot (@$);
654                 book->paper_ = dynamic_cast<Output_def*> (unsmob_output_def (parser->lexer_->lookup_identifier ("$defaultpaper"))->clone ());
655                 book->paper_->unprotect ();
656                 push_paper (parser, book->paper_);
657                 book->header_ = get_header (parser);
658                 $$ = book->unprotect ();
659                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-book"), $$);
660         }
661         | BOOK_IDENTIFIER {
662                 unsmob_book ($1)->origin ()->set_spot (@$);
663                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-book"), $1);
664         }
665         | book_body paper_block {
666                 unsmob_book ($1)->paper_ = unsmob_output_def ($2);
667                 set_paper (parser, unsmob_output_def ($2));
668         }
669         | book_body bookpart_block {
670                 SCM proc = parser->lexer_->lookup_identifier ("book-bookpart-handler");
671                 scm_call_2 (proc, $1, $2);
672         }
673         | book_body score_block {
674                 SCM proc = parser->lexer_->lookup_identifier ("book-score-handler");
675                 scm_call_2 (proc, $1, $2);
676         }
677         | book_body composite_music {
678                 SCM proc = parser->lexer_->lookup_identifier ("book-music-handler");
679                 scm_call_3 (proc, parser->self_scm (), $1, $2);
680         }
681         | book_body full_markup {
682                 SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
683                 scm_call_2 (proc, $1, scm_list_1 ($2));
684         }
685         | book_body full_markup_list {
686                 SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
687                 scm_call_2 (proc, $1, $2);
688         }
689         | book_body
690         {
691                 parser->lexer_->add_scope (unsmob_book ($1)->header_);
692         } lilypond_header
693         | book_body embedded_scm { }
694         | book_body error {
695                 Book *book = unsmob_book ($1);
696                 book->paper_ = 0;
697                 book->scores_ = SCM_EOL;
698                 book->bookparts_ = SCM_EOL;
699         }
700         ;
701
702 bookpart_block:
703         BOOKPART '{' bookpart_body '}' {
704                 $$ = $3;
705                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-bookpart"), SCM_BOOL_F);
706         }
707         ;
708
709 bookpart_body:
710         {
711                 Book *book = new Book;
712                 book->origin ()->set_spot (@$);
713                 $$ = book->unprotect ();
714                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-bookpart"), $$);
715         }
716         | BOOK_IDENTIFIER {
717                 unsmob_book ($1)->origin ()->set_spot (@$);
718                 parser->lexer_->set_identifier (ly_symbol2scm ("$current-bookpart"), $1);
719         }
720         | bookpart_body paper_block {
721                 unsmob_book ($$)->paper_ = unsmob_output_def ($2);
722         }
723         | bookpart_body score_block {
724                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-score-handler");
725                 scm_call_2 (proc, $1, $2);
726         }
727         | bookpart_body composite_music {
728                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-music-handler");
729                 scm_call_3 (proc, parser->self_scm (), $1, $2);
730         }
731         | bookpart_body full_markup {
732                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
733                 scm_call_2 (proc, $1, scm_list_1 ($2));
734         }
735         | bookpart_body full_markup_list {
736                 SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
737                 scm_call_2 (proc, $1, $2);
738         }
739         | bookpart_body
740         {
741                 Book *book = unsmob_book ($1);
742                 if (!ly_is_module (book->header_))
743                         book->header_ = ly_make_module (false);
744                 parser->lexer_->add_scope (book->header_);
745         } lilypond_header
746         | bookpart_body embedded_scm { }
747         | bookpart_body error {
748                 Book *book = unsmob_book ($1);
749                 book->paper_ = 0;
750                 book->scores_ = SCM_EOL;
751         }
752         ;
753
754 score_block:
755         SCORE '{' score_body '}'        {
756                 $$ = $3;
757         }
758         ;
759
760 score_body:
761         music {
762                 SCM scorify = ly_lily_module_constant ("scorify-music");
763                 $$ = scm_call_2 (scorify, $1, parser->self_scm ());
764
765                 unsmob_score ($$)->origin ()->set_spot (@$);
766         }
767         | SCORE_IDENTIFIER {
768                 unsmob_score ($$)->origin ()->set_spot (@$);
769         }
770         | score_body
771         {
772                 Score *score = unsmob_score ($1);
773                 if (!ly_is_module (score->get_header ()))
774                         score->set_header (ly_make_module (false));
775                 parser->lexer_->add_scope (score->get_header ());
776         } lilypond_header
777         | score_body output_def {
778                 Output_def *od = unsmob_output_def ($2);
779                 if (od->lookup_variable (ly_symbol2scm ("is-paper")) == SCM_BOOL_T)
780                 {
781                         parser->parser_error (@2, _("\\paper cannot be used in \\score, use \\layout instead"));
782
783                 }
784                 else
785                 {
786                         unsmob_score ($1)->add_output_def (od);
787                 }
788         }
789         | score_body error {
790                 unsmob_score ($$)->error_found_ = true;
791         }
792         ;
793
794
795 /*
796         OUTPUT DEF
797 */
798
799 paper_block:
800         output_def {
801                 Output_def *od = unsmob_output_def ($1);
802
803                 if (od->lookup_variable (ly_symbol2scm ("is-paper")) != SCM_BOOL_T)
804                 {
805                         parser->parser_error (@1, _ ("need \\paper for paper block"));
806                         $$ = get_paper (parser)->unprotect ();
807                 }
808         }
809         ;
810
811
812 output_def:
813         output_def_body '}' {
814                 $$ = $1;
815
816                 parser->lexer_->remove_scope ();
817                 parser->lexer_->pop_state ();
818         }
819         ;
820
821 output_def_head:
822         PAPER {
823                 Output_def *p = get_paper (parser);
824                 p->input_origin_ = @$;
825                 parser->lexer_->add_scope (p->scope_);
826                 $$ = p->unprotect ();
827         }
828         | MIDI    {
829                 Output_def *p = get_midi (parser);
830                 $$ = p->unprotect ();
831                 parser->lexer_->add_scope (p->scope_);
832         }
833         | LAYOUT        {
834                 Output_def *p = get_layout (parser);
835
836                 parser->lexer_->add_scope (p->scope_);
837                 $$ = p->unprotect ();
838         }
839         ;
840
841 output_def_head_with_mode_switch:
842         output_def_head {
843                 parser->lexer_->push_initial_state ();
844                 $$ = $1;
845         }
846         ;
847
848 // We need this weird nonterminal because both music as well as a
849 // context definition can start with \context and the difference is
850 // only apparent after looking at the next token.  If it is '{', there
851 // is still time to escape from notes mode.
852
853 music_or_context_def:
854         music_arg
855         {
856                 parser->lexer_->pop_state ();
857         }
858         | CONTEXT
859         {
860                 parser->lexer_->pop_state ();
861         } '{' context_def_spec_body '}'
862         {
863                 $$ = $4;
864         }
865         ;
866
867 output_def_body:
868         output_def_head_with_mode_switch '{' {
869                 $$ = $1;
870                 unsmob_output_def ($$)->input_origin_.set_spot (@$);
871         }
872         | output_def_head_with_mode_switch '{' OUTPUT_DEF_IDENTIFIER    {
873                 Output_def *o = unsmob_output_def ($3);
874                 o->input_origin_.set_spot (@$);
875                 $$ = o->self_scm ();
876                 parser->lexer_->remove_scope ();
877                 parser->lexer_->add_scope (o->scope_);
878         }
879         | output_def_body assignment  {
880
881         }
882         | output_def_body
883         {
884                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
885                 parser->lexer_->push_note_state (nn);
886         } music_or_context_def
887         {
888                 if (unsmob_context_def ($3))
889                         assign_context_def (unsmob_output_def ($1), $3);
890                 else {
891
892                         SCM proc = parser->lexer_->lookup_identifier
893                                      ("output-def-music-handler");
894                         scm_call_3 (proc, parser->self_scm (),
895                                     $1, $3);
896                 }
897         }
898         | output_def_body error {
899
900         }
901         ;
902
903 tempo_event:
904         TEMPO steno_duration '=' tempo_range    {
905                 $$ = MAKE_SYNTAX ("tempo", @$, SCM_EOL, $2, $4);
906         }
907         | TEMPO scalar_closed steno_duration '=' tempo_range    {
908                 $$ = MAKE_SYNTAX ("tempo", @$, $2, $3, $5);
909         }
910         | TEMPO scalar {
911                 $$ = MAKE_SYNTAX ("tempo", @$, $2);
912         }
913         ;
914
915 /*
916 The representation of a  list is reversed to have efficient append.  */
917
918 music_list:
919         /* empty */ {
920                 $$ = SCM_EOL;
921         }
922         | music_list music_embedded {
923                 if (unsmob_music ($2))
924                         $$ = scm_cons ($2, $1);
925         }
926         | music_list error {
927                 Music *m = MY_MAKE_MUSIC("Music", @$);
928                 // ugh. code dup
929                 m->set_property ("error-found", SCM_BOOL_T);
930                 $$ = scm_cons (m->self_scm (), $1);
931                 m->unprotect (); /* UGH */
932         }
933         ;
934
935 braced_music_list:
936         '{' music_list '}'
937         {
938                 $$ = scm_reverse_x ($2, SCM_EOL);
939         }
940         ;
941
942 music:  music_arg
943         | lyric_element_music
944         ;
945
946 music_embedded:
947         music
948         | embedded_scm
949         {
950                 if (unsmob_music ($1)
951                     || scm_is_eq ($1, SCM_UNSPECIFIED))
952                         $$ = $1;
953                 else
954                 {
955                         @$.warning (_ ("Ignoring non-music expression"));
956                         $$ = SCM_UNSPECIFIED;
957                 }
958         }
959         ;
960
961 music_arg:
962         simple_music
963         {
964                 if (unsmob_pitch ($1)) {
965                         Music *n = MY_MAKE_MUSIC ("NoteEvent", @1);
966                         n->set_property ("pitch", $1);
967                         n->set_property ("duration",
968                                          parser->default_duration_.smobbed_copy ());
969                         $$ = n->unprotect ();
970                 }
971         }
972         | composite_music %prec COMPOSITE
973         ;
974
975 music_assign:
976         simple_music
977         | composite_music %prec COMPOSITE
978         | lyric_element_music
979         ;
980
981 repeated_music:
982         REPEAT simple_string unsigned_number music
983         {
984                 $$ = MAKE_SYNTAX ("repeat", @$, $2, $3, $4, SCM_EOL);
985         }
986         | REPEAT simple_string unsigned_number music ALTERNATIVE braced_music_list
987         {
988                 $$ = MAKE_SYNTAX ("repeat", @$, $2, $3, $4, $6);
989         }
990         ;
991
992 sequential_music:
993         SEQUENTIAL braced_music_list {
994                 $$ = MAKE_SYNTAX ("sequential-music", @$, $2);
995         }
996         | braced_music_list {
997                 $$ = MAKE_SYNTAX ("sequential-music", @$, $1);
998         }
999         ;
1000
1001 simultaneous_music:
1002         SIMULTANEOUS braced_music_list {
1003                 $$ = MAKE_SYNTAX ("simultaneous-music", @$, $2);
1004         }
1005         | DOUBLE_ANGLE_OPEN music_list DOUBLE_ANGLE_CLOSE       {
1006                 $$ = MAKE_SYNTAX ("simultaneous-music", @$, scm_reverse_x ($2, SCM_EOL));
1007         }
1008         ;
1009
1010 simple_music:
1011         event_chord
1012         | music_property_def
1013         | context_change
1014         ;
1015
1016 context_modification:
1017         WITH { parser->lexer_->push_initial_state (); } '{' context_mod_list '}'
1018         {
1019                 parser->lexer_->pop_state ();
1020                 $$ = $4;
1021         }
1022         | WITH CONTEXT_MOD_IDENTIFIER
1023         {
1024                 $$ = $2;
1025         }
1026         | CONTEXT_MOD_IDENTIFIER
1027         {
1028                 $$ = $1;
1029         }
1030         | WITH embedded_scm_closed
1031         {
1032                 if (unsmob_context_mod ($2))
1033                         $$ = $2;
1034                 else {
1035                         parser->parser_error (@2, _ ("not a context mod"));
1036                         $$ = Context_mod ().smobbed_copy ();
1037                 }
1038         }
1039         ;
1040
1041 optional_context_mod:
1042         /**/ {
1043             $$ = SCM_EOL;
1044         }
1045         | context_modification
1046         {
1047               $$ = $1;
1048         }
1049         ;
1050
1051 context_mod_list:
1052         /**/ {
1053             $$ = Context_mod ().smobbed_copy ();
1054         }
1055         | context_mod_list context_mod  {
1056                  unsmob_context_mod ($1)->add_context_mod ($2);
1057         }
1058         | context_mod_list CONTEXT_MOD_IDENTIFIER {
1059                  Context_mod *md = unsmob_context_mod ($2);
1060                  if (md)
1061                      unsmob_context_mod ($1)->add_context_mods (md->get_mods ());
1062         }
1063         | context_mod_list context_mod_embedded {
1064                 unsmob_context_mod ($1)->add_context_mods
1065                         (unsmob_context_mod ($2)->get_mods ());
1066         }
1067         ;
1068
1069 composite_music:
1070         complex_music
1071         | music_bare
1072         ;
1073
1074 /* Music that can be parsed without lookahead */
1075 closed_music:
1076         music_bare
1077         | complex_music_prefix closed_music
1078         {
1079                 $$ = FINISH_MAKE_SYNTAX ($1, @$, $2);
1080         }
1081         | music_function_call_closed
1082         ;
1083
1084 music_bare:
1085         mode_changed_music
1086         | MUSIC_IDENTIFIER
1087         | grouped_music_list
1088         ;
1089
1090 grouped_music_list:
1091         simultaneous_music              { $$ = $1; }
1092         | sequential_music              { $$ = $1; }
1093         ;
1094
1095 /* An argument list. If a function \foo expects scm scm pitch, then the lexer expands \foo into the token sequence:
1096  MUSIC_FUNCTION EXPECT_PITCH EXPECT_SCM EXPECT_SCM EXPECT_NO_MORE_ARGS
1097 and this rule returns the reversed list of arguments. */
1098
1099 function_arglist_skip:
1100         function_arglist_common
1101         | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_skip
1102         {
1103                 $$ = scm_cons ($1, $3);
1104         } %prec FUNCTION_ARGLIST
1105         | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_skip
1106         {
1107                 $$ = scm_cons ($1, $3);
1108         } %prec FUNCTION_ARGLIST
1109         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip
1110         {
1111                 $$ = scm_cons ($1, $3);
1112         } %prec FUNCTION_ARGLIST
1113         ;
1114
1115
1116 function_arglist_nonbackup_common:
1117         EXPECT_OPTIONAL EXPECT_PITCH function_arglist pitch_also_in_chords {
1118                 $$ = scm_cons ($4, $3);
1119         }
1120         | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed duration_length {
1121                 $$ = scm_cons ($4, $3);
1122         }
1123         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed FRACTION
1124         {
1125                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1126         }
1127         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed post_event_nofinger
1128         {
1129                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1130         }
1131         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed '-' UNSIGNED
1132         {
1133                 SCM n = scm_difference ($5, SCM_UNDEFINED);
1134                 if (scm_is_true (scm_call_1 ($2, n)))
1135                         $$ = scm_cons (n, $3);
1136                 else {
1137                         Music *t = MY_MAKE_MUSIC ("FingeringEvent", @5);
1138                         t->set_property ("digit", $5);
1139                         $$ = t->unprotect ();
1140                         if (scm_is_true (scm_call_1 ($2, $$)))
1141                                 $$ = scm_cons ($$, $3);
1142                         else
1143                                 $$ = check_scheme_arg (parser, @4, n, $3, $2);
1144                 }
1145                 
1146         }
1147         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed '-' REAL
1148         {
1149                 $$ = check_scheme_arg (parser, @4,
1150                                        scm_difference ($5, SCM_UNDEFINED),
1151                                        $3, $2);
1152         }
1153         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed '-' NUMBER_IDENTIFIER
1154         {
1155                 $$ = check_scheme_arg (parser, @4,
1156                                        scm_difference ($5, SCM_UNDEFINED),
1157                                        $3, $2);
1158         }
1159         ;
1160
1161 function_arglist_closed_nonbackup:
1162         function_arglist_nonbackup_common
1163         | EXPECT_OPTIONAL EXPECT_SCM function_arglist embedded_scm_arg_closed
1164         {
1165                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1166         }
1167         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed bare_number_closed
1168         {
1169                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1170         }
1171         ;
1172
1173 function_arglist_nonbackup:
1174         function_arglist_nonbackup_common
1175         | EXPECT_OPTIONAL EXPECT_SCM function_arglist embedded_scm_arg
1176         {
1177                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1178         }
1179         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed bare_number
1180         {
1181                 $$ = check_scheme_arg (parser, @4, $4, $3, $2);
1182         }
1183         ;
1184
1185 function_arglist_keep:
1186         function_arglist_common
1187         | function_arglist_backup
1188         ;
1189
1190 function_arglist_closed_keep:
1191         function_arglist_closed_common
1192         | function_arglist_backup
1193         ;
1194
1195 function_arglist_backup:
1196         EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm_arg_closed
1197         {
1198                 if (scm_is_true (scm_call_1 ($2, $4)))
1199                 {
1200                         $$ = scm_cons ($4, $3);
1201                 } else {
1202                         $$ = scm_cons (loc_on_music (@3, $1), $3);
1203                         MYBACKUP (SCM_IDENTIFIER, $4, @4);
1204                 }
1205         }
1206         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep post_event_nofinger
1207         {
1208                 if (scm_is_true (scm_call_1 ($2, $4)))
1209                 {
1210                         $$ = scm_cons ($4, $3);
1211                 } else {
1212                         $$ = scm_cons (loc_on_music (@3, $1), $3);
1213                         MYBACKUP (EVENT_IDENTIFIER, $4, @4);
1214                 }
1215         }
1216         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep lyric_element
1217         {
1218                 // There is no point interpreting a lyrics string as
1219                 // an event, since we don't allow music possibly
1220                 // followed by durations or postevent into closed
1221                 // music, and we only accept closed music in optional
1222                 // arguments at the moment.  If this changes, more
1223                 // complex schemes might become interesting here as
1224                 // well: see how we do this at the mandatory argument
1225                 // point.
1226                 if (scm_is_true (scm_call_1 ($2, $4)))
1227                         $$ = scm_cons ($4, $3);
1228                 else {
1229                         $$ = scm_cons (loc_on_music (@3, $1), $3);
1230                         MYBACKUP (LYRICS_STRING, $4, @4);
1231                 }
1232         }
1233         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep UNSIGNED
1234         {
1235                 if (scm_is_true (scm_call_1 ($2, $4)))
1236                 {
1237                         $$ = $3;
1238                         MYREPARSE (@4, $2, UNSIGNED, $4);
1239                 } else {
1240                         $$ = scm_cons (loc_on_music (@3, $1), $3);
1241                         MYBACKUP (UNSIGNED, $4, @4);
1242                 }
1243         }
1244         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep REAL
1245         {
1246                 if (scm_is_true (scm_call_1 ($2, $4)))
1247                 {
1248                         $$ = $3;
1249                         MYREPARSE (@4, $2, REAL, $4);
1250                 } else {
1251                         $$ = scm_cons (loc_on_music (@3, $1), $3);
1252                         MYBACKUP (REAL, $4, @4);
1253                 }
1254         }
1255         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep NUMBER_IDENTIFIER
1256         {
1257                 if (scm_is_true (scm_call_1 ($2, $4)))
1258                 {
1259                         $$ = scm_cons ($4, $3);
1260                 } else {
1261                         $$ = scm_cons (loc_on_music (@3, $1), $3);
1262                         MYBACKUP (NUMBER_IDENTIFIER, $4, @4);
1263                 }
1264         }
1265         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep FRACTION
1266         {
1267                 if (scm_is_true (scm_call_1 ($2, $4)))
1268                 {
1269                         $$ = scm_cons ($4, $3);
1270                 } else {
1271                         $$ = scm_cons (loc_on_music (@3, $1), $3);
1272                         MYBACKUP (FRACTION, $4, @4);
1273                 }
1274         }
1275         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep '-' UNSIGNED
1276         {
1277                 SCM n = scm_difference ($5, SCM_UNDEFINED);
1278                 if (scm_is_true (scm_call_1 ($2, n))) {
1279                         $$ = $3;
1280                         MYREPARSE (@5, $2, REAL, n);
1281                 } else {
1282                         Music *t = MY_MAKE_MUSIC ("FingeringEvent", @5);
1283                         t->set_property ("digit", $5);
1284                         $$ = t->unprotect ();
1285                         if (scm_is_true (scm_call_1 ($2, $$)))
1286                                 $$ = scm_cons ($$, $3);
1287                         else {
1288                                 $$ = scm_cons (loc_on_music (@3, $1), $3);
1289                                 MYBACKUP (UNSIGNED, $5, @5);
1290                                 parser->lexer_->push_extra_token ('-');
1291                         }
1292                 }
1293                 
1294         }
1295         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep '-' REAL
1296         {
1297                 SCM n = scm_difference ($5, SCM_UNDEFINED);
1298                 if (scm_is_true (scm_call_1 ($2, n))) {
1299                         MYREPARSE (@5, $2, REAL, n);
1300                         $$ = $3;
1301                 } else {
1302                         MYBACKUP (REAL, n, @5);
1303                 }
1304         }
1305         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_keep '-' NUMBER_IDENTIFIER
1306         {
1307                 SCM n = scm_difference ($5, SCM_UNDEFINED);
1308                 if (scm_is_true (scm_call_1 ($2, n))) {
1309                         $$ = scm_cons (n, $3);
1310                 } else {
1311                         MYBACKUP (NUMBER_IDENTIFIER, n, @5);
1312                 }
1313         }
1314         | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_keep pitch_also_in_chords
1315         {
1316                 $$ = scm_cons ($4, $3);
1317         }
1318         | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_keep duration_length
1319         {
1320                 $$ = scm_cons ($4, $3);
1321         }
1322         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup BACKUP
1323         {
1324                 $$ = scm_cons ($1, $3);
1325                 MYBACKUP(0, SCM_UNDEFINED, @3);
1326         }
1327         | function_arglist_backup REPARSE embedded_scm_arg_closed
1328         {
1329                 $$ = check_scheme_arg (parser, @3,
1330                                        $3, $1, $2);
1331         }
1332         | function_arglist_backup REPARSE bare_number
1333         {
1334                 $$ = check_scheme_arg (parser, @3,
1335                                        $3, $1, $2);
1336         }
1337         ;
1338
1339 function_arglist:
1340         function_arglist_common
1341         | function_arglist_nonbackup
1342         ;
1343
1344 function_arglist_common:
1345         function_arglist_bare
1346         | EXPECT_SCM function_arglist_optional embedded_scm_arg
1347         {
1348                 $$ = check_scheme_arg (parser, @3,
1349                                        $3, $2, $1);
1350         }
1351         | EXPECT_SCM function_arglist_closed_optional bare_number
1352         {
1353                 $$ = check_scheme_arg (parser, @3,
1354                                        $3, $2, $1);
1355         }
1356         | EXPECT_SCM function_arglist_closed_optional FRACTION
1357         {
1358                 $$ = check_scheme_arg (parser, @3,
1359                                        $3, $2, $1);
1360         }
1361         | EXPECT_SCM function_arglist_closed_optional post_event_nofinger
1362         {
1363                 $$ = check_scheme_arg (parser, @3,
1364                                        $3, $2, $1);
1365         }
1366         | function_arglist_common_minus
1367         | function_arglist_common_lyric
1368         ;
1369
1370 function_arglist_common_lyric:
1371         EXPECT_SCM function_arglist_optional lyric_element
1372         {
1373                 // We check how the predicate thinks about a lyrics
1374                 // event or about a markup.  If it accepts neither, we
1375                 // backup the original token.  Otherwise we commit to
1376                 // taking the token.  Depending on what the predicate
1377                 // is willing to accept, we interpret as a string, as
1378                 // a lyric event, or ambiguously (meaning that if
1379                 // something looking like a duration or post event
1380                 // follows, we take the event, otherwise the string).
1381                 SCM lyric_event = MAKE_SYNTAX ("lyric-event", @3, $3,
1382                                                parser->default_duration_.smobbed_copy ());
1383                 if (scm_is_true (scm_call_1 ($1, $3)))
1384                         if (scm_is_true (scm_call_1 ($1, lyric_event)))
1385                         {
1386                                 $$ = $2;
1387                                 MYREPARSE (@3, $1, LYRICS_STRING, $3);
1388                         } else {
1389                                 $$ = scm_cons ($3, $2);
1390                         }
1391                 else if (scm_is_true (scm_call_1 ($1, lyric_event)))
1392                 {
1393                         $$ = $2;
1394                         MYREPARSE (@3, $1, LYRIC_ELEMENT, $3);
1395                 } else {
1396                         // This is going to flag a syntax error, we
1397                         // know the predicate to be false.
1398                         check_scheme_arg (parser, @3,
1399                                           $3, $2, $1);
1400                 }
1401         }
1402         | function_arglist_common_lyric REPARSE lyric_element_arg
1403         {
1404                 // This should never be false
1405                 $$ = check_scheme_arg (parser, @3,
1406                                        $3, $1, $2);
1407         }
1408         ;
1409
1410 function_arglist_common_minus:
1411         EXPECT_SCM function_arglist_closed_optional '-' UNSIGNED
1412         {
1413                 SCM n = scm_difference ($4, SCM_UNDEFINED);
1414                 if (scm_is_true (scm_call_1 ($1, n))) {
1415                         $$ = $2;
1416                         MYREPARSE (@4, $1, REAL, n);
1417                 } else {
1418                         Music *t = MY_MAKE_MUSIC ("FingeringEvent", @4);
1419                         t->set_property ("digit", $4);
1420                         $$ = t->unprotect ();
1421                         if (scm_is_true (scm_call_1 ($1, $$)))
1422                                 $$ = scm_cons ($$, $2);
1423                         else
1424                                 $$ = check_scheme_arg (parser, @3, n, $2, $1);
1425                 }
1426                 
1427         }
1428         | EXPECT_SCM function_arglist_closed_optional '-' REAL
1429         {
1430                 $$ = $2;
1431                 SCM n = scm_difference ($4, SCM_UNDEFINED);
1432                 MYREPARSE (@4, $1, REAL, n);
1433         }
1434         | EXPECT_SCM function_arglist_closed_optional '-' NUMBER_IDENTIFIER
1435         {
1436                 SCM n = scm_difference ($4, SCM_UNDEFINED);
1437                 $$ = check_scheme_arg (parser, @4, n, $2, $1);
1438         }
1439         | function_arglist_common_minus REPARSE bare_number
1440         {
1441                 $$ = check_scheme_arg (parser, @3, $3, $1, $2);
1442         }
1443         ;
1444
1445 function_arglist_closed:
1446         function_arglist_closed_common
1447         | function_arglist_closed_nonbackup
1448         ;
1449
1450 function_arglist_closed_common:
1451         function_arglist_bare
1452         | EXPECT_SCM function_arglist_optional embedded_scm_arg_closed
1453         {
1454                 $$ = check_scheme_arg (parser, @3,
1455                                        $3, $2, $1);
1456         }
1457         | EXPECT_SCM function_arglist_closed_optional bare_number
1458         {
1459                 $$ = check_scheme_arg (parser, @3,
1460                                        $3, $2, $1);
1461         }
1462         | EXPECT_SCM function_arglist_closed_optional '-' UNSIGNED
1463         {
1464                 SCM n = scm_difference ($4, SCM_UNDEFINED);
1465                 if (scm_is_true (scm_call_1 ($1, n))) {
1466                         $$ = scm_cons (n, $2);
1467                 } else {
1468                         Music *t = MY_MAKE_MUSIC ("FingeringEvent", @4);
1469                         t->set_property ("digit", $4);
1470                         $$ = t->unprotect ();
1471                         if (scm_is_true (scm_call_1 ($1, $$)))
1472                                 $$ = scm_cons ($$, $2);
1473                         else
1474                                 $$ = check_scheme_arg (parser, @3, n, $2, $1);
1475                 }
1476                 
1477         }
1478         | EXPECT_SCM function_arglist_closed_optional '-' REAL
1479         {
1480                 $$ = check_scheme_arg (parser, @3,
1481                                        scm_difference ($4, SCM_UNDEFINED),
1482                                        $2, $1);
1483         }
1484         | EXPECT_SCM function_arglist_closed_optional '-' NUMBER_IDENTIFIER
1485         {
1486                 $$ = check_scheme_arg (parser, @3,
1487                                        scm_difference ($4, SCM_UNDEFINED),
1488                                        $2, $1);
1489         }
1490         | EXPECT_SCM function_arglist_closed_optional post_event_nofinger
1491         {
1492                 $$ = check_scheme_arg (parser, @3,
1493                                        $3, $2, $1);
1494         }
1495         | EXPECT_SCM function_arglist_closed_optional FRACTION
1496         {
1497                 $$ = check_scheme_arg (parser, @3,
1498                                        $3, $2, $1);
1499         }
1500         | EXPECT_SCM function_arglist_optional lyric_element
1501         {
1502                 $$ = check_scheme_arg (parser, @3,
1503                                        $3, $2, $1);
1504         }
1505         ;
1506
1507 function_arglist_optional:
1508         function_arglist_keep %prec FUNCTION_ARGLIST
1509         | function_arglist_backup BACKUP
1510         | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_optional
1511         {
1512                 $$ = scm_cons ($1, $3);
1513         }
1514         | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_optional
1515         {
1516                 $$ = scm_cons ($1, $3);
1517         }
1518         ;
1519
1520 function_arglist_closed_optional:
1521         function_arglist_closed_keep %prec FUNCTION_ARGLIST
1522         | function_arglist_backup BACKUP
1523         | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_closed_optional
1524         {
1525                 $$ = scm_cons ($1, $3);
1526         }
1527         | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_optional
1528         {
1529                 $$ = scm_cons ($1, $3);
1530         }
1531         ;
1532
1533 embedded_scm_closed:
1534         embedded_scm_bare
1535         | scm_function_call_closed
1536         ;
1537
1538 embedded_scm_arg_closed:
1539         embedded_scm_bare_arg
1540         | scm_function_call_closed
1541         | closed_music
1542         ;
1543
1544 scm_function_call_closed:
1545         SCM_FUNCTION function_arglist_closed {
1546                 $$ = MAKE_SYNTAX ("music-function", @$,
1547                                          $1, $2);
1548         } %prec FUNCTION_ARGLIST
1549         ;
1550
1551 function_arglist_bare:
1552         EXPECT_NO_MORE_ARGS {
1553                 $$ = SCM_EOL;
1554         }
1555         | EXPECT_PITCH function_arglist_optional pitch_also_in_chords {
1556                 $$ = scm_cons ($3, $2);
1557         }
1558         | EXPECT_DURATION function_arglist_closed_optional duration_length {
1559                 $$ = scm_cons ($3, $2);
1560         }
1561         | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_skip DEFAULT {
1562                 $$ = scm_cons ($1, $3);
1563         }
1564         | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_skip DEFAULT {
1565                 $$ = scm_cons ($1, $3);
1566         }
1567         | EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip DEFAULT {
1568                 $$ = scm_cons ($1, $3);
1569         }
1570         ;
1571
1572 music_function_call:
1573         MUSIC_FUNCTION function_arglist {
1574                 $$ = MAKE_SYNTAX ("music-function", @$,
1575                                          $1, $2);
1576         }
1577         ;
1578
1579
1580 optional_id:
1581         /**/ { $$ = SCM_EOL; }
1582         | '=' simple_string {
1583                 $$ = $2;
1584         }
1585         ;
1586
1587 complex_music:
1588         music_function_call
1589         | repeated_music                { $$ = $1; }
1590         | re_rhythmed_music     { $$ = $1; }
1591         | complex_music_prefix music
1592         {
1593                 $$ = FINISH_MAKE_SYNTAX ($1, @$, $2);
1594         }
1595         ;
1596
1597 complex_music_prefix:
1598         CONTEXT simple_string optional_id optional_context_mod {
1599                 Context_mod *ctxmod = unsmob_context_mod ($4);
1600                 SCM mods = SCM_EOL;
1601                 if (ctxmod)
1602                         mods = ctxmod->get_mods ();
1603                 $$ = START_MAKE_SYNTAX ("context-specification", $2, $3, mods, SCM_BOOL_F);
1604         }
1605         | NEWCONTEXT simple_string optional_id optional_context_mod {
1606                 Context_mod *ctxmod = unsmob_context_mod ($4);
1607                 SCM mods = SCM_EOL;
1608                 if (ctxmod)
1609                         mods = ctxmod->get_mods ();
1610                 $$ = START_MAKE_SYNTAX ("context-specification", $2, $3, mods, SCM_BOOL_T);
1611         }
1612         ;
1613
1614 mode_changed_music:
1615         mode_changing_head grouped_music_list {
1616                 if ($1 == ly_symbol2scm ("chords"))
1617                 {
1618                   $$ = MAKE_SYNTAX ("unrelativable-music", @$, $2);
1619                 }
1620                 else
1621                 {
1622                   $$ = $2;
1623                 }
1624                 parser->lexer_->pop_state ();
1625         }
1626         | mode_changing_head_with_context optional_context_mod grouped_music_list {
1627                 Context_mod *ctxmod = unsmob_context_mod ($2);
1628                 SCM mods = SCM_EOL;
1629                 if (ctxmod)
1630                         mods = ctxmod->get_mods ();
1631                 $$ = MAKE_SYNTAX ("context-specification", @$, $1, SCM_EOL, mods, SCM_BOOL_T, $3);
1632                 if ($1 == ly_symbol2scm ("ChordNames"))
1633                 {
1634                   $$ = MAKE_SYNTAX ("unrelativable-music", @$, $$);
1635                 }
1636                 parser->lexer_->pop_state ();
1637         }
1638         ;
1639
1640 mode_changing_head:
1641         NOTEMODE {
1642                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
1643                 parser->lexer_->push_note_state (nn);
1644
1645                 $$ = ly_symbol2scm ("notes");
1646         }
1647         | DRUMMODE
1648                 {
1649                 SCM nn = parser->lexer_->lookup_identifier ("drumPitchNames");
1650                 parser->lexer_->push_note_state (nn);
1651
1652                 $$ = ly_symbol2scm ("drums");
1653         }
1654         | FIGUREMODE {
1655                 parser->lexer_->push_figuredbass_state ();
1656
1657                 $$ = ly_symbol2scm ("figures");
1658         }
1659         | CHORDMODE {
1660                 SCM nn = parser->lexer_->lookup_identifier ("chordmodifiers");
1661                 parser->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
1662                 nn = parser->lexer_->lookup_identifier ("pitchnames");
1663                 parser->lexer_->push_chord_state (nn);
1664                 $$ = ly_symbol2scm ("chords");
1665
1666         }
1667         | LYRICMODE
1668                 { parser->lexer_->push_lyric_state ();
1669                 $$ = ly_symbol2scm ("lyrics");
1670         }
1671         ;
1672
1673 mode_changing_head_with_context:
1674         DRUMS {
1675                 SCM nn = parser->lexer_->lookup_identifier ("drumPitchNames");
1676                 parser->lexer_->push_note_state (nn);
1677
1678                 $$ = ly_symbol2scm ("DrumStaff");
1679         }
1680         | FIGURES {
1681                 parser->lexer_->push_figuredbass_state ();
1682
1683                 $$ = ly_symbol2scm ("FiguredBass");
1684         }
1685         | CHORDS {
1686                 SCM nn = parser->lexer_->lookup_identifier ("chordmodifiers");
1687                 parser->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
1688                 nn = parser->lexer_->lookup_identifier ("pitchnames");
1689                 parser->lexer_->push_chord_state (nn);
1690                 $$ = ly_symbol2scm ("ChordNames");
1691         }
1692         | LYRICS
1693                 { parser->lexer_->push_lyric_state ();
1694                 $$ = ly_symbol2scm ("Lyrics");
1695         }
1696         ;
1697
1698 new_lyrics:
1699         ADDLYRICS { parser->lexer_->push_lyric_state (); }
1700         /*cont */
1701         composite_music {
1702         /* Can also use music at the expensive of two S/Rs similar to
1703            \repeat \alternative */
1704                 parser->lexer_->pop_state ();
1705
1706                 $$ = scm_cons ($3, SCM_EOL);
1707         }
1708         | new_lyrics ADDLYRICS {
1709                 parser->lexer_->push_lyric_state ();
1710         } composite_music {
1711                 parser->lexer_->pop_state ();
1712                 $$ = scm_cons ($4, $1);
1713         }
1714         ;
1715
1716 re_rhythmed_music:
1717         composite_music new_lyrics {
1718                 $$ = MAKE_SYNTAX ("add-lyrics", @$, $1, scm_reverse_x ($2, SCM_EOL));
1719         } %prec COMPOSITE
1720         | LYRICSTO simple_string {
1721                 parser->lexer_->push_lyric_state ();
1722         } music {
1723                 parser->lexer_->pop_state ();
1724                 $$ = MAKE_SYNTAX ("lyric-combine", @$, $2, $4);
1725         }
1726         ;
1727
1728 context_change:
1729         CHANGE STRING '=' STRING  {
1730                 $$ = MAKE_SYNTAX ("context-change", @$, scm_string_to_symbol ($2), $4);
1731         }
1732         ;
1733
1734
1735 property_path_revved:
1736         embedded_scm_closed {
1737                 $$ = scm_cons ($1, SCM_EOL);
1738         }
1739         | property_path_revved embedded_scm_closed {
1740                 $$ = scm_cons ($2, $1);
1741         }
1742         ;
1743
1744 property_path:
1745         property_path_revved  {
1746                 $$ = scm_reverse_x ($1, SCM_EOL);
1747         }
1748         ;
1749
1750 property_operation:
1751         STRING '=' scalar {
1752                 $$ = scm_list_3 (ly_symbol2scm ("assign"),
1753                         scm_string_to_symbol ($1), $3);
1754         }
1755         | UNSET simple_string {
1756                 $$ = scm_list_2 (ly_symbol2scm ("unset"),
1757                         scm_string_to_symbol ($2));
1758         }
1759         | OVERRIDE simple_string property_path '=' scalar {
1760                 $$ = scm_append (scm_list_2 (scm_list_3 (ly_symbol2scm ("push"),
1761                                                         scm_string_to_symbol ($2), $5),
1762                                              $3));
1763         }
1764         | REVERT simple_string embedded_scm {
1765                 $$ = scm_list_3 (ly_symbol2scm ("pop"),
1766                         scm_string_to_symbol ($2), $3);
1767         }
1768         ;
1769
1770 context_def_mod:
1771         CONSISTS { $$ = ly_symbol2scm ("consists"); }
1772         | REMOVE { $$ = ly_symbol2scm ("remove"); }
1773
1774         | ACCEPTS { $$ = ly_symbol2scm ("accepts"); }
1775         | DEFAULTCHILD { $$ = ly_symbol2scm ("default-child"); }
1776         | DENIES { $$ = ly_symbol2scm ("denies"); }
1777
1778         | ALIAS { $$ = ly_symbol2scm ("alias"); }
1779         | TYPE { $$ = ly_symbol2scm ("translator-type"); }
1780         | DESCRIPTION { $$ = ly_symbol2scm ("description"); }
1781         | NAME { $$ = ly_symbol2scm ("context-name"); }
1782         ;
1783
1784 context_mod:
1785         property_operation { $$ = $1; }
1786         | context_def_mod STRING {
1787                 $$ = scm_list_2 ($1, $2);
1788         }
1789         | context_def_mod embedded_scm
1790         {
1791                 if (!scm_is_string ($2)
1792                     && ly_symbol2scm ("consists") != $1
1793                     && ly_symbol2scm ("remove") != $1)
1794                 {
1795                         $$ = SCM_EOL;
1796                         parser->parser_error (@1, _ ("only \\consists and \\remove take non-string argument."));
1797                 }
1798                 else
1799                 {
1800                         $$ = scm_list_2 ($1, $2);
1801                 }
1802         }
1803         ;
1804
1805 context_prop_spec:
1806         simple_string {
1807                 if (!is_regular_identifier ($1))
1808                 {
1809                         @$.error (_("Grob name should be alphanumeric"));
1810                 }
1811
1812                 $$ = scm_list_2 (ly_symbol2scm ("Bottom"),
1813                         scm_string_to_symbol ($1));
1814         }
1815         | simple_string '.' simple_string {
1816                 $$ = scm_list_2 (scm_string_to_symbol ($1),
1817                         scm_string_to_symbol ($3));
1818         }
1819         ;
1820
1821 simple_music_property_def:
1822         OVERRIDE context_prop_spec property_path '=' scalar {
1823                 $$ = scm_append (scm_list_2 (scm_list_n (scm_car ($2),
1824                                 ly_symbol2scm ("OverrideProperty"),
1825                                 scm_cadr ($2),
1826                                 $5, SCM_UNDEFINED),
1827                                 $3));
1828         }
1829         | REVERT context_prop_spec embedded_scm {
1830                 $$ = scm_list_4 (scm_car ($2),
1831                         ly_symbol2scm ("RevertProperty"),
1832                         scm_cadr ($2),
1833                         $3);
1834         }
1835         | SET context_prop_spec '=' scalar {
1836                 $$ = scm_list_4 (scm_car ($2),
1837                         ly_symbol2scm ("PropertySet"),
1838                         scm_cadr ($2),
1839                         $4);
1840         }
1841         | UNSET context_prop_spec {
1842                 $$ = scm_list_3 (scm_car ($2),
1843                         ly_symbol2scm ("PropertyUnset"),
1844                         scm_cadr ($2));
1845         }
1846         ;
1847
1848 music_property_def:
1849         simple_music_property_def {
1850                 $$ = LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant ("property-operation"), scm_cons2 (parser->self_scm (), make_input (@$), $1));
1851         }
1852         ;
1853
1854 string:
1855         STRING {
1856                 $$ = $1;
1857         }
1858         | full_markup
1859         | string '+' string {
1860                 if (!scm_is_string ($1)) {
1861                         parser->parser_error (@1, (_ ("simple string expected")));
1862                         $1 = scm_string (SCM_EOL);
1863                 }
1864                 if (!scm_is_string ($3)) {
1865                         parser->parser_error (@3, (_ ("simple string expected")));
1866                         $3 = scm_string (SCM_EOL);
1867                 }
1868                 $$ = scm_string_append (scm_list_2 ($1, $3));
1869         }
1870         ;
1871
1872 simple_string: STRING {
1873                 $$ = $1;
1874         }
1875         | LYRICS_STRING {
1876                 $$ = $1;
1877         }
1878         | MARKUP_IDENTIFIER
1879         {
1880                 if (scm_is_string ($1)) {
1881                         $$ = $1;
1882                 } else {
1883                         parser->parser_error (@1, (_ ("simple string expected")));
1884                         $$ = scm_string (SCM_EOL);
1885                 }
1886         }
1887         | LYRIC_MARKUP_IDENTIFIER
1888         {
1889                 if (scm_is_string ($1)) {
1890                         $$ = $1;
1891                 } else {
1892                         parser->parser_error (@1, (_ ("simple string expected")));
1893                         $$ = scm_string (SCM_EOL);
1894                 }
1895         }
1896         ;
1897
1898 scalar:
1899         embedded_scm_arg
1900         | bare_number
1901         | FRACTION
1902         | lyric_element
1903         ;
1904
1905 scalar_closed:
1906         embedded_scm_arg_closed
1907         | bare_number
1908         | FRACTION
1909         | lyric_element
1910         ;
1911
1912
1913 event_chord:
1914         simple_element post_events {
1915                 // Let the rhythmic music iterator sort this mess out.
1916                 if (scm_is_pair ($2)) {
1917                         if (unsmob_pitch ($1)) {
1918                                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @1);
1919                                 n->set_property ("pitch", $1);
1920                                 n->set_property ("duration",
1921                                                  parser->default_duration_.smobbed_copy ());
1922                                 $$ = n->unprotect ();
1923                         }
1924                         unsmob_music ($$)->set_property ("articulations",
1925                                                          scm_reverse_x ($2, SCM_EOL));
1926                 }
1927         }
1928         | simple_chord_elements post_events     {
1929                 SCM elts = ly_append2 ($1, scm_reverse_x ($2, SCM_EOL));
1930
1931                 Input i;
1932                 /* why is this giving wrong start location? -ns
1933                  * i = @$; */
1934                 i.set_location (@1, @2);
1935                 $$ = MAKE_SYNTAX ("event-chord", i, elts);
1936         }
1937         | CHORD_REPETITION optional_notemode_duration post_events {
1938                 Input i;
1939                 i.set_location (@1, @3);
1940                 $$ = MAKE_SYNTAX ("repetition-chord", i,
1941                                   $2, scm_reverse_x ($3, SCM_EOL));
1942         }
1943         | MULTI_MEASURE_REST optional_notemode_duration post_events {
1944                 Input i;
1945                 i.set_location (@1, @3);
1946                 $$ = MAKE_SYNTAX ("multi-measure-rest", i, $2,
1947                                   scm_reverse_x ($3, SCM_EOL));
1948         }
1949         | command_element
1950         | note_chord_element
1951         ;
1952
1953
1954 note_chord_element:
1955         chord_body optional_notemode_duration post_events
1956         {
1957                 Music *m = unsmob_music ($1);
1958                 SCM dur = unsmob_duration ($2)->smobbed_copy ();
1959                 SCM es = m->get_property ("elements");
1960                 SCM postevs = scm_reverse_x ($3, SCM_EOL);
1961
1962                 for (SCM s = es; scm_is_pair (s); s = scm_cdr (s))
1963                   unsmob_music (scm_car (s))->set_property ("duration", dur);
1964                 es = ly_append2 (es, postevs);
1965
1966                 m-> set_property ("elements", es);
1967                 m->set_spot (@$);
1968                 $$ = m->self_scm ();
1969         }
1970         ;
1971
1972 chord_body:
1973         ANGLE_OPEN chord_body_elements ANGLE_CLOSE
1974         {
1975                 $$ = MAKE_SYNTAX ("event-chord", @$, scm_reverse_x ($2, SCM_EOL));
1976         }
1977         ;
1978
1979 chord_body_elements:
1980         /* empty */             { $$ = SCM_EOL; }
1981         | chord_body_elements chord_body_element {
1982                 if (!SCM_UNBNDP ($2))
1983                         $$ = scm_cons ($2, $1);
1984         }
1985         ;
1986
1987 chord_body_element:
1988         pitch exclamations questions octave_check post_events
1989         {
1990                 bool q = to_boolean ($3);
1991                 bool ex = to_boolean ($2);
1992                 SCM check = $4;
1993                 SCM post = $5;
1994
1995                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
1996                 n->set_property ("pitch", $1);
1997                 if (q)
1998                         n->set_property ("cautionary", SCM_BOOL_T);
1999                 if (ex || q)
2000                         n->set_property ("force-accidental", SCM_BOOL_T);
2001
2002                 if (scm_is_pair (post)) {
2003                         SCM arts = scm_reverse_x (post, SCM_EOL);
2004                         n->set_property ("articulations", arts);
2005                 }
2006                 if (scm_is_number (check))
2007                 {
2008                         int q = scm_to_int (check);
2009                         n->set_property ("absolute-octave", scm_from_int (q-1));
2010                 }
2011
2012                 $$ = n->unprotect ();
2013         }
2014         | DRUM_PITCH post_events {
2015                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
2016                 n->set_property ("drum-type", $1);
2017
2018                 if (scm_is_pair ($2)) {
2019                         SCM arts = scm_reverse_x ($2, SCM_EOL);
2020                         n->set_property ("articulations", arts);
2021                 }
2022                 $$ = n->unprotect ();
2023         }
2024         | music_function_chord_body
2025         {
2026                 Music *m = unsmob_music ($1);
2027
2028                 while (m && m->is_mus_type ("music-wrapper-music")) {
2029                         $$ = m->get_property ("element");
2030                         m = unsmob_music ($$);
2031                 }
2032
2033                 if (!(m && m->is_mus_type ("rhythmic-event"))) {
2034                         parser->parser_error (@$, _ ("not a rhythmic event"));
2035                         $$ = SCM_UNDEFINED;
2036                 }
2037         }
2038         ;
2039
2040 music_function_chord_body:
2041         music_function_call
2042         | MUSIC_IDENTIFIER
2043         ;
2044
2045 // Event functions may only take closed arglists, otherwise it would
2046 // not be clear whether a following postevent should be associated
2047 // with the last argument of the event function or with the expression
2048 // for which the function call acts itself as event.
2049
2050 music_function_call_closed:
2051         MUSIC_FUNCTION function_arglist_closed {
2052                 $$ = MAKE_SYNTAX ("music-function", @$,
2053                                          $1, $2);
2054         }
2055         ;
2056
2057 event_function_event:
2058         EVENT_FUNCTION function_arglist_closed {
2059                 $$ = MAKE_SYNTAX ("music-function", @$,
2060                                          $1, $2);
2061         }
2062         ;
2063
2064 command_element:
2065         command_event {
2066                 $$ = $1;
2067         }
2068         | E_BRACKET_OPEN {
2069                 Music *m = MY_MAKE_MUSIC ("LigatureEvent", @$);
2070                 m->set_property ("span-direction", scm_from_int (START));
2071                 $$ = m->unprotect();
2072         }
2073         | E_BRACKET_CLOSE {
2074                 Music *m = MY_MAKE_MUSIC ("LigatureEvent", @$);
2075                 m->set_property ("span-direction", scm_from_int (STOP));
2076                 $$ = m->unprotect ();
2077         }
2078         | E_BACKSLASH {
2079                 $$ = MAKE_SYNTAX ("voice-separator", @$);
2080         }
2081         | '|'      {
2082                 SCM pipe = parser->lexer_->lookup_identifier ("pipeSymbol");
2083
2084                 Music *m = unsmob_music (pipe);
2085                 if (m)
2086                 {
2087                         m = m->clone ();
2088                         m->set_spot (@$);
2089                         $$ = m->unprotect ();
2090                 }
2091                 else
2092                         $$ = MAKE_SYNTAX ("bar-check", @$);
2093
2094         }
2095         ;
2096
2097 command_event:
2098         E_TILDE {
2099                 $$ = MY_MAKE_MUSIC ("PesOrFlexaEvent", @$)->unprotect ();
2100         }
2101         | tempo_event {
2102                 $$ = $1;
2103         }
2104         ;
2105
2106
2107 post_events:
2108         /* empty */ {
2109                 $$ = SCM_EOL;
2110         }
2111         | post_events post_event {
2112                 unsmob_music ($2)->set_spot (@2);
2113                 $$ = scm_cons ($2, $$);
2114         }
2115         ;
2116
2117 post_event_nofinger:
2118         direction_less_event {
2119                 $$ = $1;
2120         }
2121         | script_dir music_function_call_closed {
2122                 $$ = $2;
2123                 if (!SCM_UNBNDP ($1))
2124                 {
2125                         unsmob_music ($$)->set_property ("direction", $1);
2126                 }
2127         }
2128         | HYPHEN {
2129                 if (!parser->lexer_->is_lyric_state ())
2130                         parser->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
2131                 $$ = MY_MAKE_MUSIC ("HyphenEvent", @$)->unprotect ();
2132         }
2133         | EXTENDER {
2134                 if (!parser->lexer_->is_lyric_state ())
2135                         parser->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
2136                 $$ = MY_MAKE_MUSIC ("ExtenderEvent", @$)->unprotect ();
2137         }
2138         | script_dir direction_reqd_event {
2139                 if (!SCM_UNBNDP ($1))
2140                 {
2141                         Music *m = unsmob_music ($2);
2142                         m->set_property ("direction", $1);
2143                 }
2144                 $$ = $2;
2145         }
2146         | script_dir direction_less_event {
2147                 if (!SCM_UNBNDP ($1))
2148                 {
2149                         Music *m = unsmob_music ($2);
2150                         m->set_property ("direction", $1);
2151                 }
2152                 $$ = $2;
2153         }
2154         | '^' fingering
2155         {
2156                 $$ = $2;
2157                 unsmob_music ($$)->set_property ("direction", scm_from_int (UP));
2158         }
2159         | '_' fingering
2160         {
2161                 $$ = $2;
2162                 unsmob_music ($$)->set_property ("direction", scm_from_int (DOWN));
2163         }                       
2164         ;
2165
2166 post_event:
2167         post_event_nofinger
2168         | '-' fingering {
2169                 $$ = $2;
2170         }
2171         ;
2172
2173 string_number_event:
2174         E_UNSIGNED {
2175                 Music *s = MY_MAKE_MUSIC ("StringNumberEvent", @$);
2176                 s->set_property ("string-number", $1);
2177                 $$ = s->unprotect ();
2178         }
2179         ;
2180
2181 direction_less_char:
2182         '['  {
2183                 $$ = ly_symbol2scm ("bracketOpenSymbol");
2184         }
2185         | ']'  {
2186                 $$ = ly_symbol2scm ("bracketCloseSymbol");
2187         }
2188         | '~'  {
2189                 $$ = ly_symbol2scm ("tildeSymbol");
2190         }
2191         | '('  {
2192                 $$ = ly_symbol2scm ("parenthesisOpenSymbol");
2193         }
2194         | ')'  {
2195                 $$ = ly_symbol2scm ("parenthesisCloseSymbol");
2196         }
2197         | E_EXCLAMATION  {
2198                 $$ = ly_symbol2scm ("escapedExclamationSymbol");
2199         }
2200         | E_OPEN  {
2201                 $$ = ly_symbol2scm ("escapedParenthesisOpenSymbol");
2202         }
2203         | E_CLOSE  {
2204                 $$ = ly_symbol2scm ("escapedParenthesisCloseSymbol");
2205         }
2206         | E_ANGLE_CLOSE  {
2207                 $$ = ly_symbol2scm ("escapedBiggerSymbol");
2208         }
2209         | E_ANGLE_OPEN  {
2210                 $$ = ly_symbol2scm ("escapedSmallerSymbol");
2211         }
2212         ;
2213
2214 direction_less_event:
2215         direction_less_char {
2216                 SCM predefd = parser->lexer_->lookup_identifier_symbol ($1);
2217                 Music *m = 0;
2218                 if (unsmob_music (predefd))
2219                 {
2220                         m = unsmob_music (predefd)->clone ();
2221                         m->set_spot (@$);
2222                 }
2223                 else
2224                 {
2225                         m = MY_MAKE_MUSIC ("Music", @$);
2226                 }
2227                 $$ = m->unprotect ();
2228         }
2229         | string_number_event
2230         | EVENT_IDENTIFIER      {
2231                 $$ = $1;
2232         }
2233         | tremolo_type  {
2234                Music *a = MY_MAKE_MUSIC ("TremoloEvent", @$);
2235                a->set_property ("tremolo-type", $1);
2236                $$ = a->unprotect ();
2237         }
2238         | event_function_event  
2239         ;
2240
2241 direction_reqd_event:
2242         gen_text_def {
2243                 $$ = $1;
2244         }
2245         | script_abbreviation {
2246                 SCM s = parser->lexer_->lookup_identifier ("dash" + ly_scm2string ($1));
2247                 Music *a = MY_MAKE_MUSIC ("ArticulationEvent", @$);
2248                 if (scm_is_string (s))
2249                         a->set_property ("articulation-type", s);
2250                 else parser->parser_error (@1, _ ("expecting string as script definition"));
2251                 $$ = a->unprotect ();
2252         }
2253         ;
2254
2255 octave_check:
2256         /**/ { $$ = SCM_EOL; }
2257         | '=' quotes { $$ = $2; }
2258         ;
2259
2260 quotes:
2261         /* empty */
2262         {
2263                 $$ = SCM_INUM0;
2264         }
2265         | sub_quotes
2266         | sup_quotes
2267         ;
2268
2269 sup_quotes:
2270         '\'' {
2271                 $$ = scm_from_int (1);
2272         }
2273         | sup_quotes '\'' {
2274                 $$ = scm_oneplus ($1);
2275         }
2276         ;
2277
2278 sub_quotes:
2279         ',' {
2280                 $$ = scm_from_int (-1);
2281         }
2282         | sub_quotes ',' {
2283                 $$ = scm_oneminus ($1);
2284         }
2285         ;
2286
2287 steno_pitch:
2288         NOTENAME_PITCH quotes {
2289                 if (!scm_is_eq (SCM_INUM0, $2))
2290                 {
2291                         Pitch p = *unsmob_pitch ($1);
2292                         p = p.transposed (Pitch (scm_to_int ($2),0,0));
2293                         $$ = p.smobbed_copy ();
2294                 }
2295         }
2296         ;
2297
2298 /*
2299 ugh. duplication
2300 */
2301
2302 steno_tonic_pitch:
2303         TONICNAME_PITCH quotes {
2304                 if (!scm_is_eq (SCM_INUM0, $2))
2305                 {
2306                         Pitch p = *unsmob_pitch ($1);
2307                         p = p.transposed (Pitch (scm_to_int ($2),0,0));
2308                         $$ = p.smobbed_copy ();
2309                 }
2310         }
2311         ;
2312
2313 pitch:
2314         steno_pitch
2315         | PITCH_IDENTIFIER
2316         ;
2317
2318 pitch_also_in_chords:
2319         pitch
2320         | steno_tonic_pitch
2321         ;
2322
2323 gen_text_def:
2324         full_markup {
2325                 Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
2326                 t->set_property ("text", $1);
2327                 $$ = t->unprotect ();
2328         }
2329         | STRING {
2330                 Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
2331                 t->set_property ("text",
2332                         make_simple_markup ($1));
2333                 $$ = t->unprotect ();
2334         }
2335         | LYRICS_STRING {
2336                 Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
2337                 t->set_property ("text",
2338                         make_simple_markup ($1));
2339                 $$ = t->unprotect ();
2340         }
2341         ;
2342
2343 fingering:
2344         UNSIGNED {
2345                 Music *t = MY_MAKE_MUSIC ("FingeringEvent", @$);
2346                 t->set_property ("digit", $1);
2347                 $$ = t->unprotect ();
2348         }
2349         ;
2350
2351 script_abbreviation:
2352         '^'             {
2353                 $$ = scm_from_locale_string ("Hat");
2354         }
2355         | '+'           {
2356                 $$ = scm_from_locale_string ("Plus");
2357         }
2358         | '-'           {
2359                 $$ = scm_from_locale_string ("Dash");
2360         }
2361         | '|'           {
2362                 $$ = scm_from_locale_string ("Bar");
2363         }
2364         | ANGLE_CLOSE   {
2365                 $$ = scm_from_locale_string ("Larger");
2366         }
2367         | '.'           {
2368                 $$ = scm_from_locale_string ("Dot");
2369         }
2370         | '_' {
2371                 $$ = scm_from_locale_string ("Underscore");
2372         }
2373         ;
2374
2375 script_dir:
2376         '_'     { $$ = scm_from_int (DOWN); }
2377         | '^'   { $$ = scm_from_int (UP); }
2378         | '-'   { $$ = SCM_UNDEFINED; }
2379         ;
2380
2381 duration_length:
2382         multiplied_duration {
2383                 $$ = $1;
2384         }
2385         ;
2386
2387 maybe_notemode_duration:
2388         {
2389                 $$ = SCM_UNDEFINED;
2390         }
2391         | multiplied_duration   {
2392                 $$ = $1;
2393                 parser->default_duration_ = *unsmob_duration ($$);
2394         }
2395 ;
2396
2397
2398 optional_notemode_duration:
2399         maybe_notemode_duration
2400         {
2401                 if (SCM_UNBNDP ($$))
2402                         $$ = parser->default_duration_.smobbed_copy ();
2403         }
2404         ;
2405
2406 steno_duration:
2407         UNSIGNED dots           {
2408                 int len = 0;
2409                 int n = scm_to_int ($1);
2410                 if (!is_duration (n))
2411                         parser->parser_error (@1, _f ("not a duration: %d", n));
2412                 else
2413                         len = intlog2 (n);
2414
2415                 $$ = Duration (len, scm_to_int ($2)).smobbed_copy ();
2416         }
2417         | DURATION_IDENTIFIER dots      {
2418                 Duration *d = unsmob_duration ($1);
2419                 Duration k (d->duration_log (),
2420                             d->dot_count () + scm_to_int ($2));
2421                 k = k.compressed (d->factor ());
2422                 scm_remember_upto_here_1 ($1);
2423                 $$ = k.smobbed_copy ();
2424         }
2425         ;
2426
2427 multiplied_duration:
2428         steno_duration {
2429                 $$ = $1;
2430         }
2431         | multiplied_duration '*' UNSIGNED {
2432                 $$ = unsmob_duration ($$)->compressed (scm_to_int ($3)).smobbed_copy ();
2433         }
2434         | multiplied_duration '*' FRACTION {
2435                 Rational  m (scm_to_int (scm_car ($3)), scm_to_int (scm_cdr ($3)));
2436
2437                 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
2438         }
2439         ;
2440
2441 dots:
2442         /* empty */     {
2443                 $$ = SCM_INUM0;
2444         }
2445         | dots '.' {
2446                 $$ = scm_oneplus ($1);
2447         }
2448         ;
2449
2450 tremolo_type:
2451         ':'     {
2452                 $$ = SCM_INUM0;
2453         }
2454         | ':' UNSIGNED {
2455                 int n = scm_to_int ($2);
2456                 if (!is_duration (n))
2457                         parser->parser_error (@2, _f ("not a duration: %d", n));
2458                 $$ = $2;
2459         }
2460         ;
2461
2462 bass_number:
2463         UNSIGNED { $$ = $1; }
2464         | STRING { $$ = $1; }
2465         | full_markup { $$ = $1; }
2466         ;
2467
2468 figured_bass_alteration:
2469         '-'     { $$ = ly_rational2scm (FLAT_ALTERATION); }
2470         | '+'   { $$ = ly_rational2scm (SHARP_ALTERATION); }
2471         | '!'   { $$ = scm_from_int (0); }
2472         ;
2473
2474 bass_figure:
2475         FIGURE_SPACE {
2476                 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent", @$);
2477                 $$ = bfr->unprotect ();
2478         }
2479         | bass_number  {
2480                 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent", @$);
2481                 $$ = bfr->self_scm ();
2482
2483                 if (scm_is_number ($1))
2484                         bfr->set_property ("figure", $1);
2485                 else if (Text_interface::is_markup ($1))
2486                         bfr->set_property ("text", $1);
2487
2488                 bfr->unprotect ();
2489         }
2490         | bass_figure ']' {
2491                 $$ = $1;
2492                 unsmob_music ($1)->set_property ("bracket-stop", SCM_BOOL_T);
2493         }
2494         | bass_figure figured_bass_alteration {
2495                 Music *m = unsmob_music ($1);
2496                 if (scm_to_double ($2)) {
2497                         SCM salter = m->get_property ("alteration");
2498                         SCM alter = scm_is_number (salter) ? salter : scm_from_int (0);
2499                         m->set_property ("alteration",
2500                                          scm_sum (alter, $2));
2501                 } else {
2502                         m->set_property ("alteration", scm_from_int (0));
2503                 }
2504         }
2505         | bass_figure figured_bass_modification  {
2506                 Music *m = unsmob_music ($1);
2507                 if ($2 == ly_symbol2scm ("plus"))
2508                         {
2509                         m->set_property ("augmented", SCM_BOOL_T);
2510                         }
2511                 else if ($2 == ly_symbol2scm ("slash"))
2512                         {
2513                         m->set_property ("diminished", SCM_BOOL_T);
2514                         }
2515                 else if ($2 == ly_symbol2scm ("exclamation"))
2516                         {
2517                         m->set_property ("no-continuation", SCM_BOOL_T);
2518                         }
2519                 else if ($2 == ly_symbol2scm ("backslash"))
2520                         {
2521                         m->set_property ("augmented-slash", SCM_BOOL_T);
2522                         }
2523         }
2524         ;
2525
2526
2527 figured_bass_modification:
2528         E_PLUS          {
2529                 $$ = ly_symbol2scm ("plus");
2530         }
2531         | E_EXCLAMATION {
2532                 $$ = ly_symbol2scm ("exclamation");
2533         }
2534         | '/'           {
2535                 $$ = ly_symbol2scm ("slash");
2536         }
2537         | E_BACKSLASH {
2538                 $$ = ly_symbol2scm ("backslash");
2539         }
2540         ;
2541
2542 br_bass_figure:
2543         bass_figure {
2544                 $$ = $1;
2545         }
2546         | '[' bass_figure {
2547                 $$ = $2;
2548                 unsmob_music ($$)->set_property ("bracket-start", SCM_BOOL_T);
2549         }
2550         ;
2551
2552 figure_list:
2553         /**/            {
2554                 $$ = SCM_EOL;
2555         }
2556         | figure_list br_bass_figure {
2557                 $$ = scm_cons ($2, $1);
2558         }
2559         ;
2560
2561 figure_spec:
2562         FIGURE_OPEN figure_list FIGURE_CLOSE {
2563                 $$ = scm_reverse_x ($2, SCM_EOL);
2564         }
2565         ;
2566
2567
2568 optional_rest:
2569         /**/   { $$ = SCM_BOOL_F; }
2570         | REST { $$ = SCM_BOOL_T; }
2571         ;
2572
2573 simple_element:
2574         pitch exclamations questions octave_check maybe_notemode_duration optional_rest {
2575                 if (!parser->lexer_->is_note_state ())
2576                         parser->parser_error (@1, _ ("have to be in Note mode for notes"));
2577                 if (!SCM_UNBNDP ($2)
2578                     || !SCM_UNBNDP ($3)
2579                     || scm_is_number ($4)
2580                     || !SCM_UNBNDP ($5)
2581                     || scm_is_true ($6))
2582                 {
2583                         Music *n = 0;
2584                         if (scm_is_true ($6))
2585                                 n = MY_MAKE_MUSIC ("RestEvent", @$);
2586                         else
2587                                 n = MY_MAKE_MUSIC ("NoteEvent", @$);
2588                         
2589                         n->set_property ("pitch", $1);
2590                         if (SCM_UNBNDP ($5))
2591                                 n->set_property ("duration",
2592                                                  parser->default_duration_.smobbed_copy ());
2593                         else
2594                                 n->set_property ("duration", $5);
2595                         
2596                         if (scm_is_number ($4))
2597                         {
2598                                 int q = scm_to_int ($4);
2599                                 n->set_property ("absolute-octave", scm_from_int (q-1));
2600                         }
2601                         
2602                         if (to_boolean ($3))
2603                                 n->set_property ("cautionary", SCM_BOOL_T);
2604                         if (to_boolean ($2) || to_boolean ($3))
2605                                 n->set_property ("force-accidental", SCM_BOOL_T);
2606                         
2607                         $$ = n->unprotect ();
2608                 }
2609         }
2610         | DRUM_PITCH optional_notemode_duration {
2611                 Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
2612                 n->set_property ("duration", $2);
2613                 n->set_property ("drum-type", $1);
2614
2615                 $$ = n->unprotect ();
2616         }
2617         | RESTNAME optional_notemode_duration           {
2618                 Music *ev = 0;
2619                 if (ly_scm2string ($1) == "s") {
2620                         /* Space */
2621                         ev = MY_MAKE_MUSIC ("SkipEvent", @$);
2622                   }
2623                 else {
2624                         ev = MY_MAKE_MUSIC ("RestEvent", @$);
2625
2626                     }
2627                 ev->set_property ("duration", $2);
2628                 $$ = ev->unprotect ();
2629         }
2630         ;
2631
2632 simple_chord_elements:
2633         new_chord {
2634                 if (!parser->lexer_->is_chord_state ())
2635                         parser->parser_error (@1, _ ("have to be in Chord mode for chords"));
2636                 $$ = $1;
2637         }
2638         | figure_spec optional_notemode_duration {
2639                 for (SCM s = $1; scm_is_pair (s); s = scm_cdr (s))
2640                 {
2641                         unsmob_music (scm_car (s))->set_property ("duration", $2);
2642                 }
2643                 $$ = $1;
2644         }
2645         ;
2646
2647 lyric_element:
2648         lyric_markup {
2649                 $$ = $1;
2650         }
2651         | LYRICS_STRING {
2652                 $$ = $1;
2653         }
2654         ;
2655
2656 lyric_element_arg:
2657         lyric_element
2658         | lyric_element multiplied_duration post_events {
2659                 $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
2660                 if (scm_is_pair ($3))
2661                         unsmob_music ($$)->set_property
2662                                 ("articulations", scm_reverse_x ($3, SCM_EOL));
2663         }
2664         | lyric_element post_event post_events {
2665                 $$ = MAKE_SYNTAX ("lyric-event", @$, $1,
2666                                   parser->default_duration_.smobbed_copy ());
2667                 unsmob_music ($$)->set_property
2668                         ("articulations", scm_cons ($2, scm_reverse_x ($3, SCM_EOL)));
2669         }
2670         | LYRIC_ELEMENT optional_notemode_duration post_events {
2671                 $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
2672                 if (scm_is_pair ($3))
2673                         unsmob_music ($$)->set_property
2674                                 ("articulations", scm_reverse_x ($3, SCM_EOL));
2675         }
2676         ;
2677
2678
2679 lyric_element_music:
2680         lyric_element optional_notemode_duration post_events {
2681                 $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
2682                 if (scm_is_pair ($3))
2683                         unsmob_music ($$)->set_property
2684                                 ("articulations", scm_reverse_x ($3, SCM_EOL));
2685         }
2686         ;
2687
2688 new_chord:
2689         steno_tonic_pitch optional_notemode_duration   {
2690                 $$ = make_chord_elements (@$, $1, $2, SCM_EOL);
2691         }
2692         | steno_tonic_pitch optional_notemode_duration chord_separator chord_items {
2693                 SCM its = scm_reverse_x ($4, SCM_EOL);
2694                 $$ = make_chord_elements (@$, $1, $2, scm_cons ($3, its));
2695         }
2696         ;
2697
2698 chord_items:
2699         /**/ {
2700                 $$ = SCM_EOL;
2701         }
2702         | chord_items chord_item {
2703                 $$ = scm_cons ($2, $$);
2704         }
2705         ;
2706
2707 chord_separator:
2708         CHORD_COLON {
2709                 $$ = ly_symbol2scm ("chord-colon");
2710         }
2711         | CHORD_CARET {
2712                 $$ = ly_symbol2scm ("chord-caret");
2713         }
2714         | CHORD_SLASH steno_tonic_pitch {
2715                 $$ = scm_list_2 (ly_symbol2scm ("chord-slash"), $2);
2716         }
2717         | CHORD_BASS steno_tonic_pitch {
2718                 $$ = scm_list_2 (ly_symbol2scm ("chord-bass"), $2);
2719         }
2720         ;
2721
2722 chord_item:
2723         chord_separator {
2724                 $$ = $1;
2725         }
2726         | step_numbers {
2727                 $$ = scm_reverse_x ($1, SCM_EOL);
2728         }
2729         | CHORD_MODIFIER  {
2730                 $$ = $1;
2731         }
2732         ;
2733
2734 step_numbers:
2735         step_number { $$ = scm_cons ($1, SCM_EOL); }
2736         | step_numbers '.' step_number {
2737                 $$ = scm_cons ($3, $$);
2738         }
2739         ;
2740
2741 step_number:
2742         UNSIGNED {
2743                 $$ = make_chord_step ($1, 0);
2744         }
2745         | UNSIGNED '+' {
2746                 $$ = make_chord_step ($1, SHARP_ALTERATION);
2747         }
2748         | UNSIGNED CHORD_MINUS {
2749                 $$ = make_chord_step ($1, FLAT_ALTERATION);
2750         }
2751         ;
2752
2753 tempo_range:
2754         UNSIGNED {
2755                 $$ = $1;
2756         }
2757         | UNSIGNED '~' UNSIGNED {
2758                 $$ = scm_cons ($1, $3);
2759         }
2760         ;
2761
2762 /*
2763         UTILITIES
2764
2765 TODO: should deprecate in favor of Scheme?
2766
2767  */
2768 number_expression:
2769         number_expression '+' number_term {
2770                 $$ = scm_sum ($1, $3);
2771         }
2772         | number_expression '-' number_term {
2773                 $$ = scm_difference ($1, $3);
2774         }
2775         | number_term
2776         ;
2777
2778 number_term:
2779         number_factor {
2780                 $$ = $1;
2781         }
2782         | number_factor '*' number_factor {
2783                 $$ = scm_product ($1, $3);
2784         }
2785         | number_factor '/' number_factor {
2786                 $$ = scm_divide ($1, $3);
2787         }
2788         ;
2789
2790 number_factor:
2791         '-'  number_factor { /* %prec UNARY_MINUS */
2792                 $$ = scm_difference ($2, SCM_UNDEFINED);
2793         }
2794         | bare_number
2795         ;
2796
2797
2798 bare_number:
2799         bare_number_closed
2800         | UNSIGNED NUMBER_IDENTIFIER    {
2801                 $$ = scm_product ($1, $2);
2802         }
2803         | REAL NUMBER_IDENTIFIER        {
2804                 $$ = scm_product ($1, $2);
2805         }
2806         ;
2807
2808 bare_number_closed:
2809         UNSIGNED
2810         | REAL
2811         | NUMBER_IDENTIFIER
2812         ;
2813
2814 unsigned_number:
2815         UNSIGNED
2816         | NUMBER_IDENTIFIER
2817         ;
2818
2819 exclamations:
2820                 { $$ = SCM_UNDEFINED; }
2821         | exclamations '!'
2822         {
2823                 if (SCM_UNBNDP ($1))
2824                         $$ = SCM_BOOL_T;
2825                 else
2826                         $$ = scm_not ($1);
2827         }
2828         ;
2829
2830 questions:
2831         { $$ = SCM_UNDEFINED; }
2832         | questions '?'
2833         {
2834                 if (SCM_UNBNDP ($1))
2835                         $$ = SCM_BOOL_T;
2836                 else
2837                         $$ = scm_not ($1);
2838         }
2839         ;
2840
2841 /*
2842 This should be done more dynamically if possible.
2843 */
2844
2845 lyric_markup:
2846         LYRIC_MARKUP_IDENTIFIER {
2847                 $$ = $1;
2848         }
2849         | LYRIC_MARKUP
2850                 { parser->lexer_->push_markup_state (); }
2851         markup_top {
2852                 $$ = $3;
2853                 parser->lexer_->pop_state ();
2854         }
2855         ;
2856
2857 full_markup_list:
2858         MARKUPLIST_IDENTIFIER {
2859                 $$ = $1;
2860         }
2861         | MARKUPLIST
2862                 { parser->lexer_->push_markup_state (); }
2863         markup_list {
2864                 $$ = $3;
2865                 parser->lexer_->pop_state ();
2866         }
2867         ;
2868
2869 full_markup:
2870         MARKUP_IDENTIFIER {
2871                 $$ = $1;
2872         }
2873         | MARKUP
2874                 { parser->lexer_->push_markup_state (); }
2875         markup_top {
2876                 $$ = $3;
2877                 parser->lexer_->pop_state ();
2878         }
2879         ;
2880
2881 markup_top:
2882         markup_list {
2883                 $$ = scm_list_2 (ly_lily_module_constant ("line-markup"),  $1);
2884         }
2885         | markup_head_1_list simple_markup      {
2886                 $$ = scm_car (scm_call_2 (ly_lily_module_constant ("map-markup-command-list"), $1, scm_list_1 ($2)));
2887         }
2888         | simple_markup {
2889                 $$ = $1;
2890         }
2891         ;
2892
2893 markup_scm:
2894         embedded_scm_bare
2895         {
2896                 if (Text_interface::is_markup ($1))
2897                         MYBACKUP (MARKUP_IDENTIFIER, $1, @1);
2898                 else if (Text_interface::is_markup_list ($1))
2899                         MYBACKUP (MARKUPLIST_IDENTIFIER, $1, @1);
2900                 else {
2901                         parser->parser_error (@1, _ ("not a markup"));
2902                         MYBACKUP (MARKUP_IDENTIFIER, scm_string (SCM_EOL), @1);
2903                 }
2904         } BACKUP
2905         ;
2906                         
2907
2908 markup_list:
2909         MARKUPLIST_IDENTIFIER {
2910                 $$ = $1;
2911         }
2912         | markup_composed_list {
2913                 $$ = $1;
2914         }
2915         | markup_braced_list {
2916                 $$ = $1;
2917         }
2918         | markup_command_list {
2919                 $$ = scm_list_1 ($1);
2920         }
2921         | markup_scm MARKUPLIST_IDENTIFIER
2922         {
2923                 $$ = $2;
2924         }
2925         ;
2926
2927 markup_composed_list:
2928         markup_head_1_list markup_braced_list {
2929                 $$ = scm_call_2 (ly_lily_module_constant ("map-markup-command-list"), $1, $2);
2930
2931         }
2932         ;
2933
2934 markup_braced_list:
2935         '{' markup_braced_list_body '}' {
2936                 $$ = scm_reverse_x ($2, SCM_EOL);
2937         }
2938         ;
2939
2940 markup_braced_list_body:
2941         /* empty */     {  $$ = SCM_EOL; }
2942         | markup_braced_list_body markup {
2943                 $$ = scm_cons ($2, $1);
2944         }
2945         | markup_braced_list_body markup_list {
2946                 $$ = scm_reverse_x ($2, $1);
2947         }
2948         ;
2949
2950 markup_command_list:
2951         MARKUP_LIST_FUNCTION markup_command_list_arguments {
2952           $$ = scm_cons ($1, scm_reverse_x($2, SCM_EOL));
2953         }
2954         ;
2955
2956 markup_command_basic_arguments:
2957         EXPECT_MARKUP_LIST markup_command_list_arguments markup_list {
2958           $$ = scm_cons ($3, $2);
2959         }
2960         | EXPECT_SCM markup_command_list_arguments embedded_scm_closed {
2961           $$ = check_scheme_arg (parser, @3, $3, $2, $1);
2962         }
2963         | EXPECT_NO_MORE_ARGS {
2964           $$ = SCM_EOL;
2965         }
2966         ;
2967
2968 markup_command_list_arguments:
2969         markup_command_basic_arguments { $$ = $1; }
2970         | EXPECT_MARKUP markup_command_list_arguments markup {
2971           $$ = scm_cons ($3, $2);
2972         }
2973         ;
2974
2975 markup_head_1_item:
2976         MARKUP_FUNCTION EXPECT_MARKUP markup_command_list_arguments {
2977           $$ = scm_cons ($1, scm_reverse_x ($3, SCM_EOL));
2978         }
2979         ;
2980
2981 markup_head_1_list:
2982         markup_head_1_item      {
2983                 $$ = scm_list_1 ($1);
2984         }
2985         | markup_head_1_list markup_head_1_item {
2986                 $$ = scm_cons ($2, $1);
2987         }
2988         ;
2989
2990 simple_markup:
2991         STRING {
2992                 $$ = make_simple_markup ($1);
2993         }
2994         | MARKUP_IDENTIFIER {
2995                 $$ = $1;
2996         }
2997         | LYRIC_MARKUP_IDENTIFIER {
2998                 $$ = $1;
2999         }
3000         | SCORE {
3001                 SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
3002                 parser->lexer_->push_note_state (nn);
3003         } '{' score_body '}' {
3004                 $$ = scm_list_2 (ly_lily_module_constant ("score-markup"), $4);
3005                 parser->lexer_->pop_state ();
3006         }
3007         | MARKUP_FUNCTION markup_command_basic_arguments {
3008                 $$ = scm_cons ($1, scm_reverse_x ($2, SCM_EOL));
3009         }
3010         | markup_scm MARKUP_IDENTIFIER
3011         {
3012                 $$ = $2;
3013         }
3014         ;
3015
3016 markup:
3017         markup_head_1_list simple_markup        {
3018                 SCM mapper = ly_lily_module_constant ("map-markup-command-list");
3019                 $$ = scm_car (scm_call_2 (mapper, $1, scm_list_1 ($2)));
3020         }
3021         | simple_markup {
3022                 $$ = $1;
3023         }
3024         ;
3025
3026 %%
3027
3028 void
3029 Lily_parser::set_yydebug (bool x)
3030 {
3031         yydebug = x;
3032 }
3033
3034 SCM
3035 Lily_parser::do_yyparse ()
3036 {
3037         SCM retval = SCM_UNDEFINED;
3038         yyparse (this, &retval);
3039         return retval;
3040 }
3041
3042
3043
3044
3045
3046 /*
3047
3048 It is a little strange to have this function in this file, but
3049 otherwise, we have to import music classes into the lexer.
3050
3051 */
3052 int
3053 Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
3054 {
3055         if (unsmob_book (sid)) {
3056                 Book *book =  unsmob_book (sid)->clone ();
3057                 *destination = book->self_scm ();
3058                 book->unprotect ();
3059
3060                 return BOOK_IDENTIFIER;
3061         } else if (scm_is_number (sid)) {
3062                 *destination = sid;
3063                 return NUMBER_IDENTIFIER;
3064         } else if (unsmob_context_def (sid)) {
3065                 Context_def *def= unsmob_context_def (sid)->clone ();
3066
3067                 *destination = def->self_scm ();
3068                 def->unprotect ();
3069
3070                 return CONTEXT_DEF_IDENTIFIER;
3071         } else if (unsmob_context_mod (sid)) {
3072                 *destination = unsmob_context_mod (sid)->smobbed_copy ();
3073
3074                 return CONTEXT_MOD_IDENTIFIER;
3075         } else if (unsmob_score (sid)) {
3076                 Score *score = new Score (*unsmob_score (sid));
3077                 *destination = score->self_scm ();
3078
3079                 score->unprotect ();
3080                 return SCORE_IDENTIFIER;
3081         } else if (Music *mus = unsmob_music (sid)) {
3082                 mus = mus->clone ();
3083                 *destination = mus->self_scm ();
3084                 unsmob_music (*destination)->
3085                         set_property ("origin", make_input (last_input_));
3086
3087                 bool is_event = mus->is_mus_type ("post-event");
3088                 mus->unprotect ();
3089                 return is_event ? EVENT_IDENTIFIER : MUSIC_IDENTIFIER;
3090         } else if (unsmob_pitch (sid)) {
3091                 *destination = unsmob_pitch (sid)->smobbed_copy ();
3092                 return PITCH_IDENTIFIER;
3093         } else if (unsmob_duration (sid)) {
3094                 *destination = unsmob_duration (sid)->smobbed_copy ();
3095                 return DURATION_IDENTIFIER;
3096         } else if (unsmob_output_def (sid)) {
3097                 Output_def *p = unsmob_output_def (sid);
3098                 p = p->clone ();
3099
3100                 *destination = p->self_scm ();
3101                 p->unprotect ();
3102                 return OUTPUT_DEF_IDENTIFIER;
3103         } else if (Text_interface::is_markup (sid)) {
3104                 *destination = sid;
3105                 if (is_lyric_state ())
3106                         return LYRIC_MARKUP_IDENTIFIER;
3107                 return MARKUP_IDENTIFIER;
3108         } else if (Text_interface::is_markup_list (sid)) {
3109                 *destination = sid;
3110                 return MARKUPLIST_IDENTIFIER;
3111         }
3112
3113         return -1;
3114 }
3115
3116 SCM
3117 get_next_unique_context_id ()
3118 {
3119         return scm_from_locale_string ("$uniqueContextId");
3120 }
3121
3122
3123 SCM
3124 get_next_unique_lyrics_context_id ()
3125 {
3126         static int new_context_count;
3127         char s[128];
3128         snprintf (s, sizeof (s)-1, "uniqueContext%d", new_context_count++);
3129         return scm_from_locale_string (s);
3130 }
3131
3132 SCM check_scheme_arg (Lily_parser *parser, Input loc,
3133                       SCM arg, SCM args, SCM pred)
3134 {
3135         args = scm_cons (arg, args);
3136         if (scm_is_true (scm_call_1 (pred, arg)))
3137                 return args;
3138         scm_set_cdr_x (scm_last_pair (args), SCM_EOL);
3139         MAKE_SYNTAX ("argument-error", loc, scm_length (args), pred, arg);
3140         scm_set_cdr_x (scm_last_pair (args), SCM_BOOL_F);
3141         return args;
3142 }
3143
3144 SCM loc_on_music (Input loc, SCM arg)
3145 {
3146         if (Music *m = unsmob_music (arg))
3147         {
3148                 m = m->clone ();
3149                 m->set_spot (loc);
3150                 return m->unprotect ();
3151         }
3152         return arg;
3153 }
3154
3155 bool
3156 is_regular_identifier (SCM id)
3157 {
3158   string str = ly_scm2string (id);
3159   char const *s = str.c_str ();
3160
3161   bool v = true;
3162 #if 0
3163   isalpha (*s);
3164   s++;
3165 #endif
3166   while (*s && v)
3167    {
3168         v = v && isalnum (*s);
3169         s++;
3170    }
3171   return v;
3172 }
3173
3174 Music *
3175 make_music_with_input (SCM name, Input where)
3176 {
3177        Music *m = make_music_by_name (name);
3178        m->set_spot (where);
3179        return m;
3180 }
3181
3182 SCM
3183 make_simple_markup (SCM a)
3184 {
3185         return a;
3186 }
3187
3188 bool
3189 is_duration (int t)
3190 {
3191   return t && t == 1 << intlog2 (t);
3192 }
3193
3194 SCM
3195 make_chord_step (SCM step_scm, Rational alter)
3196 {
3197         int step = scm_to_int (step_scm);
3198
3199         if (step == 7)
3200                 alter += FLAT_ALTERATION;
3201
3202         while (step < 0)
3203                 step += 7;
3204         Pitch m ((step -1) / 7, (step - 1) % 7, alter);
3205         return m.smobbed_copy ();
3206 }
3207
3208
3209 SCM
3210 make_chord_elements (Input loc, SCM pitch, SCM dur, SCM modification_list)
3211 {
3212         SCM chord_ctor = ly_lily_module_constant ("construct-chord-elements");
3213         SCM res = scm_call_3 (chord_ctor, pitch, dur, modification_list);
3214         for (SCM s = res; scm_is_pair (s); s = scm_cdr (s))
3215         {
3216                 unsmob_music (scm_car (s))->set_spot (loc);
3217         }
3218         return res;
3219 }
3220
3221 int
3222 yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser)
3223 {
3224         Lily_lexer *lex = parser->lexer_;
3225
3226         lex->lexval_ = s;
3227         lex->lexloc_ = loc;
3228         lex->prepare_for_next_token ();
3229         return lex->yylex ();
3230 }