1 %{ // -*-Fundamental-*-
4 parser.yy -- Bison/C++ parser for lilypond
6 source file of the GNU LilyPond music typesetter
8 (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 Jan Nieuwenhuizen <janneke@gnu.org>
13 Two shift/reduce problems:
20 the rules for who is protecting what are very shady. TODO: uniformise
29 #include "translator-def.hh"
30 #include "lily-guile.hh"
31 #include "change-iterator.hh"
33 #include "my-lily-lexer.hh"
34 #include "paper-def.hh"
35 #include "midi-def.hh"
37 #include "file-path.hh"
39 #include "dimensions.hh"
40 #include "command-request.hh"
41 #include "musical-request.hh"
42 #include "my-lily-parser.hh"
43 #include "context-specced-music.hh"
45 #include "music-list.hh"
46 #include "output-property-music-iterator.hh"
47 #include "property-iterator.hh"
48 #include "file-results.hh"
51 #include "relative-music.hh"
52 #include "lyric-combine-music.hh"
53 #include "transposed-music.hh"
54 #include "time-scaled-music.hh"
55 #include "repeated-music.hh"
56 #include "untransposable-music.hh"
57 #include "lilypond-input-version.hh"
58 #include "grace-music.hh"
59 #include "part-combine-music.hh"
60 #include "scm-hash.hh"
61 #include "auto-change-iterator.hh"
62 #include "un-relativable-music.hh"
66 regular_identifier_b (SCM id)
68 String str = ly_scm2string (id);
69 char const *s = str.ch_C() ;
74 v = v && isalpha (*s);
82 set_property_music (SCM sym, SCM value)
84 Music * p = new Music (SCM_EOL);
85 p->set_mus_property ("symbol", sym);
86 p->set_mus_property ("iterator-ctor",
87 Property_iterator::constructor_cxx_function);
89 p->set_mus_property ("value", value);
96 return t && t == 1 << intlog2 (t);
100 set_music_properties (Music *p, SCM a)
102 for (SCM k = a; gh_pair_p (k); k = ly_cdr (k))
104 p->internal_set_mus_property (ly_caar (k), ly_cdar (k));
114 // needed for bison.simple's malloc () and free ()
121 #define YYERROR_VERBOSE 1
123 #define YYPARSE_PARAM my_lily_parser_l
124 #define YYLEX_PARAM my_lily_parser_l
126 ((My_lily_parser *) my_lily_parser_l)
128 #define yyerror THIS->parser_error
129 #define ARRAY_SIZE(a,s) if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
136 Link_array<Request> *reqvec;
138 String *string; // needed by the lexer as temporary scratch area.
142 Scheme_hash_table *scmhash;
143 Music_output_def * outputdef;
147 /* We use SCMs to do strings, because it saves us the trouble of
148 deleting them. Let's hope that a stack overflow doesnt trigger a move
149 of the parse stack onto the heap. */
159 yylex (YYSTYPE *s, void * v_l)
161 My_lily_parser *pars_l = (My_lily_parser*) v_l;
162 My_lily_lexer * lex_l = pars_l->lexer_p_;
164 lex_l->lexval_l = (void*) s;
165 return lex_l->yylex ();
173 /* tokens which are not keywords */
183 %token CHORDMODIFIERS
191 %token GROBDESCRIPTIONS
197 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
207 %token MULTI_MEASURE_REST
219 %token OVERRIDE SET REVERT
232 %token COMMANDSPANREQUEST
234 %token OUTPUTPROPERTY
244 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE E_TILDE
246 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
248 %type <i> exclamations questions dots
249 %type <i> bass_number bass_mod
250 %type <scm> bass_figure figure_list figure_spec
252 %token <scm> NOTENAME_PITCH
253 %token <scm> TONICNAME_PITCH
254 %token <scm> CHORDMODIFIER_PITCH
255 %token <scm> DURATION_IDENTIFIER
256 %token <scm> FRACTION
257 %token <id> IDENTIFIER
260 %token <scm> SCORE_IDENTIFIER
261 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
263 %token <scm> NUMBER_IDENTIFIER
264 %token <scm> REQUEST_IDENTIFIER
265 %token <scm> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
266 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
267 %token <scm> RESTNAME
273 %type <outputdef> output_def
274 %type <scmhash> lilypond_header lilypond_header_body
275 %type <request> open_request_parens close_request_parens open_request close_request
276 %type <request> request_with_dir request_that_take_dir verbose_request
277 %type <i> sub_quotes sup_quotes
278 %type <music> simple_element request_chord command_element Simple_music Composite_music
279 %type <music> Repeated_music
280 %type <scm> Alternative_music
281 %type <i> tremolo_type
282 %type <i> bare_int bare_unsigned
285 %type <scm> identifier_init
287 %type <scm> steno_duration optional_notemode_duration multiplied_duration
288 %type <scm> verbose_duration
290 %type <reqvec> pre_requests post_requests
291 %type <request> gen_text_def
292 %type <scm> steno_pitch pitch absolute_pitch
293 %type <scm> explicit_pitch steno_tonic_pitch
295 %type <scm> chord_additions chord_subtractions chord_notes chord_step
297 %type <scm> chord_note chord_inversion chord_bass
298 %type <scm> duration_length fraction
300 %type <scm> embedded_scm scalar
301 %type <music> Music Sequential_music Simultaneous_music
302 %type <music> relative_music re_rhythmed_music part_combined_music
303 %type <music> property_def translator_change
304 %type <scm> Music_list
305 %type <outputdef> music_output_def_body
306 %type <request> shorthand_command_req
307 %type <request> post_request
308 %type <music> command_req verbose_command_req
309 %type <request> extender_req
310 %type <request> hyphen_req
311 %type <scm> string bare_number number_expression number_term number_factor
313 %type <score> score_block score_body
315 %type <scm> translator_spec_block translator_spec_body
316 %type <tempo> tempo_request
317 %type <scm> notenames_body notenames_block chordmodifiers_block
318 %type <scm> script_abbreviation
324 /* We don't assign precedence to / and *, because we might need varied
325 prec levels in different prods */
331 lilypond: /* empty */
332 | lilypond toplevel_expression {}
333 | lilypond assignment { }
335 THIS->error_level_i_ = 1;
338 THIS->error_level_i_ = 1;
344 THIS->lexer_p_->pitchname_tab_ = $1;
346 | chordmodifiers_block {
347 THIS->lexer_p_->chordmodifier_tab_ = $1;
351 scm_gc_unprotect_object (global_header_p->self_scm ());
352 global_header_p = $1;
355 score_global_array.push ($1);
358 if (dynamic_cast<Paper_def*> ($1))
359 THIS->lexer_p_->set_identifier ("$defaultpaper", $1->self_scm ());
360 else if (dynamic_cast<Midi_def*> ($1))
361 THIS->lexer_p_->set_identifier ("$defaultmidi", $1->self_scm ());
374 chordmodifiers_block:
375 CHORDMODIFIERS notenames_body { $$ = $2; }
379 PITCHNAMES notenames_body { $$ = $2; }
384 int i = scm_ilength ($1);
386 SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
387 for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) {
388 SCM pt = ly_cdar (s);
389 if (!unsmob_pitch (pt))
390 THIS->parser_error ("Need pitch object.");
392 scm_hashq_set_x (tab, ly_caar (s), pt);
399 lilypond_header_body:
401 $$ = new Scheme_hash_table;
403 Scope *sc = new Scope ($$);
404 THIS->lexer_p_-> scope_l_arr_.push (sc);
406 | lilypond_header_body assignment {
412 HEADER '{' lilypond_header_body '}' {
414 delete THIS->lexer_p_-> scope_l_arr_.pop ();
426 /* cont */ '=' identifier_init {
429 Should find generic way of associating input with objects.
431 Input ip = THIS->pop_spot ();
433 if (! regular_identifier_b ($1))
435 ip.warning (_ ("Identifier should have alphabetic characters only"));
438 THIS->lexer_p_->set_identifier (ly_scm2string ($1), $4);
441 TODO: devise standard for protection in parser.
443 The parser stack lives on the C-stack, which means that
444 all objects can be unprotected as soon as they're here.
454 $$ = $1->self_scm ();
455 scm_gc_unprotect_object ($$);
458 $$ = $1->self_scm ();
459 scm_gc_unprotect_object ($$);
461 | translator_spec_block {
465 $$ = $1->self_scm ();
466 scm_gc_unprotect_object ($$);
469 $$ = $1->self_scm ();
470 scm_gc_unprotect_object ($$);
475 | number_expression {
486 translator_spec_block:
487 TRANSLATOR '{' translator_spec_body '}'
493 translator_spec_body:
494 TRANSLATOR_IDENTIFIER {
495 $$ = unsmob_translator_def ($1)->clone_scm ();
496 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
499 $$ = Translator_def::make_scm ();
500 Translator_def*td = unsmob_translator_def ($$);
501 td->translator_group_type_ = $2;
502 td->set_spot (THIS->here_input ());
504 | translator_spec_body STRING '=' embedded_scm {
505 unsmob_translator_def ($$)->add_property_assign ($2, $4);
507 | translator_spec_body STRING OVERRIDE embedded_scm '=' embedded_scm {
508 unsmob_translator_def ($$)
509 ->add_push_property (scm_string_to_symbol ($2), $4, $6);
511 | translator_spec_body STRING REVERT embedded_scm {
512 unsmob_translator_def ($$)->add_pop_property (
513 scm_string_to_symbol ($2), $4);
515 | translator_spec_body NAME STRING {
516 unsmob_translator_def ($$)->type_name_ = $3;
518 | translator_spec_body CONSISTS STRING {
519 unsmob_translator_def ($$)->add_element ($3);
521 | translator_spec_body ALIAS STRING {
522 Translator_def*td = unsmob_translator_def ($$);
523 td->type_aliases_ = gh_cons ($3, td->type_aliases_);
525 | translator_spec_body GROBDESCRIPTIONS embedded_scm {
526 Translator_def*td = unsmob_translator_def($$);
527 // td->add_property_assign (ly_symbol2scm ("allGrobDescriptions"), $3);
528 for (SCM p = $3; gh_pair_p (p); p = ly_cdr (p))
529 td->add_property_assign (scm_symbol_to_string (ly_caar (p)), ly_cdar (p));
531 | translator_spec_body CONSISTSEND STRING {
532 unsmob_translator_def ($$)->add_last_element ( $3);
534 | translator_spec_body ACCEPTS STRING {
535 unsmob_translator_def ($$)->set_acceptor ($3,true);
537 | translator_spec_body DENIES STRING {
538 unsmob_translator_def ($$)->set_acceptor ($3,false);
540 | translator_spec_body REMOVE STRING {
541 unsmob_translator_def ($$)->remove_element ($3);
552 /*cont*/ '{' score_body '}' {
555 if (!$$->def_p_arr_.size ())
557 Music_output_def *id =
558 unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
559 $$->add_output (id ? id->clone () : new Paper_def );
568 $$->set_spot (THIS->here_input ());
569 SCM m = $1->self_scm ();
570 scm_gc_unprotect_object (m);
574 $$ = new Score (*unsmob_score ($1));
575 $$->set_spot (THIS->here_input ());
577 | score_body lilypond_header {
578 scm_gc_unprotect_object ($2->self_scm ());
581 | score_body output_def {
594 music_output_def_body '}' {
596 THIS-> lexer_p_-> scope_l_arr_.pop ();
600 music_output_def_body:
602 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
607 p = dynamic_cast<Midi_def*> (id->clone ());
612 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
615 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
618 p = dynamic_cast<Paper_def*> (id->clone ());
621 THIS-> lexer_p_-> scope_l_arr_.push (p->scope_p_);
624 | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
625 Music_output_def *p = unsmob_music_output_def ($3);
627 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
630 | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
631 Music_output_def *p = unsmob_music_output_def ($3);
634 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
637 | music_output_def_body assignment {
640 | music_output_def_body translator_spec_block {
641 $$->assign_translator ($2);
643 | music_output_def_body STYLESHEET embedded_scm {
644 dynamic_cast<Paper_def*> ($$)-> style_sheet_ = $3;
646 | music_output_def_body tempo_request {
648 junk this ? there already is tempo stuff in
651 int m = gh_scm2int ( $2->get_mus_property ("metronome-count"));
652 Duration *d = unsmob_duration ($2->get_mus_property ("duration"));
653 dynamic_cast<Midi_def*> ($$)->set_tempo (d->length_mom (), m);
655 | music_output_def_body error {
661 TEMPO steno_duration '=' bare_unsigned {
663 $$->set_mus_property ("duration", $2);
664 $$->set_mus_property ("metronome-count", gh_int2scm ( $4));
669 The representation of a list is the
673 to have efficient append.
675 Music_list: /* empty */ {
676 $$ = gh_cons (SCM_EOL, SCM_EOL);
680 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
681 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
682 if (gh_pair_p (ly_cdr (s)))
683 gh_set_cdr_x (ly_cdr (s), c); /* append */
685 gh_set_car_x (s, c); /* set first cons */
686 gh_set_cdr_x (s, c) ; /* remember last cell */
702 | ALTERNATIVE '{' Music_list '}' {
708 REPEAT string bare_unsigned Music Alternative_music
712 SCM alts = gh_pair_p ($5) ? gh_car ($5) : SCM_EOL;
713 if (times < scm_ilength (alts)) {
714 unsmob_music (gh_car (alts))
715 ->origin ()->warning (
716 _("More alternatives than repeats. Junking excess alternatives."));
717 alts = ly_truncate_list (times, alts);
720 Repeated_music * r = new Repeated_music (SCM_EOL);
723 r-> set_mus_property ("element", beg->self_scm ());
724 scm_gc_unprotect_object (beg->self_scm ());
726 r->set_mus_property ("repeat-count", gh_int2scm (times >? 1));
728 r-> set_mus_property ("elements",alts);
729 SCM func = scm_primitive_eval (ly_symbol2scm ("repeat-name-to-ctor"));
730 SCM result = gh_call1 (func, $2);
732 set_music_properties (r, result);
734 r->set_spot (*$4->origin ());
740 SEQUENTIAL '{' Music_list '}' {
741 $$ = new Sequential_music (SCM_EOL);
742 $$->set_mus_property ("elements", ly_car ($3));
744 | '{' Music_list '}' {
745 $$ = new Sequential_music (SCM_EOL);
746 $$->set_mus_property ("elements", ly_car ($2));
751 SIMULTANEOUS '{' Music_list '}'{
752 $$ = new Simultaneous_music (SCM_EOL);
753 $$->set_mus_property ("elements", ly_car ($3));
756 | '<' Music_list '>' {
757 $$ = new Simultaneous_music (SCM_EOL);
758 $$->set_mus_property ("elements", ly_car ($2));
763 request_chord { $$ = $1; }
764 | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm {
766 if (!gh_symbol_p ($3))
768 THIS->parser_error (_ ("Second argument must be a symbol"));
770 /*hould check # args */
771 if (!gh_procedure_p (pred))
773 THIS->parser_error (_ ("First argument must be a procedure taking 1 argument"));
776 Music *m = new Music (SCM_EOL);
777 m->set_mus_property ("predicate", pred);
778 m->set_mus_property ("grob-property", $3);
779 m->set_mus_property ("grob-value", $5);
780 m->set_mus_property ("iterator-ctor",
781 Output_property_music_iterator::constructor_cxx_function);
786 $$ = unsmob_music ($1)->clone ();
794 CONTEXT STRING Music {
795 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
796 csm->set_mus_property ("element", $3->self_scm ());
797 scm_gc_unprotect_object ($3->self_scm ());
799 csm->set_mus_property ("context-type",$2);
800 csm->set_mus_property ("context-id", ly_str02scm (""));
804 | AUTOCHANGE STRING Music {
805 Music * chm = new Music_wrapper (SCM_EOL);
806 chm->set_mus_property ("element", $3->self_scm ());
807 chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_cxx_function);
809 scm_gc_unprotect_object ($3->self_scm ());
810 chm->set_mus_property ("what", $2);
813 chm->set_spot (*$3->origin ());
818 The other version is for easier debugging of
819 Sequential_music_iterator in combination with grace notes.
822 SCM start = THIS->lexer_p_->lookup_identifier ("startGraceMusic");
823 SCM stop = THIS->lexer_p_->lookup_identifier ("stopGraceMusic");
824 Music *startm = unsmob_music (start);
825 Music *stopm = unsmob_music (stop);
829 stopm = stopm->clone ();
830 ms = gh_cons (stopm->self_scm (), ms);
831 scm_gc_unprotect_object (stopm->self_scm ());
833 ms = gh_cons ($2->self_scm (), ms);
834 scm_gc_unprotect_object ($2->self_scm());
836 startm = startm->clone ();
837 ms = gh_cons (startm->self_scm () , ms);
838 scm_gc_unprotect_object (startm->self_scm ());
841 Music* seq = new Sequential_music (SCM_EOL);
842 seq->set_mus_property ("elements", ms);
844 $$ = new Grace_music (SCM_EOL);
845 $$->set_mus_property ("element", seq->self_scm ());
846 scm_gc_unprotect_object (seq->self_scm ());
848 $$ = new Grace_music (SCM_EOL);
849 $$->set_mus_property ("element", $2->self_scm ());
850 scm_gc_unprotect_object ($2->self_scm ());
853 | CONTEXT string '=' string Music {
854 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
855 csm->set_mus_property ("element", $5->self_scm ());
856 scm_gc_unprotect_object ($5->self_scm ());
858 csm->set_mus_property ("context-type", $2);
859 csm->set_mus_property ("context-id", $4);
870 int n = gh_scm2int (ly_car ($3)); int d = gh_scm2int (ly_cdr ($3));
872 $$ = new Time_scaled_music (SCM_EOL);
873 $$->set_spot (THIS->pop_spot ());
876 $$->set_mus_property ("element", mp->self_scm ());
877 scm_gc_unprotect_object (mp->self_scm ());
878 $$->set_mus_property ("numerator", gh_int2scm (n));
879 $$->set_mus_property ("denominator", gh_int2scm (d));
880 $$->compress (Moment (Rational (n,d)));
883 | Repeated_music { $$ = $1; }
884 | Simultaneous_music { $$ = $1; }
885 | Sequential_music { $$ = $1; }
886 | TRANSPOSE pitch Music {
887 $$ = new Transposed_music (SCM_EOL);
889 Pitch pit = *unsmob_pitch ($2);
892 $$->set_mus_property ("element", p->self_scm ());
893 scm_gc_unprotect_object (p->self_scm ());
895 | TRANSPOSE steno_tonic_pitch Music {
896 $$ = new Transposed_music (SCM_EOL);
898 Pitch pit = *unsmob_pitch ($2);
901 $$->set_mus_property ("element", p->self_scm ());
902 scm_gc_unprotect_object (p->self_scm ());
905 | APPLY embedded_scm Music {
906 SCM ret = gh_call1 ($2, $3->self_scm ());
907 Music *m = unsmob_music (ret);
909 THIS->parser_error ("\\apply must return a Music");
910 m = new Music (SCM_EOL);
915 { THIS->lexer_p_->push_note_state (); }
918 THIS->lexer_p_->pop_state ();
921 { THIS->lexer_p_->push_figuredbass_state (); }
924 Music * chm = new Untransposable_music () ;
925 chm->set_mus_property ("element", $3->self_scm ());
928 THIS->lexer_p_->pop_state ();
931 { THIS->lexer_p_->push_chord_state (); }
934 Music * chm = new Un_relativable_music ;
935 chm->set_mus_property ("element", $3->self_scm ());
938 THIS->lexer_p_->pop_state ();
941 { THIS->lexer_p_->push_lyric_state (); }
945 THIS->lexer_p_->pop_state ();
947 | relative_music { $$ = $1; }
948 | re_rhythmed_music { $$ = $1; }
949 | part_combined_music { $$ = $1; }
953 RELATIVE absolute_pitch Music {
955 Pitch pit = *unsmob_pitch ($2);
956 $$ = new Relative_octave_music (SCM_EOL);
958 $$->set_mus_property ("element", p->self_scm ());
959 scm_gc_unprotect_object (p->self_scm ());
961 $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ());
967 ADDLYRICS Music Music {
968 Lyric_combine_music * l = new Lyric_combine_music (SCM_EOL);
969 l->set_mus_property ("elements", gh_list ($2->self_scm (), $3->self_scm (), SCM_UNDEFINED));
970 scm_gc_unprotect_object ($3->self_scm ());
971 scm_gc_unprotect_object ($2->self_scm ());
977 PARTCOMBINE STRING Music Music {
978 Part_combine_music * p = new Part_combine_music (SCM_EOL);
980 p->set_mus_property ("what", $2);
981 p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED));
983 scm_gc_unprotect_object ($3->self_scm ());
984 scm_gc_unprotect_object ($4->self_scm ());
991 TRANSLATOR STRING '=' STRING {
992 Music * t = new Music (SCM_EOL);
993 t->set_mus_property ("iterator-ctor",
994 Change_iterator::constructor_cxx_function);
995 t-> set_mus_property ("change-to-type", $2);
996 t-> set_mus_property ("change-to-id", $4);
999 $$->set_spot (THIS->here_input ());
1004 PROPERTY STRING '.' STRING '=' scalar {
1006 Music *t = set_property_music (scm_string_to_symbol ($4), $6);
1007 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1009 csm->set_mus_property ("element", t->self_scm ());
1010 scm_gc_unprotect_object (t->self_scm ());
1013 $$->set_spot (THIS->here_input ());
1015 csm-> set_mus_property ("context-type", $2);
1017 | PROPERTY STRING '.' STRING UNSET {
1018 Music *t = new Music (SCM_EOL);
1020 t->set_mus_property ("iterator-ctor",
1021 Property_unset_iterator::constructor_cxx_function);
1022 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1024 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1025 csm->set_mus_property ("element", t->self_scm ());
1026 scm_gc_unprotect_object (t->self_scm ());
1029 $$->set_spot (THIS->here_input ());
1031 csm-> set_mus_property ("context-type", $2);
1033 | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm {
1034 Music *t = new Music (SCM_EOL);
1035 t->set_mus_property ("iterator-ctor",
1036 Push_property_iterator::constructor_cxx_function);
1037 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1038 t->set_mus_property ("pop-first", SCM_BOOL_T);
1039 t->set_mus_property ("grob-property", $6);
1040 t->set_mus_property ("grob-value", $8);
1041 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1042 csm->set_mus_property ("element", t->self_scm ());
1043 scm_gc_unprotect_object (t->self_scm ());
1045 $$->set_spot (THIS->here_input ());
1047 csm-> set_mus_property ("context-type", $2);
1049 | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
1050 Music *t = new Music (SCM_EOL);
1051 t->set_mus_property ("iterator-ctor",
1052 Push_property_iterator::constructor_cxx_function);
1053 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1054 t->set_mus_property ("grob-property", $6);
1055 t->set_mus_property ("grob-value", $8);
1056 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1057 csm->set_mus_property ("element", t->self_scm ());
1058 scm_gc_unprotect_object (t->self_scm ());
1061 $$->set_spot (THIS->here_input ());
1063 csm-> set_mus_property ("context-type", $2);
1065 | PROPERTY STRING '.' STRING REVERT embedded_scm {
1066 Music *t = new Music (SCM_EOL);
1067 t->set_mus_property ("iterator-ctor",
1068 Pop_property_iterator::constructor_cxx_function);
1069 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1070 t->set_mus_property ("grob-property", $6);
1072 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1073 csm->set_mus_property ("element", t->self_scm ());
1074 scm_gc_unprotect_object (t->self_scm ());
1077 $$->set_spot (THIS->here_input ());
1079 csm-> set_mus_property ("context-type", $2);
1085 | bare_int { $$ = gh_int2scm ($1); }
1086 | embedded_scm { $$ = $1; }
1093 } /*cont */ simple_element post_requests {
1094 Music_sequence *l = dynamic_cast<Music_sequence*> ($3);
1097 for (int i=0; i < $1->size (); i++) {
1098 Music * m = $1->elem (i);
1099 l->append_music (m);
1111 $$ = new Request_chord (SCM_EOL);
1112 $$->set_mus_property ("elements", gh_cons ($1->self_scm (), SCM_EOL));
1113 $$-> set_spot (THIS->here_input ());
1114 $1-> set_spot (THIS->here_input ());
1117 $$ = new Music (gh_list (gh_cons (ly_symbol2scm ("name"), ly_symbol2scm ("separator")), SCM_UNDEFINED));
1118 $$->set_spot (THIS->here_input ());
1122 extern Music * get_barcheck();
1123 $$ = get_barcheck ();
1124 $$->set_spot (THIS->here_input ());
1127 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1129 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1130 csm->set_mus_property ("element", t->self_scm ());
1131 scm_gc_unprotect_object (t->self_scm ());
1134 $$->set_spot (THIS->here_input ());
1136 csm->set_mus_property ("context-type", ly_str02scm ("Score"));
1138 | PARTIAL duration_length {
1139 Moment m = - unsmob_duration ($2)->length_mom ();
1140 Music * p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1142 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1143 sp->set_mus_property ("element", p->self_scm ());
1144 scm_gc_unprotect_object (p->self_scm ());
1147 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1150 SCM func = scm_primitive_eval (ly_symbol2scm ("clef-name-to-properties"));
1151 SCM result = gh_call1 (func, $2);
1154 for (SCM s = result ; gh_pair_p (s); s = ly_cdr (s)) {
1155 Music * p = new Music (SCM_EOL);
1156 set_music_properties (p, ly_car (s));
1157 l = gh_cons (p->self_scm (), l);
1158 scm_gc_unprotect_object (p->self_scm ());
1160 Sequential_music * seq = new Sequential_music (SCM_EOL);
1161 seq->set_mus_property ("elements", l);
1163 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1164 sp->set_mus_property ("element", seq->self_scm ());
1165 scm_gc_unprotect_object (seq->self_scm ());
1168 sp-> set_mus_property ("context-type", ly_str02scm ("Staff"));
1171 Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2);
1173 int l = gh_scm2int (ly_car ($2));
1174 int o = gh_scm2int (ly_cdr ($2));
1176 Moment one_beat = Moment (1)/Moment (o);
1177 Moment len = Moment (l) * one_beat;
1180 Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ());
1181 Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ());
1183 SCM list = scm_list_n (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED);
1184 Sequential_music *seq = new Sequential_music (SCM_EOL);
1185 seq->set_mus_property ("elements", list);
1188 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1189 sp->set_mus_property ("element", seq->self_scm ());
1193 scm_gc_unprotect_object (p3->self_scm ());
1194 scm_gc_unprotect_object (p2->self_scm ());
1195 scm_gc_unprotect_object (p1->self_scm ());
1196 scm_gc_unprotect_object (seq->self_scm ());
1201 TODO: should make alias TimingContext for Score
1204 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1209 shorthand_command_req { $$ = $1; }
1210 | verbose_command_req { $$ = $1; }
1213 shorthand_command_req:
1224 Span_req*b= new Span_req;
1225 b->set_span_dir (START);
1226 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1230 THIS->last_beam_start_ = b->self_scm ();
1233 Span_req*b= new Span_req;
1234 b->set_span_dir ( STOP);
1235 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1239 $$ = new Breathing_sign_req;
1242 $$ = new Porrectus_req;
1246 verbose_command_req:
1247 COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1248 Span_req * sp_p = new Span_req;
1249 sp_p-> set_span_dir ( Direction ($2));
1250 sp_p->set_mus_property ("span-type",$3);
1251 sp_p->set_spot (THIS->here_input ());
1255 Mark_req * m = new Mark_req;
1259 Mark_req *m = new Mark_req;
1260 m->set_mus_property ("label", $2);
1265 Break_req * b = new Break_req;
1267 if (!gh_number_p (s))
1270 b->set_mus_property ("penalty", s);
1271 b->set_spot (THIS->here_input ());
1274 | SKIP duration_length {
1275 Skip_req * skip_p = new Skip_req;
1276 skip_p->set_mus_property ("duration", $2);
1284 Key_change_req *key_p= new Key_change_req;
1287 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1288 Key_change_req *key_p= new Key_change_req;
1290 key_p->set_mus_property ("pitch-alist", $3);
1291 ((Music*)key_p)->transpose (* unsmob_pitch ($2));
1298 $$ = new Link_array<Request>;
1300 | post_requests post_request {
1301 $2->set_spot (THIS->here_input ());
1313 request_that_take_dir:
1316 | script_abbreviation {
1317 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1318 Articulation_req *a = new Articulation_req;
1319 if (gh_string_p (s))
1320 a->set_mus_property ("articulation-type", s);
1321 else THIS->parser_error (_ ("Expecting string as script definition"));
1327 script_dir request_that_take_dir {
1328 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1329 gs->set_direction (Direction ($1));
1331 $2->origin ()->warning (_ ("Can't specify direction for this request"));
1337 REQUEST_IDENTIFIER {
1338 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1339 $$->set_spot (THIS->here_input ());
1341 | DYNAMICSCRIPT embedded_scm {
1343 TODO: junkme, use text-type == dynamic
1345 Text_script_req *d = new Text_script_req;
1346 SCM dyn = ly_symbol2scm ("dynamic");
1347 d->set_mus_property ("text-type" , dyn);
1348 d->set_mus_property ("text", $2);
1349 d->set_spot (THIS->here_input ());
1352 | SPANREQUEST bare_int STRING {
1353 Span_req * sp_p = new Span_req;
1354 sp_p->set_span_dir ( Direction ($2));
1355 sp_p->set_mus_property ("span-type", $3);
1356 sp_p->set_spot (THIS->here_input ());
1360 Tremolo_req* a = new Tremolo_req;
1361 a->set_spot (THIS->here_input ());
1362 a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1366 Articulation_req * a = new Articulation_req;
1367 a->set_mus_property ("articulation-type", $2);
1368 a->set_spot (THIS->here_input ());
1372 duh, junk this syntax from the parser, if possible.
1375 Arpeggio_req *a = new Arpeggio_req;
1376 a->set_spot (THIS->here_input ());
1380 Glissando_req *g = new Glissando_req;
1381 g->set_spot /* No pun intended */ (THIS->here_input ());
1408 | NOTENAME_PITCH sup_quotes {
1409 Pitch p = *unsmob_pitch ($1);
1411 $$ = p.smobbed_copy ();
1413 | NOTENAME_PITCH sub_quotes {
1414 Pitch p =* unsmob_pitch ($1);
1417 $$ = p.smobbed_copy ();
1430 | TONICNAME_PITCH sup_quotes {
1431 Pitch p = *unsmob_pitch ($1);
1433 $$ = p.smobbed_copy ();
1435 | TONICNAME_PITCH sub_quotes {
1436 Pitch p =* unsmob_pitch ($1);
1439 $$ = p.smobbed_copy ();
1454 PITCH embedded_scm {
1456 if (!unsmob_pitch ($2)) {
1457 THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1458 $$ = Pitch ().smobbed_copy ();
1464 DURATION embedded_scm {
1466 if (!unsmob_duration ($2))
1468 THIS->parser_error (_ ("Must have duration object"));
1469 $$ = Duration ().smobbed_copy ();
1476 if (!THIS->lexer_p_->lyric_state_b ())
1477 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1478 $$ = new Extender_req;
1484 if (!THIS->lexer_p_->lyric_state_b ())
1485 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1486 $$ = new Hyphen_req;
1491 close_request_parens {
1493 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1496 close_request_parens:
1498 Span_req* s= new Span_req;
1500 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1503 Span_req* s= new Span_req;
1505 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1508 Span_req*s =new Span_req;
1510 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1513 Span_req*s =new Span_req;
1515 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1521 open_request_parens {
1523 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1527 open_request_parens:
1529 Span_req *s = new Span_req;
1530 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1535 Span_req* s= new Span_req;
1537 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1540 Span_req* s= new Span_req;
1542 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1548 Text_script_req *t = new Text_script_req;
1549 t->set_mus_property ("text", $1);
1550 t->set_spot (THIS->here_input ());
1554 Text_script_req *t = new Text_script_req;
1555 t->set_mus_property ("text", $1);
1556 t->set_spot (THIS->here_input ());
1560 String ds = to_str ($1);
1561 Text_script_req* t = new Text_script_req;
1562 SCM finger = ly_symbol2scm ("finger");
1563 t->set_mus_property ("text", ly_str02scm (ds.ch_C ()));
1564 t->set_mus_property ("text-type" , finger);
1565 t->set_spot (THIS->here_input ());
1570 script_abbreviation:
1572 $$ = gh_str02scm ("Hat");
1575 $$ = gh_str02scm ("Plus");
1578 $$ = gh_str02scm ("Dash");
1581 $$ = gh_str02scm ("Bar");
1584 $$ = gh_str02scm ("Larger");
1587 $$ = gh_str02scm ("Dot");
1594 | '-' { $$ = CENTER; }
1599 $$ = new Link_array<Request>;
1601 | pre_requests open_request {
1613 multiplied_duration {
1616 | verbose_duration {
1621 optional_notemode_duration:
1623 Duration dd = THIS->default_duration_;
1624 $$ = dd.smobbed_copy ();
1626 THIS->beam_check ($$);
1628 | multiplied_duration {
1630 THIS->default_duration_ = *unsmob_duration ($$);
1632 THIS->beam_check ($$);
1634 | verbose_duration {
1636 THIS->default_duration_ = *unsmob_duration ($$);
1641 bare_unsigned dots {
1643 if (!is_duration_b ($1))
1644 THIS->parser_error (_f ("not a duration: %d", $1));
1648 $$ = Duration (l, $2).smobbed_copy ();
1650 | DURATION_IDENTIFIER dots {
1651 Duration *d =unsmob_duration ($1);
1652 Duration k (d->duration_log (),d->dot_count () + $2);
1653 $$ = k.smobbed_copy ();
1660 multiplied_duration:
1664 | multiplied_duration '*' bare_unsigned {
1665 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1667 | multiplied_duration '*' FRACTION {
1668 Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr ($3)));
1670 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1675 FRACTION { $$ = $1; }
1676 | UNSIGNED '/' UNSIGNED {
1677 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1695 | ':' bare_unsigned {
1696 if (!is_duration_b ($2))
1697 THIS->parser_error (_f ("not a duration: %d", $2));
1717 p .notename_i_ = $1 - 1;
1720 Note_req * nr = new Note_req;
1721 $$ = nr->self_scm ();
1722 nr->set_mus_property ("pitch", p.smobbed_copy ());
1723 scm_gc_unprotect_object ($$);
1725 | bass_figure bass_mod {
1727 SCM sp = unsmob_music ($1)->get_mus_property ("pitch");
1728 unsmob_pitch (sp)->alteration_i_ += $2;
1730 unsmob_music ($1)->set_mus_property ("force-accidental", SCM_BOOL_T);
1739 | figure_list bass_figure {
1740 $$ = gh_cons ($2, $1);
1745 FIGURE_OPEN figure_list FIGURE_CLOSE {
1746 Music * m = new Request_chord (SCM_EOL);
1747 $2 = scm_reverse_x ($2, SCM_EOL);
1748 m->set_mus_property ("elements", $2);
1749 $$ = m->self_scm ();
1754 pitch exclamations questions optional_notemode_duration {
1756 Input i = THIS->pop_spot ();
1757 if (!THIS->lexer_p_->note_state_b ())
1758 THIS->parser_error (_ ("Have to be in Note mode for notes"));
1760 Note_req *n = new Note_req;
1762 n->set_mus_property ("pitch", $1);
1763 n->set_mus_property ("duration", $4);
1766 n->set_mus_property ("cautionary", SCM_BOOL_T);
1767 if ($2 % 2 || $3 % 2)
1768 n->set_mus_property ("force-accidental", SCM_BOOL_T);
1770 Simultaneous_music*v = new Request_chord (SCM_EOL);
1771 v->set_mus_property ("elements", scm_list_n (n->self_scm (), SCM_UNDEFINED));
1777 | figure_spec optional_notemode_duration {
1778 Music * m = unsmob_music ($1);
1779 Input i = THIS->pop_spot ();
1781 for (SCM s = m->get_mus_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
1783 unsmob_music (ly_car (s))->set_mus_property ("duration", $2);
1787 | RESTNAME optional_notemode_duration {
1789 Input i = THIS->pop_spot ();
1790 SCM e = SCM_UNDEFINED;
1791 if (ly_scm2string ($1) =="s") {
1793 Skip_req * skip_p = new Skip_req;
1794 skip_p->set_mus_property ("duration" ,$2);
1795 skip_p->set_spot (i);
1796 e = skip_p->self_scm ();
1799 Rest_req * rest_req_p = new Rest_req;
1800 rest_req_p->set_mus_property ("duration", $2);
1801 rest_req_p->set_spot (i);
1802 e = rest_req_p->self_scm ();
1804 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1805 velt_p-> set_mus_property ("elements", scm_list_n (e,SCM_UNDEFINED));
1806 velt_p->set_spot (i);
1810 | MULTI_MEASURE_REST optional_notemode_duration {
1811 Input i = THIS->pop_spot ();
1813 Skip_req * sk = new Skip_req;
1814 sk->set_mus_property ("duration", $2);
1815 Span_req *sp1 = new Span_req;
1816 Span_req *sp2 = new Span_req;
1817 sp1-> set_span_dir ( START);
1818 sp2-> set_span_dir ( STOP);
1819 SCM r = ly_str02scm ("rest");
1820 sp1->set_mus_property ("span-type", r);
1821 sp2->set_mus_property ("span-type", r);
1823 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1824 rqc1->set_mus_property ("elements", scm_list_n (sp1->self_scm (), SCM_UNDEFINED));
1825 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1826 rqc2->set_mus_property ("elements", scm_list_n (sk->self_scm (), SCM_UNDEFINED));;
1827 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1828 rqc3->set_mus_property ("elements", scm_list_n (sp2->self_scm (), SCM_UNDEFINED));;
1830 SCM ms = scm_list_n (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1832 $$ = new Sequential_music (SCM_EOL);
1833 $$->set_mus_property ("elements", ms);
1835 | STRING optional_notemode_duration {
1836 Input i = THIS->pop_spot ();
1838 Lyric_req* lreq_p = new Lyric_req;
1839 lreq_p->set_mus_property ("text", $1);
1840 lreq_p->set_mus_property ("duration",$2);
1841 lreq_p->set_spot (i);
1842 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1843 velt_p->set_mus_property ("elements", scm_list_n (lreq_p->self_scm (), SCM_UNDEFINED));
1848 Input i = THIS->pop_spot ();
1850 if (!THIS->lexer_p_->chord_state_b ())
1851 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1858 steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1859 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1860 $$->set_spot (THIS->here_input ());
1867 | CHORD_COLON chord_notes {
1876 | chord_notes '.' chord_step {
1877 $$ = gh_append2 ($$, $3);
1885 | CHORD_CARET chord_notes {
1895 | '/' steno_tonic_pitch {
1904 | CHORD_BASS steno_tonic_pitch {
1911 $$ = gh_cons ($1, SCM_EOL);
1913 | CHORDMODIFIER_PITCH {
1914 $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
1916 | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1917 $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
1925 m.notename_i_ = ($1 - 1) % 7;
1926 m.octave_i_ = $1 > 7 ? 1 : 0;
1927 m.alteration_i_ = 0;
1929 $$ = m.smobbed_copy ();
1931 | bare_unsigned '+' {
1933 m.notename_i_ = ($1 - 1) % 7;
1934 m.octave_i_ = $1 > 7 ? 1 : 0;
1935 m.alteration_i_ = 1;
1938 $$ = m.smobbed_copy ();
1940 | bare_unsigned CHORD_MINUS {
1942 m.notename_i_ = ($1 - 1) % 7;
1943 m.octave_i_ = $1 > 7 ? 1 : 0;
1944 m.alteration_i_ = -1;
1946 $$ = m.smobbed_copy ();
1954 number_expression '+' number_term {
1955 $$ = scm_sum ($1, $3);
1957 | number_expression '-' number_term {
1958 $$ = scm_difference ($1, $3);
1967 | number_factor '*' number_factor {
1968 $$ = scm_product ($1, $3);
1970 | number_factor '/' number_factor {
1971 $$ = scm_divide ($1, $3);
1976 '(' number_expression ')' {
1979 | '-' number_factor { /* %prec UNARY_MINUS */
1980 $$ = scm_difference ($2, SCM_UNDEFINED);
1988 $$ = gh_int2scm ($1);
1993 | NUMBER_IDENTIFIER {
1997 $$ = gh_double2scm (gh_scm2double ($1) CM );
2000 $$ = gh_double2scm (gh_scm2double ($1) PT);
2003 $$ = gh_double2scm (gh_scm2double ($1) INCH);
2006 $$ = gh_double2scm (gh_scm2double ($1) MM);
2009 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
2025 if (scm_integer_p ($1) == SCM_BOOL_T)
2027 int k = gh_scm2int ($1);
2031 THIS->parser_error (_ ("need integer number arg"));
2045 | STRING_IDENTIFIER {
2048 | string '+' string {
2049 $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
2056 | exclamations '!' { $$ ++; }
2061 | questions '?' { $$ ++; }
2068 My_lily_parser::set_yydebug (bool b)
2075 extern My_lily_parser * current_parser;
2078 My_lily_parser::do_yyparse ()
2081 current_parser = this;;
2082 yyparse ((void*)this);
2087 Should make this optional? It will also complain when you do
2091 which is entirely legitimate.
2093 Or we can scrap it. Barchecks should detect wrong durations, and
2094 skipTypesetting speeds it up a lot.
2097 My_lily_parser::beam_check (SCM dur)
2099 Duration *d = unsmob_duration (dur);
2100 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2102 Music * m = unsmob_music (last_beam_start_);
2103 m->origin ()->warning (_("Suspect duration found following this beam"));
2105 last_beam_start_ = SCM_EOL;