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?
29 #include "book-paper-def.hh"
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"
40 #include "midi-def.hh"
42 #include "music-list.hh"
43 #include "music-sequence.hh"
44 #include "my-lily-lexer.hh"
45 #include "my-lily-parser.hh"
46 #include "paper-book.hh"
47 #include "paper-def.hh"
48 #include "scm-hash.hh"
49 #include "scm-option.hh"
51 #include "text-item.hh"
54 #define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x))
56 Music *property_op_to_music (SCM op);
57 Music *context_spec_music (SCM type, SCM id, Music *m, SCM ops_);
58 SCM get_next_unique_context ();
60 #define YYERROR_VERBOSE 1
62 #define YYPARSE_PARAM my_lily_parser
63 #define YYLEX_PARAM my_lily_parser
65 ((My_lily_parser *) my_lily_parser)
67 #define yyerror THIS->parser_error
69 /* Add symbols to the TAGS field of a music object. */
72 tag_music (Music *m, SCM tag, Input ip)
74 SCM tags = m->get_property ("tags");
75 if (ly_c_symbol_p (tag))
76 tags = scm_cons (tag, tags);
77 else if (ly_c_list_p (tag))
78 tags = ly_append2 (tag, tags);
80 ip.warning (_ ("Tag must be symbol or list of symbols."));
82 m->set_property ("tags", tags);
86 is_regular_identifier (SCM id)
88 String str = ly_scm2string (id);
89 char const *s = str.to_str0 ();
98 v = v && isalnum (*s);
105 make_simple_markup (SCM encoding, SCM a)
107 SCM simple = ly_scheme_function ("simple-markup");
108 if (ly_c_symbol_p (encoding))
109 return scm_list_3 (ly_scheme_function ("encoded-simple-markup"),
111 return scm_list_2 (simple, a);
117 return t && t == 1 << intlog2 (t);
121 set_music_properties (Music *p, SCM a)
123 for (SCM k = a; ly_c_pair_p (k); k = ly_cdr (k))
124 p->internal_set_property (ly_caar (k), ly_cdar (k));
128 make_chord_step (int step, int alter)
135 Pitch m ((step -1) / 7, (step - 1) % 7, alter);
136 return m.smobbed_copy ();
141 make_chord (SCM pitch, SCM dur, SCM modification_list)
143 SCM chord_ctor = ly_scheme_function ("construct-chord");
144 SCM ch = scm_call_3 (chord_ctor, pitch, dur, modification_list);
145 scm_gc_protect_object (ch);
149 /* Todo: actually also use apply iso. call too ... */
151 ly_input_procedure_p (SCM x)
153 return ly_c_procedure_p (x)
154 || (ly_c_pair_p (x) && ly_c_procedure_p (ly_car (x)));
158 set_property_music (SCM sym, SCM value)
160 Music *p = MY_MAKE_MUSIC ("PropertySet");
161 p->set_property ("symbol", sym);
162 p->set_property ("value", value);
167 make_music_relative (Pitch start, Music *music)
169 Music *relative = MY_MAKE_MUSIC ("RelativeOctaveMusic");
170 relative->set_property ("element", music->self_scm ());
172 Pitch last = music->to_relative_octave (start);
173 if (lily_1_8_relative)
174 music->set_property ("last-pitch", last.smobbed_copy ());
179 make_lyric_combine_music (SCM name, Music *music)
181 Music *combine = MY_MAKE_MUSIC ("NewLyricCombineMusic");
182 combine->set_property ("element", music->self_scm ());
183 combine->set_property ("associated-context", name);
189 /* We use SCMs to do strings, because it saves us the trouble of
190 deleting them. Let's hope that a stack overflow doesnt trigger a move
191 of the parse stack onto the heap. */
197 Music_output_def *outputdef;
207 yylex (YYSTYPE *s, void *v)
209 My_lily_parser *pars = (My_lily_parser*) v;
210 My_lily_lexer *lex = pars->lexer_;
212 lex->lexval = (void*) s;
213 lex->prepare_for_next_token ();
214 return lex->yylex ();
223 Three shift/reduce problems:
225 2. \markup identifier.
230 \repeat .. \alternative
233 \repeat { \repeat .. \alternative }
237 \repeat { \repeat } \alternative
253 %token CHORDMODIFIERS
255 %token DOUBLE_ANGLE_OPEN
256 %token DOUBLE_ANGLE_CLOSE
258 %token COMMANDSPANREQUEST
266 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
267 %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
268 %token GROBDESCRIPTIONS
277 %token MULTI_MEASURE_REST
283 %token OVERRIDE SET REVERT
309 /* FIXME: this sucks. The user will get to see these names:
310 syntax error, unexpected E_CHAR:
314 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
315 %token E_LEFTSQUARE E_RIGHTSQUARE E_TILDE
317 %token <i> E_UNSIGNED
318 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET CHORD_SLASH
322 %token <scm> NOTENAME_PITCH
323 %token <scm> TONICNAME_PITCH
324 %token <scm> CHORDMODIFIER_PITCH
325 %token <scm> DURATION_IDENTIFIER
326 %token <scm> FRACTION
327 %token <id> IDENTIFIER
329 %token <scm> DRUM_PITCH
330 %token <scm> CHORD_MODIFIER
331 %token <scm> SCORE_IDENTIFIER
332 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
333 %token <scm> NUMBER_IDENTIFIER
334 %token <scm> EVENT_IDENTIFIER
335 %token <scm> MUSIC_IDENTIFIER CONTEXT_DEF_IDENTIFIER
336 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
337 %token <scm> RESTNAME
344 %token <scm> MARKUP_HEAD_MARKUP0
345 %token <scm> MARKUP_HEAD_EMPTY
346 %token <scm> MARKUP_HEAD_MARKUP0_MARKUP1
347 %token <scm> MARKUP_HEAD_SCM0
348 %token <scm> MARKUP_HEAD_SCM0_MARKUP1
349 %token <scm> MARKUP_HEAD_SCM0_SCM1
350 %token <scm> MARKUP_HEAD_SCM0_SCM1_SCM2
351 %token <scm> MARKUP_HEAD_SCM0_SCM1_MARKUP2
353 %token <scm> MUSIC_FUNCTION
354 %token <scm> MUSIC_FUNCTION_SCM
355 %token <scm> MUSIC_FUNCTION_MUSIC
356 %token <scm> MUSIC_FUNCTION_SCM_MUSIC
357 %token <scm> MUSIC_FUNCTION_MUSIC_MUSIC
358 %token <scm> MUSIC_FUNCTION_SCM_SCM_MUSIC
359 %token <scm> MUSIC_FUNCTION_SCM_MUSIC_MUSIC
361 %token <scm> MARKUP_IDENTIFIER MARKUP_HEAD_LIST0
362 %type <scm> markup markup_line markup_list markup_list_body full_markup
364 %type <book> book_block book_body
365 %type <i> exclamations questions dots optional_rest
367 %type <scm> oct_check
368 %type <scm> context_mod_list
369 %type <scm> lyric_element
370 %type <scm> bass_number br_bass_figure bass_figure figure_list figure_spec
371 %type <scm> new_lyrics
372 %type <outputdef> output_def
373 %type <scm> lilypond_header lilypond_header_body
374 %type <music> open_event close_event
375 %type <i> sub_quotes sup_quotes
376 %type <music> toplevel_music
377 %type <music> simple_element event_chord command_element
378 %type <music> Composite_music Simple_music Prefix_composite_music Generic_prefix_music
379 %type <scm> Generic_prefix_music_scm
380 %type <music> Grouped_music_list
381 %type <music> Repeated_music
382 %type <scm> Alternative_music
383 %type <i> tremolo_type
384 %type <i> bare_int bare_unsigned
386 %type <scm> identifier_init
387 %type <scm> simple_string
389 %type <music> note_chord_element chord_body chord_body_element
390 %type <scm> chord_body_elements
391 %type <scm> steno_duration optional_notemode_duration multiplied_duration
393 %type <scm> post_events
394 %type <music> gen_text_def direction_less_event direction_reqd_event
395 %type <scm> steno_pitch pitch absolute_pitch pitch_also_in_chords
396 %type <scm> steno_tonic_pitch
397 %type <scm> duration_length fraction
399 %type <scm> chord_item chord_items chord_separator new_chord
400 %type <scm> step_number step_numbers
402 %type <scm> embedded_scm scalar
403 %type <music> Music Sequential_music Simultaneous_music
404 %type <music> relative_music re_rhythmed_music
405 %type <music> music_property_def context_change
406 %type <scm> context_prop_spec
407 %type <scm> Music_list
408 %type <scm> property_operation
409 %type <scm> context_mod context_def_mod optional_context_mod
410 %type <outputdef> music_output_def_body music_output_def_head
411 %type <music> post_event tagged_post_event
412 %type <music> command_req
413 %type <music> string_number_event
414 %type <scm> string bare_number number_expression number_term number_factor
415 %type <score> score_block score_body
417 %type <scm> context_def_spec_block context_def_spec_body
418 %type <music> tempo_event
419 %type <scm> script_abbreviation
425 /* We don't assign precedence to / and *, because we might need varied
426 prec levels in different prods */
432 lilypond: /* empty */
433 | lilypond toplevel_expression {
435 | lilypond assignment {
438 THIS->error_level_ = 1;
441 THIS->error_level_ = 1;
454 SCM proc = THIS->lexer_->lookup_identifier ("toplevel-book-handler");
455 scm_call_2 (proc, THIS->self_scm (), book->self_scm ());
456 scm_gc_unprotect_object (book->self_scm ());
461 SCM proc = THIS->lexer_->lookup_identifier ("toplevel-score-handler");
462 scm_call_2 (proc, THIS->self_scm (), score->self_scm ());
463 scm_gc_unprotect_object (score->self_scm ());
467 SCM proc = THIS->lexer_->lookup_identifier ("toplevel-music-handler");
468 scm_call_2 (proc, THIS->self_scm (), music->self_scm ());
469 scm_gc_unprotect_object (music->self_scm ());
473 if (dynamic_cast<Paper_def*> ($1))
474 id = scm_makfrom0str ("$defaultpaper");
475 else if (dynamic_cast<Midi_def*> ($1))
476 id = scm_makfrom0str ("$defaultmidi");
477 THIS->lexer_->set_identifier (id, $1->self_scm ());
478 scm_gc_unprotect_object ($1->self_scm ());
493 lilypond_header_body:
495 $$ = ly_make_anonymous_module (safe_global_b);
496 THIS->lexer_->add_scope ($$);
498 | lilypond_header_body assignment {
504 HEADER '{' lilypond_header_body '}' {
505 $$ = THIS->lexer_->remove_scope ();
517 /* cont */ '=' identifier_init {
520 Should find generic way of associating input with objects.
522 Input ip = THIS->pop_spot ();
524 if (! is_regular_identifier ($1))
526 ip.warning (_ ("Identifier should have alphabetic characters only"));
529 THIS->lexer_->set_identifier ($1, $4);
532 TODO: devise standard for protection in parser.
534 The parser stack lives on the C-stack, which means that
535 all objects can be unprotected as soon as they're here.
545 $$ = $1->self_scm ();
546 scm_gc_unprotect_object ($$);
552 $$ = $1->self_scm ();
553 scm_gc_unprotect_object ($$);
555 | context_def_spec_block {
559 $$ = $1->self_scm ();
560 scm_gc_unprotect_object ($$);
563 $$ = $1->self_scm ();
564 scm_gc_unprotect_object ($$);
566 | number_expression {
577 context_def_spec_block:
578 CONTEXT '{' context_def_spec_body '}'
584 context_def_spec_body:
586 $$ = Context_def::make_scm ();
587 unsmob_context_def ($$)->set_spot (THIS->here_input ());
589 | CONTEXT_DEF_IDENTIFIER {
591 unsmob_context_def ($$)->set_spot (THIS->here_input ());
593 | context_def_spec_body GROBDESCRIPTIONS embedded_scm {
594 Context_def*td = unsmob_context_def ($$);
596 for (SCM p = $3; ly_c_pair_p (p); p = ly_cdr (p)) {
597 SCM tag = ly_caar (p);
599 /* TODO: should make new tag "grob-definition" ? */
600 td->add_context_mod (scm_list_3 (ly_symbol2scm ("assign"),
601 tag, scm_cons (ly_cdar (p), SCM_EOL)));
604 | context_def_spec_body context_mod {
605 unsmob_context_def ($$)->add_context_mod ($2);
613 /*cont*/ '{' book_body '}' {
620 * Use 'handlers' like for toplevel-* stuff?
621 * grok \paper and \midi? */
625 $$->set_spot (THIS->here_input ());
626 $$->bookpaper_ = unsmob_book_paper_def (THIS->lexer_->lookup_identifier ("$defaultbookpaper"));
628 | book_body score_block {
630 $$->scores_.push (score);
631 scm_gc_unprotect_object (score->self_scm ());
633 | book_body Composite_music {
636 = unsmob_score (ly_music_scorify (music->self_scm ()));
637 $$->scores_.push (score);
638 scm_gc_unprotect_object (music->self_scm ());
651 /*cont*/ '{' score_body '}' {
661 $$->set_spot (THIS->here_input ());
662 SCM m = $1->self_scm ();
663 scm_gc_unprotect_object (m);
668 SCM check_funcs = ly_scheme_function ("toplevel-music-functions");
669 for (; ly_c_pair_p (check_funcs); check_funcs = ly_cdr (check_funcs))
670 m = scm_call_1 (ly_car (check_funcs), m);
675 $$ = new Score ( *unsmob_score ($1));
676 $$->set_spot (THIS->here_input ());
678 | score_body lilypond_header {
681 | score_body output_def {
683 scm_gc_unprotect_object ($2->self_scm ());
695 music_output_def_body '}' {
697 THIS->lexer_->remove_scope ();
698 THIS->lexer_->pop_state ();
702 music_output_def_head:
704 Music_output_def *id = unsmob_music_output_def (THIS->lexer_->lookup_identifier ("$defaultmidi"));
709 p = dynamic_cast<Midi_def*> (id->clone ());
714 THIS->lexer_->add_scope (p->scope_);
717 Music_output_def *id = unsmob_music_output_def (THIS->lexer_->lookup_identifier ("$defaultpaper"));
720 p = dynamic_cast<Paper_def*> (id->clone ());
724 THIS->lexer_->add_scope (p->scope_);
730 music_output_def_body:
731 music_output_def_head '{' {
733 $$->input_origin_. set_spot (THIS->here_input ());
734 THIS->lexer_->push_initial_state ();
736 | music_output_def_head '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
737 scm_gc_unprotect_object ($1->self_scm ());
738 Music_output_def *o = unsmob_music_output_def ($3);
739 o->input_origin_.set_spot (THIS->here_input ());
741 THIS->lexer_->remove_scope ();
742 THIS->lexer_->add_scope (o->scope_);
743 THIS->lexer_->push_initial_state ();
745 | music_output_def_body assignment {
748 | music_output_def_body context_def_spec_block {
749 $$->assign_context_def ($2);
751 | music_output_def_body tempo_event {
753 junk this ? there already is tempo stuff in
756 int m = ly_scm2int ( $2->get_property ("metronome-count"));
757 Duration *d = unsmob_duration ($2->get_property ("tempo-unit"));
758 Midi_def *md = dynamic_cast<Midi_def*> ($$);
760 md->set_tempo (d->get_length (), m);
761 scm_gc_unprotect_object ($2->self_scm ());
763 | music_output_def_body error {
769 TEMPO steno_duration '=' bare_unsigned {
770 $$ = MY_MAKE_MUSIC ("MetronomeChangeEvent");
771 $$->set_property ("tempo-unit", $2);
772 $$->set_property ("metronome-count", scm_int2num ( $4));
777 The representation of a list is the
781 to have efficient append.
785 $$ = scm_cons (SCM_EOL, SCM_EOL);
789 SCM c = scm_cons ($2->self_scm (), SCM_EOL);
790 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
791 if (ly_c_pair_p (ly_cdr (s)))
792 scm_set_cdr_x (ly_cdr (s), c); /* append */
794 scm_set_car_x (s, c); /* set first cons */
795 scm_set_cdr_x (s, c); /* remember last cell */
797 | Music_list embedded_scm {
813 | ALTERNATIVE '{' Music_list '}' {
820 REPEAT simple_string bare_unsigned Music Alternative_music
824 SCM alts = ly_c_pair_p ($5) ? ly_car ($5) : SCM_EOL;
825 if (times < scm_ilength (alts)) {
826 unsmob_music (ly_car (alts))
827 ->origin ()->warning (
828 _ ("More alternatives than repeats. Junking excess alternatives."));
829 alts = ly_truncate_list (times, alts);
833 SCM proc = ly_scheme_function ("make-repeated-music");
835 SCM mus = scm_call_1 (proc, $2);
836 scm_gc_protect_object (mus); // UGH.
837 Music *r = unsmob_music (mus);
840 r-> set_property ("element", beg->self_scm ());
841 scm_gc_unprotect_object (beg->self_scm ());
843 r->set_property ("repeat-count", scm_int2num (times >? 1));
845 r-> set_property ("elements",alts);
846 if (ly_c_equal_p ($2, scm_makfrom0str ("tremolo"))) {
848 TODO: move this code to Scheme.
852 we can not get durations and other stuff correct down the line, so we have to
853 add to the duration log here.
855 SCM func = ly_scheme_function ("shift-duration-log");
857 int dots = ($3 % 3) ? 0 : 1;
858 int shift = -intlog2 ((dots) ? ($3*2/3) : $3);
860 Sequential_music *seq = dynamic_cast<Sequential_music*> ($4);
863 int list_len = scm_ilength (seq->music_list ());
865 seq->origin ()->warning ("Chord tremolo must have 2 elements.");
867 r->compress (Moment (Rational (1, list_len)));
869 scm_call_3 (func, r->self_scm (), scm_int2num (shift),scm_int2num (dots));
872 r->set_spot (*$4->origin ());
879 SEQUENTIAL '{' Music_list '}' {
880 $$ = MY_MAKE_MUSIC ("SequentialMusic");
881 $$->set_property ("elements", ly_car ($3));
882 $$->set_spot (THIS->here_input ());
884 | '{' Music_list '}' {
885 $$ = MY_MAKE_MUSIC ("SequentialMusic");
886 $$->set_property ("elements", ly_car ($2));
887 $$->set_spot (THIS->here_input ());
892 SIMULTANEOUS '{' Music_list '}'{
893 $$ = MY_MAKE_MUSIC ("SimultaneousMusic");
894 $$->set_property ("elements", ly_car ($3));
895 $$->set_spot (THIS->here_input ());
898 | simul_open Music_list simul_close {
899 $$ = MY_MAKE_MUSIC ("SimultaneousMusic");
900 $$->set_property ("elements", ly_car ($2));
901 $$->set_spot (THIS->here_input ());
906 event_chord { $$ = $1; }
908 $$ = unsmob_music ($1);
915 optional_context_mod:
916 /**/ { $$ = SCM_EOL; }
917 | WITH { THIS->lexer_->push_initial_state (); }
918 '{' context_mod_list '}'
920 THIS->lexer_->pop_state ();
926 /* */ { $$ = SCM_EOL; }
927 | context_mod_list context_mod {
928 $$ = scm_cons ($2, $1);
934 Prefix_composite_music { $$ = $1; }
935 | Grouped_music_list { $$ = $1; }
939 Simultaneous_music { $$ = $1; }
940 | Sequential_music { $$ = $1; }
943 Generic_prefix_music_scm:
945 $$ = scm_list_2 ($1, make_input (THIS->here_input ()));
947 | MUSIC_FUNCTION_SCM {
950 $$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3);
952 | MUSIC_FUNCTION_MUSIC {
955 $$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3->self_scm ());
956 scm_gc_unprotect_object ($3->self_scm ());
958 | MUSIC_FUNCTION_SCM_MUSIC {
960 } embedded_scm Music {
961 $$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3, $4->self_scm ());
962 scm_gc_unprotect_object ($4->self_scm ());
964 | MUSIC_FUNCTION_MUSIC_MUSIC {
967 $$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3->self_scm (), $4->self_scm ());
968 scm_gc_unprotect_object ($3->self_scm ());
969 scm_gc_unprotect_object ($4->self_scm ());
971 | MUSIC_FUNCTION_SCM_MUSIC_MUSIC {
973 } embedded_scm Music Music {
974 $$ = scm_list_5 ($1, make_input (THIS->pop_spot ()),
975 $3, $4->self_scm (), $5->self_scm ());
976 scm_gc_unprotect_object ($5->self_scm ());
977 scm_gc_unprotect_object ($4->self_scm ());
981 Generic_prefix_music:
982 Generic_prefix_music_scm {
983 SCM func = ly_car ($1);
984 Input *loc = unsmob_input (ly_cadr ($1));
985 SCM args = ly_cddr ($1);
986 SCM sig = scm_object_property (func, ly_symbol2scm ("music-function-signature"));
989 for (SCM s = sig, t = args;
990 ok && ly_c_pair_p (s) && ly_c_pair_p (t);
991 s = ly_cdr (s), t = ly_cdr (t)) {
993 if (scm_call_1 (ly_car (s), ly_car (t)) != SCM_BOOL_T)
995 loc->error (_f ("Argument %d failed typecheck", k));
996 THIS->error_level_ = 1;
1002 m = scm_apply_0 (func, ly_cdr ($1));
1003 if (unsmob_music (m))
1005 $$ = unsmob_music (m);
1006 scm_gc_protect_object (m);
1011 loc->error (_ ("Music head function should return Music object."));
1012 $$ = MY_MAKE_MUSIC ("Music");
1014 $$->set_spot (*loc);
1019 Prefix_composite_music:
1020 Generic_prefix_music {
1023 | CONTEXT simple_string '=' simple_string optional_context_mod Music {
1024 $$ = context_spec_music ($2, $4, $6, $5);
1027 | CONTEXT simple_string optional_context_mod Music {
1028 $$ = context_spec_music ($2, SCM_UNDEFINED, $4, $3);
1030 | NEWCONTEXT simple_string optional_context_mod Music {
1031 $$ = context_spec_music ($2, get_next_unique_context (), $4,
1042 int n = ly_scm2int (ly_car ($3)); int d = ly_scm2int (ly_cdr ($3));
1045 $$= MY_MAKE_MUSIC ("TimeScaledMusic");
1046 $$->set_spot (THIS->pop_spot ());
1048 $$->set_property ("element", mp->self_scm ());
1049 scm_gc_unprotect_object (mp->self_scm ());
1050 $$->set_property ("numerator", scm_int2num (n));
1051 $$->set_property ("denominator", scm_int2num (d));
1052 $$->compress (Moment (Rational (n,d)));
1055 | Repeated_music { $$ = $1; }
1056 | TRANSPOSE pitch_also_in_chords pitch_also_in_chords Music {
1057 $$ = MY_MAKE_MUSIC ("TransposedMusic");
1059 Pitch from = *unsmob_pitch ($2);
1060 Pitch to = *unsmob_pitch ($3);
1062 p->transpose (interval (from, to));
1063 $$->set_property ("element", p->self_scm ());
1064 scm_gc_unprotect_object (p->self_scm ());
1068 SCM nn = THIS->lexer_->lookup_identifier ("pitchnames");
1069 THIS->lexer_->push_note_state (alist_to_hashq (nn));
1073 THIS->lexer_->pop_state ();
1077 SCM nn = THIS->lexer_->lookup_identifier ("drumPitchNames");
1078 THIS->lexer_->push_note_state (alist_to_hashq (nn));
1080 /* FIXME: This used to be: */
1082 /* Grouped_music_list */
1084 THIS->lexer_->pop_state ();
1087 { THIS->lexer_->push_figuredbass_state (); }
1088 /* FIXME: This used to be:
1090 but that breaks web build
1094 Music *chm = MY_MAKE_MUSIC ("UntransposableMusic");
1095 chm->set_property ("element", $3->self_scm ());
1097 scm_gc_unprotect_object ($3->self_scm ());
1099 THIS->lexer_->pop_state ();
1102 SCM nn = THIS->lexer_->lookup_identifier ("chordmodifiers");
1103 THIS->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
1104 nn = THIS->lexer_->lookup_identifier ("pitchnames");
1105 THIS->lexer_->push_chord_state (alist_to_hashq (nn));
1113 Music *chm = MY_MAKE_MUSIC ("UnrelativableMusic");
1114 chm->set_property ("element", $3->self_scm ());
1115 scm_gc_unprotect_object ($3->self_scm ());
1118 THIS->lexer_->pop_state ();
1121 { THIS->lexer_->push_lyric_state (); }
1128 THIS->lexer_->pop_state ();
1130 | relative_music { $$ = $1; }
1131 | re_rhythmed_music { $$ = $1; }
1132 | TAG embedded_scm Music {
1133 tag_music ($3, $2, THIS->here_input ());
1139 RELATIVE absolute_pitch Music {
1141 Pitch start = *unsmob_pitch ($2);
1142 $$ = make_music_relative (start, m);
1143 scm_gc_unprotect_object (m->self_scm ());
1145 | RELATIVE Composite_music {
1147 /* FIXME: why is octave==0 and default not middleC? */
1148 Pitch middle_c (-1, 0, 0);
1149 $$ = make_music_relative (middle_c, m);
1150 scm_gc_unprotect_object (m->self_scm ());
1155 NEWLYRICS { THIS->lexer_->push_lyric_state (); }
1157 Grouped_music_list {
1158 /* Can also use Music at the expensive of two S/Rs similar to
1159 \repeat \alternative */
1160 THIS->lexer_->pop_state ();
1162 Music *music = MY_MAKE_MUSIC ("SimultaneousMusic");
1163 music->set_property ("elements", scm_list_1 ($3->self_scm ()));
1166 $$ = scm_cons ($3->self_scm (), SCM_EOL);
1169 | new_lyrics NEWLYRICS { THIS->lexer_->push_lyric_state (); }
1170 Grouped_music_list {
1171 THIS->lexer_->pop_state ();
1172 $$ = scm_cons ($4->self_scm (), $1);
1177 Grouped_music_list new_lyrics {
1179 /* FIXME: should find out uniqueXXX name from music */
1180 SCM name = $1->get_property ("context-id");
1181 //if (name == SCM_EOL)
1182 if (!ly_c_string_p (name))
1183 name = scm_makfrom0str ("");
1185 SCM context = scm_makfrom0str ("Lyrics");
1186 Music *all = MY_MAKE_MUSIC ("SimultaneousMusic");
1189 for (SCM s = $2; ly_c_pair_p (s); s = ly_cdr (s))
1191 Music *music = unsmob_music (ly_car (s));
1192 Music *com = make_lyric_combine_music (name, music);
1193 Music *csm = context_spec_music (context,
1194 get_next_unique_context (), com, SCM_EOL);
1195 lst = scm_cons (csm->self_scm (), lst);
1197 /* FIXME: only first lyric music is accepted,
1198 the rest is junked */
1199 all->set_property ("elements", scm_cons ($1->self_scm (),
1202 scm_gc_unprotect_object ($1->self_scm ());
1204 | LYRICSTO string Music {
1207 $$ = make_lyric_combine_music (name, music);
1208 scm_gc_unprotect_object (music->self_scm ());
1213 CHANGE STRING '=' STRING {
1214 Music*t= MY_MAKE_MUSIC ("ContextChange");
1215 t-> set_property ("change-to-type", scm_string_to_symbol ($2));
1216 t-> set_property ("change-to-id", $4);
1219 $$->set_spot (THIS->here_input ());
1225 $$ = scm_list_3 (ly_symbol2scm ("assign"),
1226 scm_string_to_symbol ($1), $3);
1228 | UNSET simple_string {
1229 $$ = scm_list_2 (ly_symbol2scm ("unset"),
1230 scm_string_to_symbol ($2));
1232 | OVERRIDE simple_string embedded_scm '=' embedded_scm {
1233 $$ = scm_list_4 (ly_symbol2scm ("push"),
1234 scm_string_to_symbol ($2), $3, $5);
1236 | REVERT simple_string embedded_scm {
1237 $$ = scm_list_3 (ly_symbol2scm ("pop"),
1238 scm_string_to_symbol ($2), $3);
1243 CONSISTSEND { $$ = ly_symbol2scm ("consists-end"); }
1244 | CONSISTS { $$ = ly_symbol2scm ("consists"); }
1245 | REMOVE { $$ = ly_symbol2scm ("remove"); }
1247 | ACCEPTS { $$ = ly_symbol2scm ("accepts"); }
1248 | DENIES { $$ = ly_symbol2scm ("denies"); }
1250 | ALIAS { $$ = ly_symbol2scm ("alias"); }
1251 | TYPE { $$ = ly_symbol2scm ("translator-type"); }
1252 | DESCRIPTION { $$ = ly_symbol2scm ("description"); }
1253 | NAME { $$ = ly_symbol2scm ("context-name"); }
1257 property_operation { $$ = $1; }
1258 | context_def_mod STRING {
1259 $$ = scm_list_2 ($1, $2);
1265 $$ = scm_list_2 (ly_symbol2scm ("Bottom"),
1266 scm_string_to_symbol ($1));
1268 | simple_string '.' simple_string {
1269 $$ = scm_list_2 (scm_string_to_symbol ($1),
1270 scm_string_to_symbol ($3));
1275 OVERRIDE context_prop_spec embedded_scm '=' scalar {
1276 $$ = property_op_to_music (scm_list_4 (
1277 ly_symbol2scm ("poppush"),
1280 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1282 | REVERT context_prop_spec embedded_scm {
1283 $$ = property_op_to_music (scm_list_3 (
1284 ly_symbol2scm ("pop"),
1288 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1290 | SET context_prop_spec '=' scalar {
1291 $$ = property_op_to_music (scm_list_3 (
1292 ly_symbol2scm ("assign"),
1295 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1297 | UNSET context_prop_spec {
1298 $$ = property_op_to_music (scm_list_2 (
1299 ly_symbol2scm ("unset"),
1301 $$= context_spec_music (ly_car ($2), SCM_UNDEFINED, $$, SCM_EOL);
1303 | ONCE music_property_def {
1304 SCM e = $2->get_property ("element");
1305 unsmob_music (e)->set_property ("once", SCM_BOOL_T);
1316 | STRING_IDENTIFIER {
1319 | string '+' string {
1320 $$ = scm_string_append (scm_list_2 ($1, $3));
1324 simple_string: STRING {
1335 $$ = scm_int2num ($1);
1342 $$ = scm_int2num ($1);
1347 FIXME: remove or fix this comment. What is `This'?
1351 Adding pre_events to the simple_element
1352 makes the choice between
1358 simple_element: STRING
1360 a single shift/reduction conflict.
1362 nevertheless, this is not very clean, and we should find a different
1372 pre_events simple_element post_events {
1373 SCM elts = $2-> get_property ("elements");
1375 elts = ly_append2 (elts, scm_reverse_x ($3, SCM_EOL));
1377 $2->set_property ("elements", elts);
1381 | note_chord_element
1386 chord_body optional_notemode_duration post_events
1388 SCM dur = unsmob_duration ($2)->smobbed_copy ();
1389 SCM es = $1->get_property ("elements");
1390 SCM postevs = scm_reverse_x ($3, SCM_EOL);
1392 for (SCM s = es; ly_c_pair_p (s); s = ly_cdr (s))
1393 unsmob_music (ly_car (s))->set_property ("duration", dur);
1394 es = ly_append2 (es, postevs);
1396 $1-> set_property ("elements", es);
1407 simul_open: DOUBLE_ANGLE_OPEN
1410 simul_close: DOUBLE_ANGLE_CLOSE
1414 chord_open chord_body_elements chord_close
1416 $$ = MY_MAKE_MUSIC ("EventChord");
1417 $$->set_property ("elements",
1418 scm_reverse_x ($2, SCM_EOL));
1422 chord_body_elements:
1423 /* empty */ { $$ = SCM_EOL; }
1424 | chord_body_elements chord_body_element {
1425 $$ = scm_cons ($2->self_scm (), $1);
1426 scm_gc_unprotect_object ($2->self_scm ());
1431 pitch exclamations questions post_events
1433 Music *n = MY_MAKE_MUSIC ("NoteEvent");
1434 n->set_property ("pitch", $1);
1436 n->set_property ("cautionary", SCM_BOOL_T);
1437 if ($2 % 2 || $3 % 2)
1438 n->set_property ("force-accidental", SCM_BOOL_T);
1440 if (ly_c_pair_p ($4)) {
1441 SCM arts = scm_reverse_x ($4, SCM_EOL);
1442 n->set_property ("articulations", arts);
1446 | DRUM_PITCH post_events {
1447 Music *n = MY_MAKE_MUSIC ("NoteEvent");
1448 n->set_property ("duration", $2);
1449 n->set_property ("drum-type", $1);
1450 n->set_spot (THIS->here_input ());
1452 if (ly_c_pair_p ($2)) {
1453 SCM arts = scm_reverse_x ($2, SCM_EOL);
1454 n->set_property ("articulations", arts);
1461 ADDQUOTE string Music {
1462 SCM adder = ly_scheme_function ("add-quotable");
1464 scm_call_2 (adder, $2, $3->self_scm ());
1465 scm_gc_unprotect_object ($3->self_scm ());
1471 $$ = MY_MAKE_MUSIC ("EventChord");
1472 $$->set_property ("elements", scm_cons ($1->self_scm (), SCM_EOL));
1473 scm_gc_unprotect_object ($1->self_scm ());
1475 $$-> set_spot (THIS->here_input ());
1476 $1-> set_spot (THIS->here_input ());
1478 | SKIP duration_length {
1479 Music *skip = MY_MAKE_MUSIC ("SkipMusic");
1480 skip->set_property ("duration", $2);
1484 | QUOTE STRING duration_length {
1485 SCM tab = THIS->lexer_->lookup_identifier ("musicQuotes");
1487 if (scm_hash_table_p (tab) == SCM_BOOL_T)
1489 SCM key = $2; // use symbol?
1490 evs = scm_hash_ref (tab, key, SCM_BOOL_F);
1493 if (ly_c_vector_p (evs))
1495 quote = MY_MAKE_MUSIC ("QuoteMusic");
1496 quote->set_property ("duration", $3);
1497 quote->set_property ("quoted-events", evs);
1499 THIS->here_input ().warning (_f ("Can\'t find music"));
1500 quote = MY_MAKE_MUSIC ("Event");
1502 quote->set_spot (THIS->here_input ());
1505 | OCTAVE { THIS->push_spot (); }
1507 Music *m = MY_MAKE_MUSIC ("RelativeOctaveCheck");
1509 $$->set_spot (THIS->pop_spot ());
1510 $$->set_property ("pitch", $3);
1513 Music *m = MY_MAKE_MUSIC ("LigatureEvent");
1514 m->set_property ("span-direction", scm_int2num (START));
1515 m->set_spot (THIS->here_input ());
1517 $$ = MY_MAKE_MUSIC ("EventChord");
1518 $$->set_property ("elements", scm_cons (m->self_scm (), SCM_EOL));
1519 scm_gc_unprotect_object (m->self_scm ());
1520 $$->set_spot (THIS->here_input ());
1523 Music *m = MY_MAKE_MUSIC ("LigatureEvent");
1524 m->set_property ("span-direction", scm_int2num (STOP));
1525 m->set_spot (THIS->here_input ());
1527 $$ = MY_MAKE_MUSIC ("EventChord");
1528 $$->set_property ("elements", scm_cons (m->self_scm (), SCM_EOL));
1529 $$->set_spot (THIS->here_input ());
1530 scm_gc_unprotect_object (m->self_scm ());
1533 $$ = MY_MAKE_MUSIC ("VoiceSeparator");
1534 $$->set_spot (THIS->here_input ());
1537 SCM pipe =THIS->lexer_->lookup_identifier ("pipeSymbol");
1539 if (Music * m = unsmob_music (pipe))
1542 $$ = MY_MAKE_MUSIC ("BarCheck");
1544 $$->set_spot (THIS->here_input ());
1546 | TRANSPOSITION pitch {
1547 $$ = set_property_music (ly_symbol2scm ("instrumentTransposition"),
1549 $$->set_spot (THIS-> here_input ());
1550 $$ = context_spec_music (ly_symbol2scm ("Staff"), SCM_UNDEFINED,
1554 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1556 Music *csm = context_spec_music (ly_symbol2scm ("Timing"), SCM_UNDEFINED,
1558 $$ = context_spec_music (ly_symbol2scm ("Score"), SCM_UNDEFINED, csm, SCM_EOL);
1559 $$->set_spot (THIS->here_input ());
1560 t->set_spot (THIS->here_input ());
1562 | PARTIAL duration_length {
1563 Moment m = - unsmob_duration ($2)->get_length ();
1564 Music *p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1565 p->set_spot (THIS->here_input ());
1566 p = context_spec_music (ly_symbol2scm ("Timing"), SCM_UNDEFINED,
1568 p = context_spec_music (ly_symbol2scm ("Score"), SCM_UNDEFINED,
1573 SCM proc = ly_scheme_function ("make-clef-set");
1575 SCM result = scm_call_1 (proc, $2);
1576 scm_gc_protect_object (result);
1577 $$ = unsmob_music (result);
1580 SCM proc= ly_scheme_function ("make-time-signature-set");
1582 SCM result = scm_apply_2 (proc, ly_car ($2), ly_cdr ($2), SCM_EOL);
1583 scm_gc_protect_object (result);
1584 $$ = unsmob_music (result);
1587 SCM proc = ly_scheme_function ("make-mark-set");
1589 SCM result = scm_call_1 (proc, $2);
1590 scm_gc_protect_object (result);
1591 $$ = unsmob_music (result);
1597 $$ = MY_MAKE_MUSIC ("PesOrFlexaEvent");
1600 Music *m = MY_MAKE_MUSIC ("MarkEvent");
1607 Music *key= MY_MAKE_MUSIC ("KeyChangeEvent");
1610 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1612 Music *key= MY_MAKE_MUSIC ("KeyChangeEvent");
1613 if (scm_ilength ($3) > 0)
1615 key->set_property ("pitch-alist", $3);
1616 key->set_property ("tonic", Pitch (0,0,0).smobbed_copy ());
1617 ((Music*)key)->transpose (* unsmob_pitch ($2));
1619 THIS->parser_error (_ ("Second argument must be pitch list."));
1630 | post_events post_event {
1631 $2->set_spot (THIS->here_input ());
1632 $$ = scm_cons ($2->self_scm (), $$);
1633 scm_gc_unprotect_object ($2->self_scm ());
1635 | post_events tagged_post_event {
1636 $2 -> set_spot (THIS->here_input ());
1637 $$ = scm_cons ($2->self_scm (), $$);
1638 scm_gc_unprotect_object ($2->self_scm ());
1644 '-' TAG embedded_scm post_event {
1645 tag_music ($4, $3, THIS->here_input ());
1651 direction_less_event {
1655 if (!THIS->lexer_->is_lyric_state ())
1656 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1657 $$ = MY_MAKE_MUSIC ("HyphenEvent");
1660 if (!THIS->lexer_->is_lyric_state ())
1661 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1662 $$ = MY_MAKE_MUSIC ("ExtenderEvent");
1664 | script_dir direction_reqd_event {
1666 $2->set_property ("direction", scm_int2num ($1));
1669 | script_dir direction_less_event {
1671 $2->set_property ("direction", scm_int2num ($1));
1674 | string_number_event
1677 string_number_event:
1679 Music *s = MY_MAKE_MUSIC ("StringNumberEvent");
1680 s->set_property ("string-number", scm_int2num ($1));
1681 s->set_spot (THIS->here_input ());
1687 direction_less_event:
1693 TODO: should take all these defs out of the parser, adn make use
1697 (set-articulation '~ "trill")
1700 Music *m = MY_MAKE_MUSIC ("BeamEvent");
1701 m->set_spot (THIS->here_input ());
1702 m->set_property ("span-direction", scm_int2num (START));
1706 Music *m = MY_MAKE_MUSIC ("BeamEvent");
1707 m->set_spot (THIS->here_input ());
1708 m->set_property ("span-direction", scm_int2num (STOP));
1712 Music *m = MY_MAKE_MUSIC ("TieEvent");
1713 m->set_spot (THIS->here_input ());
1718 dynamic_cast<Music *> ($$)->set_property ("span-direction",
1719 scm_int2num (START));
1723 dynamic_cast<Music *> ($$)->set_property ("span-direction",
1724 scm_int2num (STOP));
1726 | EVENT_IDENTIFIER {
1727 $$ = unsmob_music ($1);
1730 Music *a = MY_MAKE_MUSIC ("TremoloEvent");
1731 a->set_spot (THIS->here_input ());
1732 a->set_property ("tremolo-type", scm_int2num ($1));
1737 direction_reqd_event:
1741 | script_abbreviation {
1742 SCM s = THIS->lexer_->lookup_identifier ("dash" + ly_scm2string ($1));
1743 Music *a = MY_MAKE_MUSIC ("ArticulationEvent");
1744 if (ly_c_string_p (s))
1745 a->set_property ("articulation-type", s);
1746 else THIS->parser_error (_ ("Expecting string as script definition"));
1752 /**/ { $$ = SCM_EOL; }
1753 | '=' { $$ = scm_int2num (0); }
1754 | '=' sub_quotes { $$ = scm_int2num ($2); }
1755 | '=' sup_quotes { $$ = scm_int2num ($2); }
1780 | NOTENAME_PITCH sup_quotes {
1781 Pitch p = *unsmob_pitch ($1);
1782 p = p.transposed (Pitch ($2,0,0));
1783 $$ = p.smobbed_copy ();
1785 | NOTENAME_PITCH sub_quotes {
1786 Pitch p =* unsmob_pitch ($1);
1787 p = p.transposed (Pitch (-$2,0,0));
1788 $$ = p.smobbed_copy ();
1800 | TONICNAME_PITCH sup_quotes {
1801 Pitch p = *unsmob_pitch ($1);
1802 p = p.transposed (Pitch ($2,0,0));
1803 $$ = p.smobbed_copy ();
1805 | TONICNAME_PITCH sub_quotes {
1806 Pitch p =* unsmob_pitch ($1);
1808 p = p.transposed (Pitch (-$2,0,0));
1809 $$ = p.smobbed_copy ();
1819 pitch_also_in_chords:
1826 Music *s = MY_MAKE_MUSIC ("SlurEvent");
1828 s->set_spot (THIS->here_input ());
1831 Music *s = MY_MAKE_MUSIC ("PhrasingSlurEvent");
1833 s->set_spot (THIS->here_input ());
1836 Music *s = MY_MAKE_MUSIC ("CrescendoEvent");
1838 s->set_spot (THIS->here_input ());
1841 Music *s = MY_MAKE_MUSIC ("DecrescendoEvent");
1843 s->set_spot (THIS->here_input ());
1850 Music *s = MY_MAKE_MUSIC ("CrescendoEvent");
1851 s->set_spot (THIS->here_input ());
1856 Music *s= MY_MAKE_MUSIC ("SlurEvent");
1858 s->set_spot (THIS->here_input ());
1862 Music *s= MY_MAKE_MUSIC ("PhrasingSlurEvent");
1864 s->set_property ("span-type",
1865 scm_makfrom0str ("phrasing-slur"));
1866 s->set_spot (THIS->here_input ());
1872 Music *t = MY_MAKE_MUSIC ("TextScriptEvent");
1873 t->set_property ("text", $1);
1874 t->set_spot (THIS->here_input ());
1878 Music *t = MY_MAKE_MUSIC ("TextScriptEvent");
1879 t->set_property ("text",
1880 make_simple_markup (THIS->lexer_->encoding (), $1));
1881 t->set_spot (THIS->here_input ());
1886 Music *t = MY_MAKE_MUSIC ("FingerEvent");
1887 t->set_property ("digit", scm_int2num ($1));
1888 t->set_spot (THIS->here_input ());
1893 script_abbreviation:
1895 $$ = scm_makfrom0str ("Hat");
1898 $$ = scm_makfrom0str ("Plus");
1901 $$ = scm_makfrom0str ("Dash");
1904 $$ = scm_makfrom0str ("Bar");
1907 $$ = scm_makfrom0str ("Larger");
1910 $$ = scm_makfrom0str ("Dot");
1913 $$ = scm_makfrom0str ("Underscore");
1920 | '-' { $$ = CENTER; }
1931 multiplied_duration {
1936 optional_notemode_duration:
1938 Duration dd = THIS->default_duration_;
1939 $$ = dd.smobbed_copy ();
1941 THIS->beam_check ($$);
1943 | multiplied_duration {
1945 THIS->default_duration_ = *unsmob_duration ($$);
1947 THIS->beam_check ($$);
1952 bare_unsigned dots {
1954 if (!is_duration ($1))
1955 THIS->parser_error (_f ("not a duration: %d", $1));
1959 $$ = Duration (len, $2).smobbed_copy ();
1961 | DURATION_IDENTIFIER dots {
1962 Duration *d = unsmob_duration ($1);
1963 Duration k (d->duration_log (), d->dot_count () + $2);
1969 multiplied_duration:
1973 | multiplied_duration '*' bare_unsigned {
1974 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1976 | multiplied_duration '*' FRACTION {
1977 Rational m (ly_scm2int (ly_car ($3)), ly_scm2int (ly_cdr ($3)));
1979 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1984 FRACTION { $$ = $1; }
1985 | UNSIGNED '/' UNSIGNED {
1986 $$ = scm_cons (scm_int2num ($1), scm_int2num ($3));
2003 | ':' bare_unsigned {
2004 if (!is_duration ($2))
2005 THIS->parser_error (_f ("not a duration: %d", $2));
2012 $$ = scm_number_to_string (scm_int2num ($1), scm_int2num (10));
2013 $$ = scm_list_2 (ly_scheme_function ("number-markup"),
2017 $$ = scm_number_to_string (scm_int2num ($1), scm_int2num (10));
2018 $$ = scm_list_2 (ly_scheme_function ("number-markup"),
2021 | STRING { $$ = $1; }
2032 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent");
2033 $$ = bfr->self_scm ();
2034 scm_gc_unprotect_object ($$);
2037 Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent");
2038 $$ = bfr->self_scm ();
2040 bfr->set_property ("figure", $1);
2042 scm_gc_unprotect_object ($$);
2044 | bass_figure bass_mod {
2045 Music *m = unsmob_music ($1);
2047 SCM salter = m->get_property ("alteration");
2048 int alter = ly_c_number_p (salter) ? ly_scm2int (salter) : 0;
2049 m->set_property ("alteration",
2050 scm_int2num (alter + $2));
2052 m->set_property ("alteration", scm_int2num (0));
2060 unsmob_music ($$)->set_property ("bracket-start", SCM_BOOL_T);
2065 | br_bass_figure ']' {
2067 unsmob_music ($1)->set_property ("bracket-stop", SCM_BOOL_T);
2075 | figure_list br_bass_figure {
2076 $$ = scm_cons ($2, $1);
2081 FIGURE_OPEN figure_list FIGURE_CLOSE {
2082 Music *m = MY_MAKE_MUSIC ("EventChord");
2083 $2 = scm_reverse_x ($2, SCM_EOL);
2084 m->set_property ("elements", $2);
2085 $$ = m->self_scm ();
2096 pitch exclamations questions oct_check optional_notemode_duration optional_rest {
2098 Input i = THIS->pop_spot ();
2099 if (!THIS->lexer_->is_note_state ())
2100 THIS->parser_error (_ ("Have to be in Note mode for notes"));
2104 n = MY_MAKE_MUSIC ("RestEvent");
2106 n = MY_MAKE_MUSIC ("NoteEvent");
2108 n->set_property ("pitch", $1);
2109 n->set_property ("duration", $5);
2111 if (ly_c_number_p ($4))
2113 int q = ly_scm2int ($4);
2114 n->set_property ("absolute-octave", scm_int2num (q-1));
2118 n->set_property ("cautionary", SCM_BOOL_T);
2119 if ($2 % 2 || $3 % 2)
2120 n->set_property ("force-accidental", SCM_BOOL_T);
2122 Music *v = MY_MAKE_MUSIC ("EventChord");
2123 v->set_property ("elements", scm_list_1 (n->self_scm ()));
2124 scm_gc_unprotect_object (n->self_scm ());
2130 | DRUM_PITCH optional_notemode_duration {
2131 Input i = THIS->pop_spot ();
2133 Music *n = MY_MAKE_MUSIC ("NoteEvent");
2134 n->set_property ("duration", $2);
2135 n->set_property ("drum-type", $1);
2137 Music *v = MY_MAKE_MUSIC ("EventChord");
2138 v->set_property ("elements", scm_list_1 (n->self_scm ()));
2139 scm_gc_unprotect_object (n->self_scm ());
2145 | figure_spec optional_notemode_duration {
2146 Music *m = unsmob_music ($1);
2147 Input i = THIS->pop_spot ();
2149 for (SCM s = m->get_property ("elements"); ly_c_pair_p (s); s = ly_cdr (s))
2151 unsmob_music (ly_car (s))->set_property ("duration", $2);
2155 | RESTNAME optional_notemode_duration {
2157 Input i = THIS->pop_spot ();
2159 if (ly_scm2string ($1) == "s") {
2161 ev = MY_MAKE_MUSIC ("SkipEvent");
2164 ev = MY_MAKE_MUSIC ("RestEvent");
2167 ev->set_property ("duration", $2);
2169 Music *velt = MY_MAKE_MUSIC ("EventChord");
2170 velt->set_property ("elements", scm_list_1 (ev->self_scm ()));
2173 scm_gc_unprotect_object (ev->self_scm ());
2177 | MULTI_MEASURE_REST optional_notemode_duration {
2180 SCM proc = ly_scheme_function ("make-multi-measure-rest");
2181 SCM mus = scm_call_2 (proc, $2,
2182 make_input (THIS->here_input ()));
2183 scm_gc_protect_object (mus);
2184 $$ = unsmob_music (mus);
2187 | lyric_element optional_notemode_duration {
2188 Input i = THIS->pop_spot ();
2189 if (!THIS->lexer_->is_lyric_state ())
2190 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
2192 Music *lreq = MY_MAKE_MUSIC ("LyricEvent");
2193 lreq->set_property ("text", $1);
2194 lreq->set_property ("duration",$2);
2196 Music *velt = MY_MAKE_MUSIC ("EventChord");
2197 velt->set_property ("elements", scm_list_1 (lreq->self_scm ()));
2204 if (!THIS->lexer_->is_chord_state ())
2205 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
2206 $$ = unsmob_music ($1);
2211 /* FIXME: lyric flavoured markup would be better */
2219 steno_tonic_pitch optional_notemode_duration {
2220 $$ = make_chord ($1, $2, SCM_EOL);
2222 | steno_tonic_pitch optional_notemode_duration chord_separator chord_items {
2223 SCM its = scm_reverse_x ($4, SCM_EOL);
2224 $$ = make_chord ($1, $2, scm_cons ($3, its));
2232 | chord_items chord_item {
2233 $$ = scm_cons ($2, $$);
2239 $$ = ly_symbol2scm ("chord-colon");
2242 $$ = ly_symbol2scm ("chord-caret");
2244 | CHORD_SLASH steno_tonic_pitch {
2245 $$ = scm_list_2 (ly_symbol2scm ("chord-slash"), $2);
2247 | CHORD_BASS steno_tonic_pitch {
2248 $$ = scm_list_2 (ly_symbol2scm ("chord-bass"), $2);
2257 $$ = scm_reverse_x ($1, SCM_EOL);
2265 step_number { $$ = scm_cons ($1, SCM_EOL); }
2266 | step_numbers '.' step_number {
2267 $$ = scm_cons ($3, $$);
2273 $$ = make_chord_step ($1, 0);
2275 | bare_unsigned '+' {
2276 $$ = make_chord_step ($1, SHARP);
2278 | bare_unsigned CHORD_MINUS {
2279 $$ = make_chord_step ($1, FLAT);
2286 TODO: should deprecate in favor of Scheme?
2290 number_expression '+' number_term {
2291 $$ = scm_sum ($1, $3);
2293 | number_expression '-' number_term {
2294 $$ = scm_difference ($1, $3);
2303 | number_factor '*' number_factor {
2304 $$ = scm_product ($1, $3);
2306 | number_factor '/' number_factor {
2307 $$ = scm_divide ($1, $3);
2312 '-' number_factor { /* %prec UNARY_MINUS */
2313 $$ = scm_difference ($2, SCM_UNDEFINED);
2321 $$ = scm_int2num ($1);
2326 | NUMBER_IDENTIFIER {
2329 | REAL NUMBER_IDENTIFIER {
2330 $$ = scm_make_real (ly_scm2double ($1) *ly_scm2double ($2));
2332 | UNSIGNED NUMBER_IDENTIFIER {
2333 $$ = scm_make_real ($1 *ly_scm2double ($2));
2349 if (scm_integer_p ($1) == SCM_BOOL_T)
2351 int k = ly_scm2int ($1);
2355 THIS->parser_error (_ ("need integer number arg"));
2366 | exclamations '!' { $$ ++; }
2371 | questions '?' { $$ ++; }
2381 { THIS->lexer_->push_markup_state (); }
2384 THIS->lexer_->pop_state ();
2390 This should be done more dynamically if possible.
2394 $$ = make_simple_markup (THIS->lexer_->encoding (), $1);
2396 | MARKUP_HEAD_EMPTY {
2397 $$ = scm_list_1 ($1);
2399 | MARKUP_HEAD_MARKUP0 markup {
2400 $$ = scm_list_2 ($1, $2);
2402 | MARKUP_HEAD_MARKUP0_MARKUP1 markup markup {
2403 $$ = scm_list_3 ($1, $2, $3);
2405 | MARKUP_HEAD_SCM0_MARKUP1 SCM_T markup {
2406 $$ = scm_list_3 ($1, $2, $3);
2411 | MARKUP_HEAD_LIST0 markup_list {
2412 $$ = scm_list_2 ($1,$2);
2414 | MARKUP_HEAD_SCM0 embedded_scm {
2415 $$ = scm_list_2 ($1, $2);
2417 | MARKUP_HEAD_SCM0_SCM1_MARKUP2 embedded_scm embedded_scm markup {
2418 $$ = scm_list_4 ($1, $2, $3, $4);
2420 | MARKUP_HEAD_SCM0_SCM1_SCM2 embedded_scm embedded_scm embedded_scm {
2421 $$ = scm_list_4 ($1, $2, $3, $4);
2423 | MARKUP_HEAD_SCM0_SCM1 embedded_scm embedded_scm {
2424 $$ = scm_list_3 ($1, $2, $3);
2426 | MARKUP_IDENTIFIER {
2429 | STRING_IDENTIFIER {
2433 SCM nn = THIS->lexer_->lookup_identifier ("pitchnames");
2434 THIS->lexer_->push_note_state (alist_to_hashq (nn));
2436 /* cont */ score_block {
2437 /* WIP this is a bit arbitrary,
2438 we should also allow \book or Composite_music.
2439 However, you'd typically want to change paper
2440 settings, and need a \score block anyway. */
2442 THIS->lexer_->pop_state ();
2444 Book *book = new Book;
2445 book->scores_.push (score);
2447 Music_output_def *paper = get_paper (THIS);
2448 SCM s = book->to_stencil (paper, THIS->header_);
2449 scm_gc_unprotect_object (score->self_scm ());
2450 scm_gc_unprotect_object (book->self_scm ());
2451 $$ = scm_list_2 (ly_scheme_function ("stencil-markup"), s);
2456 chord_open markup_list_body chord_close { $$ = scm_reverse_x ($2, SCM_EOL); }
2460 '{' markup_list_body '}' {
2461 SCM line = ly_scheme_function ("line-markup");
2463 $$ = scm_list_2 (line, scm_reverse_x ($2, SCM_EOL));
2468 /**/ { $$ = SCM_EOL; }
2469 | markup_list_body markup {
2470 $$ = scm_cons ($2, $1);
2478 My_lily_parser::set_yydebug (bool )
2486 My_lily_parser::do_yyparse ()
2488 yyparse ((void*)this);
2493 Should make this optional? It will also complain when you do
2497 which is entirely legitimate.
2499 Or we can scrap it. Barchecks should detect wrong durations, and
2500 skipTypesetting speeds it up a lot.
2504 My_lily_parser::beam_check (SCM dur)
2506 Duration *d = unsmob_duration (dur);
2507 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2509 Music *m = unsmob_music (last_beam_start_);
2510 m->origin ()->warning (_ ("Suspect duration found following this beam"));
2512 last_beam_start_ = SCM_EOL;
2520 It is a little strange to have this function in this file, but
2521 otherwise, we have to import music classes into the lexer.
2525 My_lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
2527 if (ly_c_string_p (sid)) {
2529 return STRING_IDENTIFIER;
2530 } else if (ly_c_number_p (sid)) {
2532 return NUMBER_IDENTIFIER;
2533 } else if (unsmob_context_def (sid)) {
2534 *destination = unsmob_context_def (sid)->clone_scm ();
2535 return CONTEXT_DEF_IDENTIFIER;
2536 } else if (unsmob_score (sid)) {
2537 Score *score = new Score (*unsmob_score (sid));
2538 *destination = score->self_scm ();
2539 return SCORE_IDENTIFIER;
2540 } else if (Music *mus = unsmob_music (sid)) {
2541 mus = mus->clone ();
2542 *destination = mus->self_scm ();
2543 unsmob_music (*destination)->
2544 set_property ("origin", make_input (last_input_));
2545 return dynamic_cast<Event*> (mus)
2546 ? EVENT_IDENTIFIER : MUSIC_IDENTIFIER;
2547 } else if (unsmob_duration (sid)) {
2548 *destination = unsmob_duration (sid)->smobbed_copy ();
2549 return DURATION_IDENTIFIER;
2550 } else if (unsmob_music_output_def (sid)) {
2551 Music_output_def *p = unsmob_music_output_def (sid);
2554 *destination = p->self_scm ();
2555 return MUSIC_OUTPUT_DEF_IDENTIFIER;
2556 } else if (Text_item::markup_p (sid)) {
2558 return MARKUP_IDENTIFIER;
2565 property_op_to_music (SCM op)
2568 SCM tag = ly_car (op);
2569 SCM symbol = ly_cadr (op);
2570 SCM args = ly_cddr (op);
2571 SCM grob_val = SCM_UNDEFINED;
2572 SCM grob_sym = SCM_UNDEFINED;
2573 SCM val = SCM_UNDEFINED;
2575 if (tag == ly_symbol2scm ("assign"))
2577 m = MY_MAKE_MUSIC ("PropertySet");
2578 val = ly_car (args);
2580 else if (tag == ly_symbol2scm ("unset"))
2581 m = MY_MAKE_MUSIC ("PropertyUnset");
2582 else if (tag == ly_symbol2scm ("poppush")
2583 || tag == ly_symbol2scm ("push"))
2585 m = MY_MAKE_MUSIC ("OverrideProperty");
2586 grob_sym = ly_car (args);
2587 grob_val = ly_cadr (args);
2589 else if (tag == ly_symbol2scm ("pop")) {
2590 m = MY_MAKE_MUSIC ("RevertProperty");
2591 grob_sym = ly_car (args);
2594 m->set_property ("symbol", symbol);
2596 if (val != SCM_UNDEFINED)
2597 m->set_property ("value", val);
2598 if (grob_val != SCM_UNDEFINED)
2599 m->set_property ("grob-value", grob_val);
2601 if (grob_sym != SCM_UNDEFINED)
2603 bool itc = internal_type_checking_global_b;
2606 bool autobeam = ly_c_equal_p (symbol, ly_symbol2scm ("autoBeamSettings"));
2608 internal_type_checking_global_b = false;
2609 m->set_property ("grob-property", grob_sym);
2611 internal_type_checking_global_b = itc;
2614 if (tag == ly_symbol2scm ("poppush"))
2615 m->set_property ("pop-first", SCM_BOOL_T);
2622 context_spec_music (SCM type, SCM id, Music *m, SCM ops)
2624 Music *csm = MY_MAKE_MUSIC ("ContextSpeccedMusic");
2626 csm->set_property ("element", m->self_scm ());
2627 scm_gc_unprotect_object (m->self_scm ());
2629 csm->set_property ("context-type",
2630 ly_c_symbol_p (type) ? type : scm_string_to_symbol (type));
2631 csm->set_property ("property-operations", ops);
2633 if (ly_c_string_p (id))
2634 csm->set_property ("context-id", id);
2639 get_next_unique_context ()
2641 static int new_context_count;
2643 snprintf (s, 1024, "uniqueContext%d", new_context_count++);
2644 return scm_makfrom0str (s);