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