1 %{ // -*-Fundamental-*-
4 parser.yy -- Bison/C++ parser for LilyPond
6 source file of the GNU LilyPond music typesetter
8 (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 Jan Nieuwenhuizen <janneke@gnu.org>
16 * The rules for who is protecting what are very shady. Uniformise
19 * There are too many lexical modes?
30 #include "context-def.hh"
31 #include "dimensions.hh"
33 #include "file-path.hh"
34 #include "input-smob.hh"
36 #include "lily-guile.hh"
37 #include "lilypond-input-version.hh"
38 #include "ly-module.hh"
41 #include "music-list.hh"
42 #include "music-sequence.hh"
43 #include "lily-lexer.hh"
44 #include "lily-parser.hh"
45 #include "paper-book.hh"
46 #include "output-def.hh"
47 #include "scm-hash.hh"
48 #include "scm-option.hh"
50 #include "text-item.hh"
53 #define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x))
55 Music *property_op_to_music (SCM op);
56 Music *context_spec_music (SCM type, SCM id, Music *m, SCM ops_);
57 SCM get_next_unique_context ();
59 #define YYERROR_VERBOSE 1
61 #define YYPARSE_PARAM my_lily_parser
62 #define YYLEX_PARAM my_lily_parser
64 ((Lily_parser *) my_lily_parser)
66 #define yyerror THIS->parser_error
68 /* Add symbols to the TAGS field of a music object. */
71 tag_music (Music *m, SCM tag, Input ip)
73 SCM tags = m->get_property ("tags");
74 if (scm_is_symbol (tag))
75 tags = scm_cons (tag, tags);
76 else if (ly_c_list_p (tag))
77 tags = ly_append2 (tag, tags);
79 ip.warning (_ ("Tag must be symbol or list of symbols."));
81 m->set_property ("tags", tags);
85 is_regular_identifier (SCM id)
87 String str = ly_scm2string (id);
88 char const *s = str.to_str0 ();
97 v = v && isalnum (*s);
104 make_simple_markup (SCM encoding, SCM a)
106 SCM simple = ly_scheme_function ("simple-markup");
107 if (scm_is_symbol (encoding))
108 return scm_list_3 (ly_scheme_function ("encoded-simple-markup"),
110 return scm_list_2 (simple, a);
116 return t && t == 1 << intlog2 (t);
120 set_music_properties (Music *p, SCM a)
122 for (SCM k = a; ly_c_pair_p (k); k = ly_cdr (k))
123 p->internal_set_property (ly_caar (k), ly_cdar (k));
127 make_chord_step (int step, int alter)
134 Pitch m ((step -1) / 7, (step - 1) % 7, alter);
135 return m.smobbed_copy ();
140 make_chord (SCM pitch, SCM dur, SCM modification_list)
142 SCM chord_ctor = ly_scheme_function ("construct-chord");
143 SCM ch = scm_call_3 (chord_ctor, pitch, dur, modification_list);
144 scm_gc_protect_object (ch);
148 /* Todo: actually also use apply iso. call too ... */
150 ly_input_procedure_p (SCM x)
152 return ly_c_procedure_p (x)
153 || (ly_c_pair_p (x) && ly_c_procedure_p (ly_car (x)));
157 set_property_music (SCM sym, SCM value)
159 Music *p = MY_MAKE_MUSIC ("PropertySet");
160 p->set_property ("symbol", sym);
161 p->set_property ("value", value);
166 make_music_relative (Pitch start, Music *music)
168 Music *relative = MY_MAKE_MUSIC ("RelativeOctaveMusic");
169 relative->set_property ("element", music->self_scm ());
171 Pitch last = music->to_relative_octave (start);
172 if (lily_1_8_relative)
173 music->set_property ("last-pitch", last.smobbed_copy ());
178 make_lyric_combine_music (SCM name, Music *music)
180 Music *combine = MY_MAKE_MUSIC ("NewLyricCombineMusic");
181 combine->set_property ("element", music->self_scm ());
182 combine->set_property ("associated-context", name);
188 /* We use SCMs to do strings, because it saves us the trouble of
189 deleting them. Let's hope that a stack overflow doesnt trigger a move
190 of the parse stack onto the heap. */
196 Output_def *outputdef;
206 yylex (YYSTYPE *s, void *v)
208 Lily_parser *pars = (Lily_parser*) v;
209 Lily_lexer *lex = pars->lexer_;
211 lex->lexval = (void*) s;
212 lex->prepare_for_next_token ();
213 return lex->yylex ();
222 Three shift/reduce problems:
224 2. \markup identifier.
234 \repeat .. \alternative
237 \repeat { \repeat .. \alternative }
241 \repeat { \repeat } \alternative
258 %token CHORDMODIFIERS
260 %token DOUBLE_ANGLE_OPEN
261 %token DOUBLE_ANGLE_CLOSE
263 %token COMMANDSPANREQUEST
270 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
271 %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
272 %token GROBDESCRIPTIONS
280 %token MULTI_MEASURE_REST
286 %token OVERRIDE SET REVERT
313 /* FIXME: this sucks. The user will get to see these names:
314 syntax error, unexpected E_CHAR:
319 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
320 %token E_LEFTSQUARE E_RIGHTSQUARE E_TILDE
322 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET CHORD_SLASH
327 %token <i> E_UNSIGNED
328 %token <id> IDENTIFIER
329 %token <scm> CHORDMODIFIER_PITCH
330 %token <scm> DRUM_PITCH
331 %token <scm> DURATION_IDENTIFIER
332 %token <scm> EVENT_IDENTIFIER
333 %token <scm> MUSIC_IDENTIFIER CONTEXT_DEF_IDENTIFIER
334 %token <scm> NOTENAME_PITCH
335 %token <scm> NUMBER_IDENTIFIER
336 %token <scm> OUTPUT_DEF_IDENTIFIER
337 %token <scm> RESTNAME
338 %token <scm> LYRICS_STRING
340 %token <scm> SCORE_IDENTIFIER
342 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
343 %token <scm> TONICNAME_PITCH
344 %token <scm> CHORD_MODIFIER
345 %token <scm> FRACTION
347 %token <scm> MARKUP_HEAD_EMPTY
348 %token <scm> MARKUP_HEAD_MARKUP0
349 %token <scm> MARKUP_HEAD_MARKUP0_MARKUP1
350 %token <scm> MARKUP_HEAD_SCM0
351 %token <scm> MARKUP_HEAD_SCM0_MARKUP1
352 %token <scm> MARKUP_HEAD_SCM0_SCM1
353 %token <scm> MARKUP_HEAD_SCM0_SCM1_MARKUP2
354 %token <scm> MARKUP_HEAD_SCM0_SCM1_SCM2
355 %token <scm> MARKUP_IDENTIFIER MARKUP_HEAD_LIST0
356 %token <scm> MUSIC_FUNCTION
357 %token <scm> MUSIC_FUNCTION_MUSIC
358 %token <scm> MUSIC_FUNCTION_MUSIC_MUSIC
359 %token <scm> MUSIC_FUNCTION_SCM
360 %token <scm> MUSIC_FUNCTION_SCM_SCM
361 %token <scm> MUSIC_FUNCTION_SCM_MUSIC
362 %token <scm> MUSIC_FUNCTION_SCM_MUSIC_MUSIC
363 %token <scm> MUSIC_FUNCTION_SCM_SCM_MUSIC
368 %type <book> book_block book_body
369 %type <i> bare_int bare_unsigned
370 %type <i> exclamations questions dots optional_rest
372 %type <i> sub_quotes sup_quotes
373 %type <i> tremolo_type
376 %type <music> Composite_music Simple_music Prefix_composite_music Generic_prefix_music
377 %type <music> Grouped_music_list
378 %type <music> Music Sequential_music Simultaneous_music
379 %type <music> Repeated_music
380 %type <music> command_req
381 %type <music> gen_text_def direction_less_event direction_reqd_event
382 %type <music> music_property_def context_change
383 %type <music> note_chord_element chord_body chord_body_element
384 %type <music> open_event close_event
385 %type <music> post_event tagged_post_event
386 %type <music> relative_music re_rhythmed_music
387 %type <music> simple_element event_chord command_element
388 %type <music> string_number_event
389 %type <music> toplevel_music
390 %type <music> tempo_event
392 %type <outputdef> output_def_body output_def_head
393 %type <outputdef> output_def book_paper_block
395 %type <scm> Music_list
396 %type <scm> chord_body_elements
397 %type <scm> chord_item chord_items chord_separator new_chord
398 %type <scm> context_def_spec_block context_def_spec_body
399 %type <scm> context_mod context_def_mod optional_context_mod
400 %type <scm> context_prop_spec
401 %type <scm> duration_length fraction
402 %type <scm> embedded_scm scalar
403 %type <scm> identifier_init
404 %type <scm> lilypond_header lilypond_header_body
405 %type <scm> new_lyrics
406 %type <scm> post_events
407 %type <scm> property_operation
408 %type <scm> script_abbreviation
409 %type <scm> simple_string
410 %type <scm> steno_pitch pitch absolute_pitch pitch_also_in_chords
411 %type <scm> steno_tonic_pitch
412 %type <scm> step_number step_numbers
413 %type <scm> string bare_number number_expression number_term number_factor
414 %type <scm> bass_number br_bass_figure bass_figure figure_list figure_spec
415 %type <scm> context_mod_list
416 %type <scm> octave_check
417 %type <scm> steno_duration optional_notemode_duration multiplied_duration
418 %type <scm> Generic_prefix_music_scm
419 %type <scm> lyric_element
420 %type <scm> Alternative_music
421 %type <scm> markup markup_line markup_list markup_list_body full_markup
423 %type <score> score_block score_body
428 /* We don't assign precedence to / and *, because we might need varied
429 prec levels in different prods */
435 lilypond: /* empty */
436 | lilypond toplevel_expression {
438 | lilypond assignment {
441 THIS->error_level_ = 1;
444 THIS->error_level_ = 1;
450 THIS->lexer_->set_identifier (ly_symbol2scm ("$globalheader"), $1);
457 SCM proc = THIS->lexer_->lookup_identifier ("toplevel-book-handler");
458 scm_call_2 (proc, THIS->self_scm (), book->self_scm ());
459 scm_gc_unprotect_object (book->self_scm ());
464 SCM proc = THIS->lexer_->lookup_identifier ("toplevel-score-handler");
465 scm_call_2 (proc, THIS->self_scm (), score->self_scm ());
466 scm_gc_unprotect_object (score->self_scm ());
470 SCM proc = THIS->lexer_->lookup_identifier ("toplevel-music-handler");
471 scm_call_2 (proc, THIS->self_scm (), music->self_scm ());
472 scm_gc_unprotect_object (music->self_scm ());
476 Output_def * od = $1;
478 if ($1->c_variable ("is-paper") == SCM_BOOL_T)
479 id = ly_symbol2scm ("$defaultpaper");
480 else if ($1->c_variable ("is-midi") == SCM_BOOL_T)
481 id = ly_symbol2scm ("$defaultmidi");
482 else if ($1->c_variable ("is-bookpaper") == SCM_BOOL_T)
483 id = ly_symbol2scm ("$defaultbookpaper");
485 THIS->lexer_->set_identifier (id, od->self_scm ());
486 scm_gc_unprotect_object (od->self_scm ());
501 lilypond_header_body:
503 $$ = ly_make_anonymous_module (safe_global_b);
504 THIS->lexer_->add_scope ($$);
506 | lilypond_header_body assignment {
512 HEADER '{' lilypond_header_body '}' {
513 $$ = THIS->lexer_->remove_scope ();
525 /* cont */ '=' identifier_init {
528 Should find generic way of associating input with objects.
530 Input ip = THIS->pop_spot ();
532 if (! is_regular_identifier ($1))
534 ip.warning (_ ("Identifier should have alphabetic characters only"));
537 THIS->lexer_->set_identifier ($1, $4);
540 TODO: devise standard for protection in parser.
542 The parser stack lives on the C-stack, which means that
543 all objects can be unprotected as soon as they're here.
553 $$ = $1->self_scm ();
554 scm_gc_unprotect_object ($$);
557 $$ = $1->self_scm ();
558 scm_gc_unprotect_object ($$);
560 | context_def_spec_block {
564 $$ = $1->self_scm ();
565 scm_gc_unprotect_object ($$);
568 $$ = $1->self_scm ();
569 scm_gc_unprotect_object ($$);
571 | number_expression {
584 $$ = scm_int2num ($1);
588 context_def_spec_block:
589 CONTEXT '{' context_def_spec_body '}'
595 context_def_spec_body:
597 $$ = Context_def::make_scm ();
598 unsmob_context_def ($$)->set_spot (THIS->here_input ());
600 | CONTEXT_DEF_IDENTIFIER {
602 unsmob_context_def ($$)->set_spot (THIS->here_input ());
604 | context_def_spec_body GROBDESCRIPTIONS embedded_scm {
605 Context_def*td = unsmob_context_def ($$);
607 for (SCM p = $3; ly_c_pair_p (p); p = ly_cdr (p)) {
608 SCM tag = ly_caar (p);
610 /* TODO: should make new tag "grob-definition" ? */
611 td->add_context_mod (scm_list_3 (ly_symbol2scm ("assign"),
612 tag, scm_cons (ly_cdar (p), SCM_EOL)));
615 | context_def_spec_body context_mod {
616 unsmob_context_def ($$)->add_context_mod ($2);
626 /*cont*/ '{' book_body '}' {
633 * Use 'handlers' like for toplevel-* stuff?
634 * grok \paper and \midi? */
638 $$->set_spot (THIS->here_input ());
639 $$->bookpaper_ = dynamic_cast<Output_def*> (unsmob_output_def (THIS->lexer_->lookup_identifier ("$defaultbookpaper"))->clone ());
640 scm_gc_unprotect_object ($$->bookpaper_->self_scm ());
641 $$->header_ = THIS->lexer_->lookup_identifier ("$globalheader");
643 | book_body book_paper_block {
645 scm_gc_unprotect_object ($2->self_scm ());
647 | book_body score_block {
649 $$->scores_.push (score);
650 scm_gc_unprotect_object (score->self_scm ());
652 | book_body lilypond_header {
664 /*cont*/ '{' score_body '}' {
674 $$->set_spot (THIS->here_input ());
677 $$ = new Score ( *unsmob_score ($1));
678 $$->set_spot (THIS->here_input ());
681 SCM m = $2->self_scm ();
682 scm_gc_unprotect_object (m);
683 $$->set_music (m, THIS->self_scm ());
685 | score_body lilypond_header {
688 | score_body output_def {
690 scm_gc_unprotect_object ($2->self_scm ());
705 if ($$->lookup_variable (ly_symbol2scm ("is-bookpaper")) != SCM_BOOL_T)
707 THIS->parser_error (_("Need \\bookpaper for bookpaper block."));
708 $$ = get_bookpaper (THIS);
715 output_def_body '}' {
718 THIS->lexer_->remove_scope ();
720 THIS->lexer_->remove_scope ();
721 THIS->lexer_->pop_state ();
727 $$ = get_bookpaper (THIS);
728 $$->input_origin_ = THIS->here_input ();
729 THIS->lexer_->add_scope ($$->scope_);
732 Output_def *p = get_midi (THIS);
734 THIS->lexer_->add_scope (p->scope_);
737 Output_def *p = get_paper (THIS);
740 THIS->lexer_->add_scope (p->parent_->scope_);
742 THIS->lexer_->add_scope (p->scope_);
749 output_def_head '{' {
751 $$->input_origin_.set_spot (THIS->here_input ());
752 THIS->lexer_->push_initial_state ();
754 | output_def_head '{' OUTPUT_DEF_IDENTIFIER {
755 scm_gc_unprotect_object ($1->self_scm ());
756 Output_def *o = unsmob_output_def ($3);
757 o->input_origin_.set_spot (THIS->here_input ());
759 THIS->lexer_->remove_scope ();
760 THIS->lexer_->add_scope (o->scope_);
761 THIS->lexer_->push_initial_state ();
763 | output_def_body assignment {
766 | output_def_body context_def_spec_block {
767 assign_context_def ($$, $2);
769 | output_def_body tempo_event {
771 junk this ? there already is tempo stuff in
774 int m = scm_to_int ($2->get_property ("metronome-count"));
775 Duration *d = unsmob_duration ($2->get_property ("tempo-unit"));
776 set_tempo ($$, d->get_length (), m);
777 scm_gc_unprotect_object ($2->self_scm ());
779 | output_def_body error {
785 TEMPO steno_duration '=' bare_unsigned {
786 $$ = MY_MAKE_MUSIC ("MetronomeChangeEvent");
787 $$->set_property ("tempo-unit", $2);
788 $$->set_property ("metronome-count", scm_int2num ( $4));
793 The representation of a list is the
797 to have efficient append.
801 $$ = scm_cons (SCM_EOL, SCM_EOL);
805 SCM c = scm_cons ($2->self_scm (), SCM_EOL);
806 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
807 if (ly_c_pair_p (ly_cdr (s)))
808 scm_set_cdr_x (ly_cdr (s), c); /* append */
810 scm_set_car_x (s, c); /* set first cons */
811 scm_set_cdr_x (s, c); /* remember last cell */
813 | Music_list embedded_scm {
829 | ALTERNATIVE '{' Music_list '}' {
836 REPEAT simple_string bare_unsigned Music Alternative_music
840 SCM alts = ly_c_pair_p ($5) ? ly_car ($5) : SCM_EOL;
841 if (times < scm_ilength (alts)) {
842 unsmob_music (ly_car (alts))
843 ->origin ()->warning (
844 _ ("More alternatives than repeats. Junking excess alternatives."));
845 alts = ly_truncate_list (times, alts);
849 SCM proc = ly_scheme_function ("make-repeated-music");
851 SCM mus = scm_call_1 (proc, $2);
852 scm_gc_protect_object (mus); // UGH.
853 Music *r = unsmob_music (mus);
856 r-> set_property ("element", beg->self_scm ());
857 scm_gc_unprotect_object (beg->self_scm ());
859 r->set_property ("repeat-count", scm_int2num (times >? 1));
861 r-> set_property ("elements",alts);
862 if (ly_c_equal_p ($2, scm_makfrom0str ("tremolo"))) {
864 TODO: move this code to Scheme.
868 we can not get durations and other stuff correct down the line, so we have to
869 add to the duration log here.
871 SCM func = ly_scheme_function ("shift-duration-log");
873 int dots = ($3 % 3) ? 0 : 1;
874 int shift = -intlog2 ((dots) ? ($3*2/3) : $3);
876 Sequential_music *seq = dynamic_cast<Sequential_music*> ($4);
879 int list_len = scm_ilength (seq->music_list ());
881 seq->origin ()->warning ("Chord tremolo must have 2 elements.");
883 r->compress (Moment (Rational (1, list_len)));
885 scm_call_3 (func, r->self_scm (), scm_int2num (shift),scm_int2num (dots));
888 r->set_spot (*$4->origin ());
895 SEQUENTIAL '{' Music_list '}' {
896 $$ = MY_MAKE_MUSIC ("SequentialMusic");
897 $$->set_property ("elements", ly_car ($3));
898 $$->set_spot (THIS->here_input ());
900 | '{' Music_list '}' {
901 $$ = MY_MAKE_MUSIC ("SequentialMusic");
902 $$->set_property ("elements", ly_car ($2));
903 $$->set_spot (THIS->here_input ());
908 SIMULTANEOUS '{' Music_list '}'{
909 $$ = MY_MAKE_MUSIC ("SimultaneousMusic");
910 $$->set_property ("elements", ly_car ($3));
911 $$->set_spot (THIS->here_input ());
914 | simul_open Music_list simul_close {
915 $$ = MY_MAKE_MUSIC ("SimultaneousMusic");
916 $$->set_property ("elements", ly_car ($2));
917 $$->set_spot (THIS->here_input ());
922 event_chord { $$ = $1; }
924 $$ = unsmob_music ($1);
931 optional_context_mod:
932 /**/ { $$ = SCM_EOL; }
933 | WITH { THIS->lexer_->push_initial_state (); }
934 '{' context_mod_list '}'
936 THIS->lexer_->pop_state ();
942 /* */ { $$ = SCM_EOL; }
943 | context_mod_list context_mod {
944 $$ = scm_cons ($2, $1);
950 Prefix_composite_music { $$ = $1; }
951 | Grouped_music_list { $$ = $1; }
955 Simultaneous_music { $$ = $1; }
956 | Sequential_music { $$ = $1; }
959 Generic_prefix_music_scm:
961 $$ = scm_list_2 ($1, make_input (THIS->here_input ()));
963 | MUSIC_FUNCTION_SCM {
966 $$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3);
968 | MUSIC_FUNCTION_MUSIC {
971 $$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3->self_scm ());
972 scm_gc_unprotect_object ($3->self_scm ());
974 | MUSIC_FUNCTION_SCM_MUSIC {
976 } embedded_scm Music {
977 $$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3, $4->self_scm ());
978 scm_gc_unprotect_object ($4->self_scm ());
980 | MUSIC_FUNCTION_SCM_SCM {
982 } embedded_scm embedded_scm {
983 $$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3, $4);
985 | MUSIC_FUNCTION_MUSIC_MUSIC {
988 $$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3->self_scm (), $4->self_scm ());
989 scm_gc_unprotect_object ($3->self_scm ());
990 scm_gc_unprotect_object ($4->self_scm ());
992 | MUSIC_FUNCTION_SCM_MUSIC_MUSIC {
994 } embedded_scm Music Music {
995 $$ = scm_list_5 ($1, make_input (THIS->pop_spot ()),
996 $3, $4->self_scm (), $5->self_scm ());
997 scm_gc_unprotect_object ($5->self_scm ());
998 scm_gc_unprotect_object ($4->self_scm ());
1002 Generic_prefix_music:
1003 Generic_prefix_music_scm {
1004 SCM func = ly_car ($1);
1005 Input *loc = unsmob_input (ly_cadr ($1));
1006 SCM args = ly_cddr ($1);
1007 SCM sig = scm_object_property (func, ly_symbol2scm ("music-function-signature"));
1010 for (SCM s = sig, t = args;
1011 ok && ly_c_pair_p (s) && ly_c_pair_p (t);
1012 s = ly_cdr (s), t = ly_cdr (t)) {
1014 if (scm_call_1 (ly_car (s), ly_car (t)) != SCM_BOOL_T)
1016 loc->error (_f ("Argument %d failed typecheck", k));
1017 THIS->error_level_ = 1;
1023 m = scm_apply_0 (func, ly_cdr ($1));
1024 if (unsmob_music (m))
1026 $$ = unsmob_music (m);
1027 scm_gc_protect_object (m);
1032 loc->error (_ ("Music head function should return Music object."));
1033 $$ = MY_MAKE_MUSIC ("Music");
1035 $$->set_spot (*loc);
1040 Prefix_composite_music:
1041 Generic_prefix_music {
1044 | CONTEXT simple_string '=' simple_string optional_context_mod Music {
1045 $$ = context_spec_music ($2, $4, $6, $5);
1048 | CONTEXT simple_string optional_context_mod Music {
1049 $$ = context_spec_music ($2, SCM_UNDEFINED, $4, $3);
1051 | NEWCONTEXT simple_string optional_context_mod Music {
1052 $$ = context_spec_music ($2, get_next_unique_context (), $4,
1063 int n = scm_to_int (ly_car ($3)); int d = scm_to_int (ly_cdr ($3));
1066 $$= MY_MAKE_MUSIC ("TimeScaledMusic");
1067 $$->set_spot (THIS->pop_spot ());
1069 $$->set_property ("element", mp->self_scm ());
1070 scm_gc_unprotect_object (mp->self_scm ());
1071 $$->set_property ("numerator", scm_int2num (n));
1072 $$->set_property ("denominator", scm_int2num (d));
1073 $$->compress (Moment (Rational (n,d)));
1076 | Repeated_music { $$ = $1; }
1077 | TRANSPOSE pitch_also_in_chords pitch_also_in_chords Music {
1078 $$ = MY_MAKE_MUSIC ("TransposedMusic");
1080 Pitch from = *unsmob_pitch ($2);
1081 Pitch to = *unsmob_pitch ($3);
1083 p->transpose (interval (from, to));
1084 $$->set_property ("element", p->self_scm ());
1085 scm_gc_unprotect_object (p->self_scm ());
1089 SCM nn = THIS->lexer_->lookup_identifier ("pitchnames");
1090 THIS->lexer_->push_note_state (alist_to_hashq (nn));
1094 THIS->lexer_->pop_state ();
1098 SCM nn = THIS->lexer_->lookup_identifier ("drumPitchNames");
1099 THIS->lexer_->push_note_state (alist_to_hashq (nn));
1103 THIS->lexer_->pop_state ();
1106 { THIS->lexer_->push_figuredbass_state (); }
1109 Music *chm = MY_MAKE_MUSIC ("UntransposableMusic");
1110 chm->set_property ("element", $3->self_scm ());
1112 scm_gc_unprotect_object ($3->self_scm ());
1114 THIS->lexer_->pop_state ();
1117 SCM nn = THIS->lexer_->lookup_identifier ("chordmodifiers");
1118 THIS->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
1119 nn = THIS->lexer_->lookup_identifier ("pitchnames");
1120 THIS->lexer_->push_chord_state (alist_to_hashq (nn));
1125 Music *chm = MY_MAKE_MUSIC ("UnrelativableMusic");
1126 chm->set_property ("element", $3->self_scm ());
1127 scm_gc_unprotect_object ($3->self_scm ());
1130 THIS->lexer_->pop_state ();
1133 { THIS->lexer_->push_lyric_state (); }
1137 THIS->lexer_->pop_state ();
1139 | relative_music { $$ = $1; }
1140 | re_rhythmed_music { $$ = $1; }
1141 | TAG embedded_scm Music {
1142 tag_music ($3, $2, THIS->here_input ());
1148 RELATIVE absolute_pitch Music {
1150 Pitch start = *unsmob_pitch ($2);
1151 $$ = make_music_relative (start, m);
1152 scm_gc_unprotect_object (m->self_scm ());
1154 | RELATIVE Composite_music {
1157 Pitch middle_c (0, 0, 0);
1158 $$ = make_music_relative (middle_c, m);
1159 scm_gc_unprotect_object (m->self_scm ());
1164 ADDLYRICS { THIS->lexer_->push_lyric_state (); }
1166 Grouped_music_list {
1167 /* Can also use Music at the expensive of two S/Rs similar to
1168 \repeat \alternative */
1169 THIS->lexer_->pop_state ();
1171 Music *music = MY_MAKE_MUSIC ("SimultaneousMusic");
1172 music->set_property ("elements", scm_list_1 ($3->self_scm ()));
1175 $$ = scm_cons ($3->self_scm (), SCM_EOL);
1178 | new_lyrics ADDLYRICS { THIS->lexer_->push_lyric_state (); }
1179 Grouped_music_list {
1180 THIS->lexer_->pop_state ();
1181 $$ = scm_cons ($4->self_scm (), $1);
1186 Grouped_music_list new_lyrics {
1188 /* FIXME: should find out uniqueXXX name from music */
1189 SCM name = $1->get_property ("context-id");
1190 //if (name == SCM_EOL)
1191 if (!scm_is_string (name))
1192 name = scm_makfrom0str ("");
1194 SCM context = scm_makfrom0str ("Lyrics");
1195 Music *all = MY_MAKE_MUSIC ("SimultaneousMusic");
1198 for (SCM s = $2; ly_c_pair_p (s); s = ly_cdr (s))
1200 Music *music = unsmob_music (ly_car (s));
1201 Music *com = make_lyric_combine_music (name, music);
1202 Music *csm = context_spec_music (context,
1203 get_next_unique_context (), com, SCM_EOL);
1204 lst = scm_cons (csm->self_scm (), lst);
1206 /* FIXME: only first lyric music is accepted,
1207 the rest is junked */
1208 all->set_property ("elements", scm_cons ($1->self_scm (),
1211 scm_gc_unprotect_object ($1->self_scm ());
1214 THIS->lexer_->push_lyric_state ();
1215 } simple_string Music {
1216 THIS->lexer_->pop_state ();
1219 $$ = make_lyric_combine_music (name, music);
1220 scm_gc_unprotect_object (music->self_scm ());
1225 CHANGE STRING '=' STRING {
1226 Music*t= MY_MAKE_MUSIC ("ContextChange");
1227 t-> set_property ("change-to-type", scm_string_to_symbol ($2));
1228 t-> set_property ("change-to-id", $4);
1231 $$->set_spot (THIS->here_input ());
1237 $$ = scm_list_3 (ly_symbol2scm ("assign"),
1238 scm_string_to_symbol ($1), $3);
1240 | UNSET simple_string {
1241 $$ = scm_list_2 (ly_symbol2scm ("unset"),
1242 scm_string_to_symbol ($2));
1244 | OVERRIDE simple_string embedded_scm '=' embedded_scm {
1245 $$ = scm_list_4 (ly_symbol2scm ("push"),
1246 scm_string_to_symbol ($2), $3, $5);
1248 | REVERT simple_string embedded_scm {
1249 $$ = scm_list_3 (ly_symbol2scm ("pop"),
1250 scm_string_to_symbol ($2), $3);
1255 CONSISTS { $$ = ly_symbol2scm ("consists"); }
1256 | REMOVE { $$ = ly_symbol2scm ("remove"); }
1258 | ACCEPTS { $$ = ly_symbol2scm ("accepts"); }
1259 | DENIES { $$ = ly_symbol2scm ("denies"); }
1261 | ALIAS { $$ = ly_symbol2scm ("alias"); }
1262 | TYPE { $$ = ly_symbol2scm ("translator-type"); }
1263 | DESCRIPTION { $$ = ly_symbol2scm ("description"); }
1264 | NAME { $$ = ly_symbol2scm ("context-name"); }
1268 property_operation { $$ = $1; }
1269 | context_def_mod STRING {
1270 $$ = scm_list_2 ($1, $2);
1276 if (!is_regular_identifier ($1))
1278 THIS->here_input ().error (_("Grob name should be alphanumeric"));
1281 $$ = scm_list_2 (ly_symbol2scm ("Bottom"),
1282 scm_string_to_symbol ($1));
1284 | simple_string '.' simple_string {
1285 $$ = scm_list_2 (scm_string_to_symbol ($1),
1286 scm_string_to_symbol ($3));
1291 OVERRIDE context_prop_spec embedded_scm '=' scalar {
1292 $$ = property_op_to_music (scm_list_4 (
1293 ly_symbol2scm ("poppush"),
1296 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1298 | REVERT context_prop_spec embedded_scm {
1299 $$ = property_op_to_music (scm_list_3 (
1300 ly_symbol2scm ("pop"),
1304 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1306 | SET context_prop_spec '=' scalar {
1307 $$ = property_op_to_music (scm_list_3 (
1308 ly_symbol2scm ("assign"),
1311 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1313 | UNSET context_prop_spec {
1314 $$ = property_op_to_music (scm_list_2 (
1315 ly_symbol2scm ("unset"),
1317 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1319 | ONCE music_property_def {
1320 SCM e = $2->get_property ("element");
1321 unsmob_music (e)->set_property ("once", SCM_BOOL_T);
1332 | STRING_IDENTIFIER {
1335 | string '+' string {
1336 $$ = scm_string_append (scm_list_2 ($1, $3));
1340 simple_string: STRING {
1355 $$ = scm_int2num ($1);
1364 $$ = scm_int2num ($1);
1370 pre_events doesn't contain anything. It is a trick:
1372 Adding pre_events to the simple_element
1373 makes the choice between
1379 simple_element: STRING
1381 a single shift/reduction conflict.
1383 nevertheless, this is not very clean, and we should find a different
1393 pre_events simple_element post_events {
1394 SCM elts = $2-> get_property ("elements");
1396 elts = ly_append2 (elts, scm_reverse_x ($3, SCM_EOL));
1398 $2->set_property ("elements", elts);
1402 | note_chord_element
1407 chord_body optional_notemode_duration post_events
1409 SCM dur = unsmob_duration ($2)->smobbed_copy ();
1410 SCM es = $1->get_property ("elements");
1411 SCM postevs = scm_reverse_x ($3, SCM_EOL);
1413 for (SCM s = es; ly_c_pair_p (s); s = ly_cdr (s))
1414 unsmob_music (ly_car (s))->set_property ("duration", dur);
1415 es = ly_append2 (es, postevs);
1417 $1-> set_property ("elements", es);
1428 simul_open: DOUBLE_ANGLE_OPEN
1431 simul_close: DOUBLE_ANGLE_CLOSE
1435 chord_open chord_body_elements chord_close
1437 $$ = MY_MAKE_MUSIC ("EventChord");
1438 $$->set_property ("elements",
1439 scm_reverse_x ($2, SCM_EOL));
1443 chord_body_elements:
1444 /* empty */ { $$ = SCM_EOL; }
1445 | chord_body_elements chord_body_element {
1446 $$ = scm_cons ($2->self_scm (), $1);
1447 scm_gc_unprotect_object ($2->self_scm ());
1452 pitch exclamations questions octave_check post_events
1459 Music *n = MY_MAKE_MUSIC ("NoteEvent");
1460 n->set_property ("pitch", $1);
1462 n->set_property ("cautionary", SCM_BOOL_T);
1463 if (ex % 2 || q % 2)
1464 n->set_property ("force-accidental", SCM_BOOL_T);
1466 if (ly_c_pair_p (post)) {
1467 SCM arts = scm_reverse_x (post, SCM_EOL);
1468 n->set_property ("articulations", arts);
1470 if (scm_is_number (check))
1472 int q = scm_to_int (check);
1473 n->set_property ("absolute-octave", scm_int2num (q-1));
1479 | DRUM_PITCH post_events {
1480 Music *n = MY_MAKE_MUSIC ("NoteEvent");
1481 n->set_property ("duration", $2);
1482 n->set_property ("drum-type", $1);
1483 n->set_spot (THIS->here_input ());
1485 if (ly_c_pair_p ($2)) {
1486 SCM arts = scm_reverse_x ($2, SCM_EOL);
1487 n->set_property ("articulations", arts);
1494 ADDQUOTE string Music {
1495 SCM adder = ly_scheme_function ("add-quotable");
1497 scm_call_2 (adder, $2, $3->self_scm ());
1498 scm_gc_unprotect_object ($3->self_scm ());
1504 $$ = MY_MAKE_MUSIC ("EventChord");
1505 $$->set_property ("elements", scm_cons ($1->self_scm (), SCM_EOL));
1506 scm_gc_unprotect_object ($1->self_scm ());
1508 $$-> set_spot (THIS->here_input ());
1509 $1-> set_spot (THIS->here_input ());
1511 | SKIP duration_length {
1512 Music *skip = MY_MAKE_MUSIC ("SkipMusic");
1513 skip->set_property ("duration", $2);
1517 | QUOTE STRING duration_length {
1518 Music *quote = MY_MAKE_MUSIC ("QuoteMusic");
1519 quote->set_property ("duration", $3);
1520 quote->set_property ("quoted-music-name", $2);
1521 quote->set_spot (THIS->here_input ());
1525 | OCTAVE { THIS->push_spot (); }
1527 Music *m = MY_MAKE_MUSIC ("RelativeOctaveCheck");
1529 $$->set_spot (THIS->pop_spot ());
1530 $$->set_property ("pitch", $3);
1533 Music *m = MY_MAKE_MUSIC ("LigatureEvent");
1534 m->set_property ("span-direction", scm_int2num (START));
1535 m->set_spot (THIS->here_input ());
1537 $$ = MY_MAKE_MUSIC ("EventChord");
1538 $$->set_property ("elements", scm_cons (m->self_scm (), SCM_EOL));
1539 scm_gc_unprotect_object (m->self_scm ());
1540 $$->set_spot (THIS->here_input ());
1543 Music *m = MY_MAKE_MUSIC ("LigatureEvent");
1544 m->set_property ("span-direction", scm_int2num (STOP));
1545 m->set_spot (THIS->here_input ());
1547 $$ = MY_MAKE_MUSIC ("EventChord");
1548 $$->set_property ("elements", scm_cons (m->self_scm (), SCM_EOL));
1549 $$->set_spot (THIS->here_input ());
1550 scm_gc_unprotect_object (m->self_scm ());
1553 $$ = MY_MAKE_MUSIC ("VoiceSeparator");
1554 $$->set_spot (THIS->here_input ());
1557 SCM pipe =THIS->lexer_->lookup_identifier ("pipeSymbol");
1559 if (Music * m = unsmob_music (pipe))
1562 $$ = MY_MAKE_MUSIC ("BarCheck");
1564 $$->set_spot (THIS->here_input ());
1566 | TRANSPOSITION pitch {
1567 $$ = set_property_music (ly_symbol2scm ("instrumentTransposition"),
1569 $$->set_spot (THIS-> here_input ());
1570 $$ = context_spec_music (ly_symbol2scm ("Staff"), SCM_UNDEFINED,
1574 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1576 Music *csm = context_spec_music (ly_symbol2scm ("Timing"), SCM_UNDEFINED,
1578 $$ = context_spec_music (ly_symbol2scm ("Score"), SCM_UNDEFINED, csm, SCM_EOL);
1579 $$->set_spot (THIS->here_input ());
1580 t->set_spot (THIS->here_input ());
1582 | PARTIAL duration_length {
1583 Moment m = - unsmob_duration ($2)->get_length ();
1584 Music *p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1585 p->set_spot (THIS->here_input ());
1586 p = context_spec_music (ly_symbol2scm ("Timing"), SCM_UNDEFINED,
1588 p = context_spec_music (ly_symbol2scm ("Score"), SCM_UNDEFINED,
1593 SCM proc = ly_scheme_function ("make-clef-set");
1595 SCM result = scm_call_1 (proc, $2);
1596 scm_gc_protect_object (result);
1597 $$ = unsmob_music (result);
1600 SCM proc= ly_scheme_function ("make-time-signature-set");
1602 SCM result = scm_apply_2 (proc, ly_car ($2), ly_cdr ($2), SCM_EOL);
1603 scm_gc_protect_object (result);
1604 $$ = unsmob_music (result);
1607 SCM proc = ly_scheme_function ("make-mark-set");
1609 SCM result = scm_call_1 (proc, $2);
1610 scm_gc_protect_object (result);
1611 $$ = unsmob_music (result);
1617 $$ = MY_MAKE_MUSIC ("PesOrFlexaEvent");
1620 Music *m = MY_MAKE_MUSIC ("MarkEvent");
1627 Music *key= MY_MAKE_MUSIC ("KeyChangeEvent");
1630 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1632 Music *key= MY_MAKE_MUSIC ("KeyChangeEvent");
1633 if (scm_ilength ($3) > 0)
1635 key->set_property ("pitch-alist", $3);
1636 key->set_property ("tonic", Pitch (0,0,0).smobbed_copy ());
1637 ((Music*)key)->transpose (* unsmob_pitch ($2));
1639 THIS->parser_error (_ ("Second argument must be pitch list."));
1650 | post_events post_event {
1651 $2->set_spot (THIS->here_input ());
1652 $$ = scm_cons ($2->self_scm (), $$);
1653 scm_gc_unprotect_object ($2->self_scm ());
1655 | post_events tagged_post_event {
1656 $2 -> set_spot (THIS->here_input ());
1657 $$ = scm_cons ($2->self_scm (), $$);
1658 scm_gc_unprotect_object ($2->self_scm ());
1664 '-' TAG embedded_scm post_event {
1665 tag_music ($4, $3, THIS->here_input ());
1671 direction_less_event {
1675 if (!THIS->lexer_->is_lyric_state ())
1676 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1677 $$ = MY_MAKE_MUSIC ("HyphenEvent");
1680 if (!THIS->lexer_->is_lyric_state ())
1681 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1682 $$ = MY_MAKE_MUSIC ("ExtenderEvent");
1684 | script_dir direction_reqd_event {
1686 $2->set_property ("direction", scm_int2num ($1));
1689 | script_dir direction_less_event {
1691 $2->set_property ("direction", scm_int2num ($1));
1694 | string_number_event
1697 string_number_event:
1699 Music *s = MY_MAKE_MUSIC ("StringNumberEvent");
1700 s->set_property ("string-number", scm_int2num ($1));
1701 s->set_spot (THIS->here_input ());
1707 direction_less_event:
1713 TODO: should take all these defs out of the parser, adn make use
1717 (set-articulation '~ "trill")
1720 Music *m = MY_MAKE_MUSIC ("BeamEvent");
1721 m->set_spot (THIS->here_input ());
1722 m->set_property ("span-direction", scm_int2num (START));
1726 Music *m = MY_MAKE_MUSIC ("BeamEvent");
1727 m->set_spot (THIS->here_input ());
1728 m->set_property ("span-direction", scm_int2num (STOP));
1732 Music *m = MY_MAKE_MUSIC ("TieEvent");
1733 m->set_spot (THIS->here_input ());
1738 dynamic_cast<Music *> ($$)->set_property ("span-direction",
1739 scm_int2num (START));
1743 dynamic_cast<Music *> ($$)->set_property ("span-direction",
1744 scm_int2num (STOP));
1746 | EVENT_IDENTIFIER {
1747 $$ = unsmob_music ($1);
1750 Music *a = MY_MAKE_MUSIC ("TremoloEvent");
1751 a->set_spot (THIS->here_input ());
1752 a->set_property ("tremolo-type", scm_int2num ($1));
1757 direction_reqd_event:
1761 | script_abbreviation {
1762 SCM s = THIS->lexer_->lookup_identifier ("dash" + ly_scm2string ($1));
1763 Music *a = MY_MAKE_MUSIC ("ArticulationEvent");
1764 if (scm_is_string (s))
1765 a->set_property ("articulation-type", s);
1766 else THIS->parser_error (_ ("Expecting string as script definition"));
1772 /**/ { $$ = SCM_EOL; }
1773 | '=' { $$ = scm_int2num (0); }
1774 | '=' sub_quotes { $$ = scm_int2num ($2); }
1775 | '=' sup_quotes { $$ = scm_int2num ($2); }
1800 | NOTENAME_PITCH sup_quotes {
1801 Pitch p = *unsmob_pitch ($1);
1802 p = p.transposed (Pitch ($2,0,0));
1803 $$ = p.smobbed_copy ();
1805 | NOTENAME_PITCH sub_quotes {
1806 Pitch p =* unsmob_pitch ($1);
1807 p = p.transposed (Pitch (-$2,0,0));
1808 $$ = p.smobbed_copy ();
1820 | TONICNAME_PITCH sup_quotes {
1821 Pitch p = *unsmob_pitch ($1);
1822 p = p.transposed (Pitch ($2,0,0));
1823 $$ = p.smobbed_copy ();
1825 | TONICNAME_PITCH sub_quotes {
1826 Pitch p =* unsmob_pitch ($1);
1828 p = p.transposed (Pitch (-$2,0,0));
1829 $$ = p.smobbed_copy ();
1839 pitch_also_in_chords:
1846 Music *s = MY_MAKE_MUSIC ("SlurEvent");
1848 s->set_spot (THIS->here_input ());
1851 Music *s = MY_MAKE_MUSIC ("PhrasingSlurEvent");
1853 s->set_spot (THIS->here_input ());
1856 Music *s = MY_MAKE_MUSIC ("CrescendoEvent");
1858 s->set_spot (THIS->here_input ());
1861 Music *s = MY_MAKE_MUSIC ("DecrescendoEvent");
1863 s->set_spot (THIS->here_input ());
1870 Music *s = MY_MAKE_MUSIC ("CrescendoEvent");
1871 s->set_spot (THIS->here_input ());
1876 Music *s= MY_MAKE_MUSIC ("SlurEvent");
1878 s->set_spot (THIS->here_input ());
1882 Music *s= MY_MAKE_MUSIC ("PhrasingSlurEvent");
1884 s->set_property ("span-type",
1885 scm_makfrom0str ("phrasing-slur"));
1886 s->set_spot (THIS->here_input ());
1892 Music *t = MY_MAKE_MUSIC ("TextScriptEvent");
1893 t->set_property ("text", $1);
1894 t->set_spot (THIS->here_input ());
1898 Music *t = MY_MAKE_MUSIC ("TextScriptEvent");
1899 t->set_property ("text",
1900 make_simple_markup (THIS->lexer_->encoding (), $1));
1901 t->set_spot (THIS->here_input ());
1906 Music *t = MY_MAKE_MUSIC ("FingerEvent");
1907 t->set_property ("digit", scm_int2num ($1));
1908 t->set_spot (THIS->here_input ());
1913 script_abbreviation:
1915 $$ = scm_makfrom0str ("Hat");
1918 $$ = scm_makfrom0str ("Plus");
1921 $$ = scm_makfrom0str ("Dash");
1924 $$ = scm_makfrom0str ("Bar");
1927 $$ = scm_makfrom0str ("Larger");
1930 $$ = scm_makfrom0str ("Dot");
1933 $$ = scm_makfrom0str ("Underscore");
1940 | '-' { $$ = CENTER; }
1951 multiplied_duration {
1956 optional_notemode_duration:
1958 Duration dd = THIS->default_duration_;
1959 $$ = dd.smobbed_copy ();
1961 THIS->beam_check ($$);
1963 | multiplied_duration {
1965 THIS->default_duration_ = *unsmob_duration ($$);
1967 THIS->beam_check ($$);
1972 bare_unsigned dots {
1974 if (!is_duration ($1))
1975 THIS->parser_error (_f ("not a duration: %d", $1));
1979 $$ = Duration (len, $2).smobbed_copy ();
1981 | DURATION_IDENTIFIER dots {
1982 Duration *d = unsmob_duration ($1);
1983 Duration k (d->duration_log (), d->dot_count () + $2);
1989 multiplied_duration:
1993 | multiplied_duration '*' bare_unsigned {
1994 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1996 | multiplied_duration '*' FRACTION {
1997 Rational m (scm_to_int (ly_car ($3)), scm_to_int (ly_cdr ($3)));
1999 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
2004 FRACTION { $$ = $1; }
2005 | UNSIGNED '/' UNSIGNED {
2006 $$ = scm_cons (scm_int2num ($1), scm_int2num ($3));
2023 | ':' bare_unsigned {
2024 if (!is_duration ($2))
2025 THIS->parser_error (_f ("not a duration: %d", $2));
2032 $$ = scm_number_to_string (scm_int2num ($1), scm_int2num (10));
2033 $$ = scm_list_2 (ly_scheme_function ("number-markup"),
2037 $$ = scm_number_to_string (scm_int2num ($1), scm_int2num (10));
2038 $$ = scm_list_2 (ly_scheme_function ("number-markup"),
2041 | STRING { $$ = $1; }
2052 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent");
2053 $$ = bfr->self_scm ();
2054 scm_gc_unprotect_object ($$);
2057 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent");
2058 $$ = bfr->self_scm ();
2060 bfr->set_property ("figure", $1);
2062 scm_gc_unprotect_object ($$);
2064 | bass_figure bass_mod {
2065 Music *m = unsmob_music ($1);
2067 SCM salter = m->get_property ("alteration");
2068 int alter = scm_is_number (salter) ? scm_to_int (salter) : 0;
2069 m->set_property ("alteration",
2070 scm_int2num (alter + $2));
2072 m->set_property ("alteration", scm_int2num (0));
2080 unsmob_music ($$)->set_property ("bracket-start", SCM_BOOL_T);
2085 | br_bass_figure ']' {
2087 unsmob_music ($1)->set_property ("bracket-stop", SCM_BOOL_T);
2095 | figure_list br_bass_figure {
2096 $$ = scm_cons ($2, $1);
2101 FIGURE_OPEN figure_list FIGURE_CLOSE {
2102 Music *m = MY_MAKE_MUSIC ("EventChord");
2103 $2 = scm_reverse_x ($2, SCM_EOL);
2104 m->set_property ("elements", $2);
2105 $$ = m->self_scm ();
2116 pitch exclamations questions octave_check optional_notemode_duration optional_rest {
2118 Input i = THIS->pop_spot ();
2119 if (!THIS->lexer_->is_note_state ())
2120 THIS->parser_error (_ ("Have to be in Note mode for notes"));
2124 n = MY_MAKE_MUSIC ("RestEvent");
2126 n = MY_MAKE_MUSIC ("NoteEvent");
2128 n->set_property ("pitch", $1);
2129 n->set_property ("duration", $5);
2131 if (scm_is_number ($4))
2133 int q = scm_to_int ($4);
2134 n->set_property ("absolute-octave", scm_int2num (q-1));
2138 n->set_property ("cautionary", SCM_BOOL_T);
2139 if ($2 % 2 || $3 % 2)
2140 n->set_property ("force-accidental", SCM_BOOL_T);
2142 Music *v = MY_MAKE_MUSIC ("EventChord");
2143 v->set_property ("elements", scm_list_1 (n->self_scm ()));
2144 scm_gc_unprotect_object (n->self_scm ());
2150 | DRUM_PITCH optional_notemode_duration {
2151 Input i = THIS->pop_spot ();
2153 Music *n = MY_MAKE_MUSIC ("NoteEvent");
2154 n->set_property ("duration", $2);
2155 n->set_property ("drum-type", $1);
2157 Music *v = MY_MAKE_MUSIC ("EventChord");
2158 v->set_property ("elements", scm_list_1 (n->self_scm ()));
2159 scm_gc_unprotect_object (n->self_scm ());
2165 | figure_spec optional_notemode_duration {
2166 Music *m = unsmob_music ($1);
2167 Input i = THIS->pop_spot ();
2169 for (SCM s = m->get_property ("elements"); ly_c_pair_p (s); s = ly_cdr (s))
2171 unsmob_music (ly_car (s))->set_property ("duration", $2);
2175 | RESTNAME optional_notemode_duration {
2177 Input i = THIS->pop_spot ();
2179 if (ly_scm2string ($1) == "s") {
2181 ev = MY_MAKE_MUSIC ("SkipEvent");
2184 ev = MY_MAKE_MUSIC ("RestEvent");
2187 ev->set_property ("duration", $2);
2189 Music *velt = MY_MAKE_MUSIC ("EventChord");
2190 velt->set_property ("elements", scm_list_1 (ev->self_scm ()));
2193 scm_gc_unprotect_object (ev->self_scm ());
2197 | MULTI_MEASURE_REST optional_notemode_duration {
2200 SCM proc = ly_scheme_function ("make-multi-measure-rest");
2201 SCM mus = scm_call_2 (proc, $2,
2202 make_input (THIS->here_input ()));
2203 scm_gc_protect_object (mus);
2204 $$ = unsmob_music (mus);
2207 | lyric_element optional_notemode_duration {
2208 Input i = THIS->pop_spot ();
2209 if (!THIS->lexer_->is_lyric_state ())
2210 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
2212 Music *lreq = MY_MAKE_MUSIC ("LyricEvent");
2213 lreq->set_property ("text", $1);
2214 lreq->set_property ("duration",$2);
2216 Music *velt = MY_MAKE_MUSIC ("EventChord");
2217 velt->set_property ("elements", scm_list_1 (lreq->self_scm ()));
2224 if (!THIS->lexer_->is_chord_state ())
2225 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
2226 $$ = unsmob_music ($1);
2231 /* FIXME: lyric flavoured markup would be better */
2236 $$ = make_simple_markup (THIS->lexer_->encoding (), $1);
2241 steno_tonic_pitch optional_notemode_duration {
2242 $$ = make_chord ($1, $2, SCM_EOL);
2244 | steno_tonic_pitch optional_notemode_duration chord_separator chord_items {
2245 SCM its = scm_reverse_x ($4, SCM_EOL);
2246 $$ = make_chord ($1, $2, scm_cons ($3, its));
2254 | chord_items chord_item {
2255 $$ = scm_cons ($2, $$);
2261 $$ = ly_symbol2scm ("chord-colon");
2264 $$ = ly_symbol2scm ("chord-caret");
2266 | CHORD_SLASH steno_tonic_pitch {
2267 $$ = scm_list_2 (ly_symbol2scm ("chord-slash"), $2);
2269 | CHORD_BASS steno_tonic_pitch {
2270 $$ = scm_list_2 (ly_symbol2scm ("chord-bass"), $2);
2279 $$ = scm_reverse_x ($1, SCM_EOL);
2287 step_number { $$ = scm_cons ($1, SCM_EOL); }
2288 | step_numbers '.' step_number {
2289 $$ = scm_cons ($3, $$);
2295 $$ = make_chord_step ($1, 0);
2297 | bare_unsigned '+' {
2298 $$ = make_chord_step ($1, SHARP);
2300 | bare_unsigned CHORD_MINUS {
2301 $$ = make_chord_step ($1, FLAT);
2308 TODO: should deprecate in favor of Scheme?
2312 number_expression '+' number_term {
2313 $$ = scm_sum ($1, $3);
2315 | number_expression '-' number_term {
2316 $$ = scm_difference ($1, $3);
2325 | number_factor '*' number_factor {
2326 $$ = scm_product ($1, $3);
2328 | number_factor '/' number_factor {
2329 $$ = scm_divide ($1, $3);
2334 '-' number_factor { /* %prec UNARY_MINUS */
2335 $$ = scm_difference ($2, SCM_UNDEFINED);
2343 $$ = scm_int2num ($1);
2348 | NUMBER_IDENTIFIER {
2351 | REAL NUMBER_IDENTIFIER {
2352 $$ = scm_make_real (scm_to_double ($1) *scm_to_double ($2));
2354 | UNSIGNED NUMBER_IDENTIFIER {
2355 $$ = scm_make_real ($1 *scm_to_double ($2));
2371 if (scm_integer_p ($1) == SCM_BOOL_T)
2373 int k = scm_to_int ($1);
2377 THIS->parser_error (_ ("need integer number arg"));
2388 | exclamations '!' { $$ ++; }
2393 | questions '?' { $$ ++; }
2403 { THIS->lexer_->push_markup_state (); }
2406 THIS->lexer_->pop_state ();
2412 This should be done more dynamically if possible.
2416 $$ = make_simple_markup (THIS->lexer_->encoding (), $1);
2418 | MARKUP_HEAD_EMPTY {
2419 $$ = scm_list_1 ($1);
2421 | MARKUP_HEAD_MARKUP0 markup {
2422 $$ = scm_list_2 ($1, $2);
2424 | MARKUP_HEAD_MARKUP0_MARKUP1 markup markup {
2425 $$ = scm_list_3 ($1, $2, $3);
2427 | MARKUP_HEAD_SCM0_MARKUP1 SCM_T markup {
2428 $$ = scm_list_3 ($1, $2, $3);
2433 | MARKUP_HEAD_LIST0 markup_list {
2434 $$ = scm_list_2 ($1,$2);
2436 | MARKUP_HEAD_SCM0 embedded_scm {
2437 $$ = scm_list_2 ($1, $2);
2439 | MARKUP_HEAD_SCM0_SCM1_MARKUP2 embedded_scm embedded_scm markup {
2440 $$ = scm_list_4 ($1, $2, $3, $4);
2442 | MARKUP_HEAD_SCM0_SCM1_SCM2 embedded_scm embedded_scm embedded_scm {
2443 $$ = scm_list_4 ($1, $2, $3, $4);
2445 | MARKUP_HEAD_SCM0_SCM1 embedded_scm embedded_scm {
2446 $$ = scm_list_3 ($1, $2, $3);
2448 | MARKUP_IDENTIFIER {
2451 | STRING_IDENTIFIER {
2455 SCM nn = THIS->lexer_->lookup_identifier ("pitchnames");
2456 THIS->lexer_->push_note_state (alist_to_hashq (nn));
2457 } '{' score_body '}' {
2459 $$ = scm_list_2 (ly_scheme_function ("score-markup"), sc->self_scm ());
2460 scm_gc_unprotect_object (sc->self_scm ());
2461 THIS->lexer_->pop_state ();
2466 chord_open markup_list_body chord_close { $$ = scm_reverse_x ($2, SCM_EOL); }
2470 '{' markup_list_body '}' {
2471 SCM line = ly_scheme_function ("line-markup");
2473 $$ = scm_list_2 (line, scm_reverse_x ($2, SCM_EOL));
2478 /**/ { $$ = SCM_EOL; }
2479 | markup_list_body markup {
2480 $$ = scm_cons ($2, $1);
2488 Lily_parser::set_yydebug (bool )
2496 Lily_parser::do_yyparse ()
2498 yyparse ((void*)this);
2503 Should make this optional? It will also complain when you do
2507 which is entirely legitimate.
2509 Or we can scrap it. Barchecks should detect wrong durations, and
2510 skipTypesetting speeds it up a lot.
2514 Lily_parser::beam_check (SCM dur)
2516 Duration *d = unsmob_duration (dur);
2517 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2519 Music *m = unsmob_music (last_beam_start_);
2520 m->origin ()->warning (_ ("Suspect duration found following this beam"));
2522 last_beam_start_ = SCM_EOL;
2530 It is a little strange to have this function in this file, but
2531 otherwise, we have to import music classes into the lexer.
2535 Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
2537 if (scm_is_string (sid)) {
2539 return STRING_IDENTIFIER;
2540 } else if (scm_is_number (sid)) {
2542 return NUMBER_IDENTIFIER;
2543 } else if (unsmob_context_def (sid)) {
2544 *destination = unsmob_context_def (sid)->clone_scm ();
2545 return CONTEXT_DEF_IDENTIFIER;
2546 } else if (unsmob_score (sid)) {
2547 Score *score = new Score (*unsmob_score (sid));
2548 *destination = score->self_scm ();
2549 return SCORE_IDENTIFIER;
2550 } else if (Music *mus = unsmob_music (sid)) {
2551 mus = mus->clone ();
2552 *destination = mus->self_scm ();
2553 unsmob_music (*destination)->
2554 set_property ("origin", make_input (last_input_));
2555 return dynamic_cast<Event*> (mus)
2556 ? EVENT_IDENTIFIER : MUSIC_IDENTIFIER;
2557 } else if (unsmob_duration (sid)) {
2558 *destination = unsmob_duration (sid)->smobbed_copy ();
2559 return DURATION_IDENTIFIER;
2560 } else if (unsmob_output_def (sid)) {
2561 Output_def *p = unsmob_output_def (sid);
2564 *destination = p->self_scm ();
2565 return OUTPUT_DEF_IDENTIFIER;
2566 } else if (Text_item::markup_p (sid)) {
2568 return MARKUP_IDENTIFIER;
2575 property_op_to_music (SCM op)
2578 SCM tag = ly_car (op);
2579 SCM symbol = ly_cadr (op);
2580 SCM args = ly_cddr (op);
2581 SCM grob_val = SCM_UNDEFINED;
2582 SCM grob_sym = SCM_UNDEFINED;
2583 SCM val = SCM_UNDEFINED;
2585 if (tag == ly_symbol2scm ("assign"))
2587 m = MY_MAKE_MUSIC ("PropertySet");
2588 val = ly_car (args);
2590 else if (tag == ly_symbol2scm ("unset"))
2591 m = MY_MAKE_MUSIC ("PropertyUnset");
2592 else if (tag == ly_symbol2scm ("poppush")
2593 || tag == ly_symbol2scm ("push"))
2595 m = MY_MAKE_MUSIC ("OverrideProperty");
2596 grob_sym = ly_car (args);
2597 grob_val = ly_cadr (args);
2599 else if (tag == ly_symbol2scm ("pop")) {
2600 m = MY_MAKE_MUSIC ("RevertProperty");
2601 grob_sym = ly_car (args);
2604 m->set_property ("symbol", symbol);
2606 if (val != SCM_UNDEFINED)
2607 m->set_property ("value", val);
2608 if (grob_val != SCM_UNDEFINED)
2609 m->set_property ("grob-value", grob_val);
2611 if (grob_sym != SCM_UNDEFINED)
2613 bool itc = internal_type_checking_global_b;
2616 bool autobeam = ly_c_equal_p (symbol, ly_symbol2scm ("autoBeamSettings"));
2618 internal_type_checking_global_b = false;
2619 m->set_property ("grob-property", grob_sym);
2621 internal_type_checking_global_b = itc;
2624 if (tag == ly_symbol2scm ("poppush"))
2625 m->set_property ("pop-first", SCM_BOOL_T);
2632 context_spec_music (SCM type, SCM id, Music *m, SCM ops)
2634 Music *csm = MY_MAKE_MUSIC ("ContextSpeccedMusic");
2636 csm->set_property ("element", m->self_scm ());
2637 scm_gc_unprotect_object (m->self_scm ());
2639 csm->set_property ("context-type",
2640 scm_is_symbol (type) ? type : scm_string_to_symbol (type));
2641 csm->set_property ("property-operations", ops);
2643 if (scm_is_string (id))
2644 csm->set_property ("context-id", id);
2649 get_next_unique_context ()
2651 static int new_context_count;
2653 snprintf (s, 1024, "uniqueContext%d", new_context_count++);
2654 return scm_makfrom0str (s);