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 ()
124 #define YYERROR_VERBOSE 1
126 #define YYPARSE_PARAM my_lily_parser_l
127 #define YYLEX_PARAM my_lily_parser_l
129 ((My_lily_parser *) my_lily_parser_l)
131 #define yyerror THIS->parser_error
132 #define ARRAY_SIZE(a,s) if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
136 /* We use SCMs to do strings, because it saves us the trouble of
137 deleting them. Let's hope that a stack overflow doesnt trigger a move
138 of the parse stack onto the heap. */
143 Link_array<Request> *reqvec;
145 String *string; // needed by the lexer as temporary scratch area.
149 Scheme_hash_table *scmhash;
150 Music_output_def * outputdef;
162 yylex (YYSTYPE *s, void * v_l)
164 My_lily_parser *pars_l = (My_lily_parser*) v_l;
165 My_lily_lexer * lex_l = pars_l->lexer_p_;
167 lex_l->lexval_l = (void*) s;
168 return lex_l->yylex ();
176 /* tokens which are not keywords */
186 %token CHORDMODIFIERS
194 %token GROBDESCRIPTIONS
200 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
201 %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
211 %token MULTI_MEASURE_REST
223 %token OVERRIDE SET REVERT
236 %token COMMANDSPANREQUEST
238 %token OUTPUTPROPERTY
249 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE E_TILDE
251 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
255 %type <i> exclamations questions dots optional_rest
256 %type <i> bass_number bass_mod
257 %type <scm> br_bass_figure bass_figure figure_list figure_spec
259 %token <scm> NOTENAME_PITCH
260 %token <scm> TONICNAME_PITCH
261 %token <scm> CHORDMODIFIER_PITCH
262 %token <scm> DURATION_IDENTIFIER
263 %token <scm> FRACTION
264 %token <id> IDENTIFIER
267 %token <scm> SCORE_IDENTIFIER
268 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
270 %token <scm> NUMBER_IDENTIFIER
271 %token <scm> REQUEST_IDENTIFIER
272 %token <scm> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
273 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
274 %token <scm> RESTNAME
280 %type <outputdef> output_def
281 %type <scmhash> lilypond_header lilypond_header_body
282 %type <request> open_request_parens close_request_parens open_request close_request
283 %type <request> request_with_dir request_that_take_dir verbose_request
284 %type <i> sub_quotes sup_quotes
285 %type <music> simple_element request_chord command_element Simple_music Composite_music
286 %type <music> Repeated_music
287 %type <scm> Alternative_music
288 %type <i> tremolo_type
289 %type <i> bare_int bare_unsigned
292 %type <scm> identifier_init
294 %type <scm> steno_duration optional_notemode_duration multiplied_duration
295 %type <scm> verbose_duration
297 %type <reqvec> pre_requests post_requests
298 %type <request> gen_text_def
299 %type <scm> steno_pitch pitch absolute_pitch
300 %type <scm> explicit_pitch steno_tonic_pitch
302 %type <scm> chord_additions chord_subtractions chord_notes chord_step
304 %type <scm> chord_note chord_inversion chord_bass
305 %type <scm> duration_length fraction
307 %type <scm> embedded_scm scalar
308 %type <music> Music Sequential_music Simultaneous_music
309 %type <music> relative_music re_rhythmed_music part_combined_music
310 %type <music> property_def translator_change
311 %type <scm> Music_list
312 %type <outputdef> music_output_def_body
313 %type <request> shorthand_command_req
314 %type <request> post_request
315 %type <music> command_req verbose_command_req
316 %type <request> extender_req
317 %type <request> hyphen_req
318 %type <scm> string bare_number number_expression number_term number_factor
320 %type <score> score_block score_body
322 %type <scm> translator_spec_block translator_spec_body
323 %type <tempo> tempo_request
324 %type <scm> notenames_body notenames_block chordmodifiers_block
325 %type <scm> script_abbreviation
331 /* We don't assign precedence to / and *, because we might need varied
332 prec levels in different prods */
338 lilypond: /* empty */
339 | lilypond toplevel_expression {}
340 | lilypond assignment { }
342 THIS->error_level_i_ = 1;
345 THIS->error_level_i_ = 1;
351 THIS->lexer_p_->pitchname_tab_ = $1;
353 | chordmodifiers_block {
354 THIS->lexer_p_->chordmodifier_tab_ = $1;
358 scm_gc_unprotect_object (global_header_p->self_scm ());
359 global_header_p = $1;
362 score_global_array.push ($1);
365 if (dynamic_cast<Paper_def*> ($1))
366 THIS->lexer_p_->set_identifier ("$defaultpaper", $1->self_scm ());
367 else if (dynamic_cast<Midi_def*> ($1))
368 THIS->lexer_p_->set_identifier ("$defaultmidi", $1->self_scm ());
381 chordmodifiers_block:
382 CHORDMODIFIERS notenames_body { $$ = $2; }
386 PITCHNAMES notenames_body { $$ = $2; }
391 int i = scm_ilength ($1);
393 SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
394 for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) {
395 SCM pt = ly_cdar (s);
396 if (!unsmob_pitch (pt))
397 THIS->parser_error ("Need pitch object.");
399 scm_hashq_set_x (tab, ly_caar (s), pt);
406 lilypond_header_body:
408 $$ = new Scheme_hash_table;
410 Scope *sc = new Scope ($$);
411 THIS->lexer_p_-> scope_l_arr_.push (sc);
413 | lilypond_header_body assignment {
419 HEADER '{' lilypond_header_body '}' {
421 delete THIS->lexer_p_-> scope_l_arr_.pop ();
433 /* cont */ '=' identifier_init {
436 Should find generic way of associating input with objects.
438 Input ip = THIS->pop_spot ();
440 if (! regular_identifier_b ($1))
442 ip.warning (_ ("Identifier should have alphabetic characters only"));
445 THIS->lexer_p_->set_identifier (ly_scm2string ($1), $4);
448 TODO: devise standard for protection in parser.
450 The parser stack lives on the C-stack, which means that
451 all objects can be unprotected as soon as they're here.
461 $$ = $1->self_scm ();
462 scm_gc_unprotect_object ($$);
465 $$ = $1->self_scm ();
466 scm_gc_unprotect_object ($$);
468 | translator_spec_block {
472 $$ = $1->self_scm ();
473 scm_gc_unprotect_object ($$);
476 $$ = $1->self_scm ();
477 scm_gc_unprotect_object ($$);
482 | number_expression {
493 translator_spec_block:
494 TRANSLATOR '{' translator_spec_body '}'
500 translator_spec_body:
501 TRANSLATOR_IDENTIFIER {
502 $$ = unsmob_translator_def ($1)->clone_scm ();
503 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
506 $$ = Translator_def::make_scm ();
507 Translator_def*td = unsmob_translator_def ($$);
508 td->translator_group_type_ = $2;
509 td->set_spot (THIS->here_input ());
511 | translator_spec_body STRING '=' embedded_scm {
512 unsmob_translator_def ($$)->add_property_assign ($2, $4);
514 | translator_spec_body STRING OVERRIDE embedded_scm '=' embedded_scm {
515 unsmob_translator_def ($$)
516 ->add_push_property (scm_string_to_symbol ($2), $4, $6);
518 | translator_spec_body STRING REVERT embedded_scm {
519 unsmob_translator_def ($$)->add_pop_property (
520 scm_string_to_symbol ($2), $4);
522 | translator_spec_body NAME STRING {
523 unsmob_translator_def ($$)->type_name_ = $3;
525 | translator_spec_body CONSISTS STRING {
526 unsmob_translator_def ($$)->add_element ($3);
528 | translator_spec_body ALIAS STRING {
529 Translator_def*td = unsmob_translator_def ($$);
530 td->type_aliases_ = gh_cons ($3, td->type_aliases_);
532 | translator_spec_body GROBDESCRIPTIONS embedded_scm {
533 Translator_def*td = unsmob_translator_def($$);
534 // td->add_property_assign (ly_symbol2scm ("allGrobDescriptions"), $3);
535 for (SCM p = $3; gh_pair_p (p); p = ly_cdr (p))
536 td->add_property_assign (scm_symbol_to_string (ly_caar (p)), ly_cdar (p));
538 | translator_spec_body CONSISTSEND STRING {
539 unsmob_translator_def ($$)->add_last_element ( $3);
541 | translator_spec_body ACCEPTS STRING {
542 unsmob_translator_def ($$)->set_acceptor ($3,true);
544 | translator_spec_body DENIES STRING {
545 unsmob_translator_def ($$)->set_acceptor ($3,false);
547 | translator_spec_body REMOVE STRING {
548 unsmob_translator_def ($$)->remove_element ($3);
559 /*cont*/ '{' score_body '}' {
562 if (!$$->def_p_arr_.size ())
564 Music_output_def *id =
565 unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
566 $$->add_output (id ? id->clone () : new Paper_def );
575 $$->set_spot (THIS->here_input ());
576 SCM m = $1->self_scm ();
577 scm_gc_unprotect_object (m);
581 $$ = new Score (*unsmob_score ($1));
582 $$->set_spot (THIS->here_input ());
584 | score_body lilypond_header {
585 scm_gc_unprotect_object ($2->self_scm ());
588 | score_body output_def {
601 music_output_def_body '}' {
603 THIS-> lexer_p_-> scope_l_arr_.pop ();
607 music_output_def_body:
609 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
614 p = dynamic_cast<Midi_def*> (id->clone ());
619 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
622 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
625 p = dynamic_cast<Paper_def*> (id->clone ());
628 THIS-> lexer_p_-> scope_l_arr_.push (p->scope_p_);
631 | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
632 Music_output_def *p = unsmob_music_output_def ($3);
634 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
637 | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
638 Music_output_def *p = unsmob_music_output_def ($3);
641 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
644 | music_output_def_body assignment {
647 | music_output_def_body translator_spec_block {
648 $$->assign_translator ($2);
650 | music_output_def_body STYLESHEET embedded_scm {
651 dynamic_cast<Paper_def*> ($$)-> style_sheet_ = $3;
653 | music_output_def_body tempo_request {
655 junk this ? there already is tempo stuff in
658 int m = gh_scm2int ( $2->get_mus_property ("metronome-count"));
659 Duration *d = unsmob_duration ($2->get_mus_property ("duration"));
660 dynamic_cast<Midi_def*> ($$)->set_tempo (d->length_mom (), m);
662 | music_output_def_body error {
668 TEMPO steno_duration '=' bare_unsigned {
670 $$->set_mus_property ("duration", $2);
671 $$->set_mus_property ("metronome-count", gh_int2scm ( $4));
676 The representation of a list is the
680 to have efficient append.
682 Music_list: /* empty */ {
683 $$ = gh_cons (SCM_EOL, SCM_EOL);
687 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
688 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
689 if (gh_pair_p (ly_cdr (s)))
690 gh_set_cdr_x (ly_cdr (s), c); /* append */
692 gh_set_car_x (s, c); /* set first cons */
693 gh_set_cdr_x (s, c) ; /* remember last cell */
709 | ALTERNATIVE '{' Music_list '}' {
715 REPEAT string bare_unsigned Music Alternative_music
719 SCM alts = gh_pair_p ($5) ? gh_car ($5) : SCM_EOL;
720 if (times < scm_ilength (alts)) {
721 unsmob_music (gh_car (alts))
722 ->origin ()->warning (
723 _("More alternatives than repeats. Junking excess alternatives."));
724 alts = ly_truncate_list (times, alts);
727 Repeated_music * r = new Repeated_music (SCM_EOL);
730 r-> set_mus_property ("element", beg->self_scm ());
731 scm_gc_unprotect_object (beg->self_scm ());
733 r->set_mus_property ("repeat-count", gh_int2scm (times >? 1));
735 r-> set_mus_property ("elements",alts);
736 SCM func = scm_primitive_eval (ly_symbol2scm ("repeat-name-to-ctor"));
737 SCM result = gh_call1 (func, $2);
739 set_music_properties (r, result);
741 r->set_spot (*$4->origin ());
747 SEQUENTIAL '{' Music_list '}' {
748 $$ = new Sequential_music (SCM_EOL);
749 $$->set_mus_property ("elements", ly_car ($3));
751 | '{' Music_list '}' {
752 $$ = new Sequential_music (SCM_EOL);
753 $$->set_mus_property ("elements", ly_car ($2));
758 SIMULTANEOUS '{' Music_list '}'{
759 $$ = new Simultaneous_music (SCM_EOL);
760 $$->set_mus_property ("elements", ly_car ($3));
763 | '<' Music_list '>' {
764 $$ = new Simultaneous_music (SCM_EOL);
765 $$->set_mus_property ("elements", ly_car ($2));
770 request_chord { $$ = $1; }
771 | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm {
773 if (!gh_symbol_p ($3))
775 THIS->parser_error (_ ("Second argument must be a symbol"));
777 /*hould check # args */
778 if (!gh_procedure_p (pred))
780 THIS->parser_error (_ ("First argument must be a procedure taking 1 argument"));
783 Music *m = new Music (SCM_EOL);
784 m->set_mus_property ("predicate", pred);
785 m->set_mus_property ("grob-property", $3);
786 m->set_mus_property ("grob-value", $5);
787 m->set_mus_property ("iterator-ctor",
788 Output_property_music_iterator::constructor_cxx_function);
793 $$ = unsmob_music ($1)->clone ();
801 CONTEXT STRING Music {
802 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
803 csm->set_mus_property ("element", $3->self_scm ());
804 scm_gc_unprotect_object ($3->self_scm ());
806 csm->set_mus_property ("context-type",$2);
807 csm->set_mus_property ("context-id", ly_str02scm (""));
811 | AUTOCHANGE STRING Music {
812 Music * chm = new Music_wrapper (SCM_EOL);
813 chm->set_mus_property ("element", $3->self_scm ());
814 chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_cxx_function);
816 scm_gc_unprotect_object ($3->self_scm ());
817 chm->set_mus_property ("what", $2);
820 chm->set_spot (*$3->origin ());
825 The other version is for easier debugging of
826 Sequential_music_iterator in combination with grace notes.
829 SCM start = THIS->lexer_p_->lookup_identifier ("startGraceMusic");
830 SCM stop = THIS->lexer_p_->lookup_identifier ("stopGraceMusic");
831 Music *startm = unsmob_music (start);
832 Music *stopm = unsmob_music (stop);
836 stopm = stopm->clone ();
837 ms = gh_cons (stopm->self_scm (), ms);
838 scm_gc_unprotect_object (stopm->self_scm ());
840 ms = gh_cons ($2->self_scm (), ms);
841 scm_gc_unprotect_object ($2->self_scm());
843 startm = startm->clone ();
844 ms = gh_cons (startm->self_scm () , ms);
845 scm_gc_unprotect_object (startm->self_scm ());
848 Music* seq = new Sequential_music (SCM_EOL);
849 seq->set_mus_property ("elements", ms);
851 $$ = new Grace_music (SCM_EOL);
852 $$->set_mus_property ("element", seq->self_scm ());
853 scm_gc_unprotect_object (seq->self_scm ());
855 $$ = new Grace_music (SCM_EOL);
856 $$->set_mus_property ("element", $2->self_scm ());
857 scm_gc_unprotect_object ($2->self_scm ());
860 | CONTEXT string '=' string Music {
861 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
862 csm->set_mus_property ("element", $5->self_scm ());
863 scm_gc_unprotect_object ($5->self_scm ());
865 csm->set_mus_property ("context-type", $2);
866 csm->set_mus_property ("context-id", $4);
877 int n = gh_scm2int (ly_car ($3)); int d = gh_scm2int (ly_cdr ($3));
879 $$ = new Time_scaled_music (SCM_EOL);
880 $$->set_spot (THIS->pop_spot ());
883 $$->set_mus_property ("element", mp->self_scm ());
884 scm_gc_unprotect_object (mp->self_scm ());
885 $$->set_mus_property ("numerator", gh_int2scm (n));
886 $$->set_mus_property ("denominator", gh_int2scm (d));
887 $$->compress (Moment (Rational (n,d)));
890 | Repeated_music { $$ = $1; }
891 | Simultaneous_music { $$ = $1; }
892 | Sequential_music { $$ = $1; }
893 | TRANSPOSE pitch Music {
894 $$ = new Transposed_music (SCM_EOL);
896 Pitch pit = *unsmob_pitch ($2);
899 $$->set_mus_property ("element", p->self_scm ());
900 scm_gc_unprotect_object (p->self_scm ());
902 | TRANSPOSE steno_tonic_pitch Music {
903 $$ = new Transposed_music (SCM_EOL);
905 Pitch pit = *unsmob_pitch ($2);
908 $$->set_mus_property ("element", p->self_scm ());
909 scm_gc_unprotect_object (p->self_scm ());
912 | APPLY embedded_scm Music {
913 SCM ret = gh_call1 ($2, $3->self_scm ());
914 Music *m = unsmob_music (ret);
916 THIS->parser_error ("\\apply must return a Music");
917 m = new Music (SCM_EOL);
922 { THIS->lexer_p_->push_note_state (); }
925 THIS->lexer_p_->pop_state ();
928 { THIS->lexer_p_->push_figuredbass_state (); }
931 Music * chm = new Untransposable_music () ;
932 chm->set_mus_property ("element", $3->self_scm ());
935 THIS->lexer_p_->pop_state ();
938 { THIS->lexer_p_->push_chord_state (); }
941 Music * chm = new Un_relativable_music ;
942 chm->set_mus_property ("element", $3->self_scm ());
945 THIS->lexer_p_->pop_state ();
948 { THIS->lexer_p_->push_lyric_state (); }
952 THIS->lexer_p_->pop_state ();
954 | relative_music { $$ = $1; }
955 | re_rhythmed_music { $$ = $1; }
956 | part_combined_music { $$ = $1; }
960 RELATIVE absolute_pitch Music {
962 Pitch pit = *unsmob_pitch ($2);
963 $$ = new Relative_octave_music (SCM_EOL);
965 $$->set_mus_property ("element", p->self_scm ());
966 scm_gc_unprotect_object (p->self_scm ());
968 $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ());
974 ADDLYRICS Music Music {
975 Lyric_combine_music * l = new Lyric_combine_music (SCM_EOL);
976 l->set_mus_property ("elements", gh_list ($2->self_scm (), $3->self_scm (), SCM_UNDEFINED));
977 scm_gc_unprotect_object ($3->self_scm ());
978 scm_gc_unprotect_object ($2->self_scm ());
984 PARTCOMBINE STRING Music Music {
985 Part_combine_music * p = new Part_combine_music (SCM_EOL);
987 p->set_mus_property ("what", $2);
988 p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED));
990 scm_gc_unprotect_object ($3->self_scm ());
991 scm_gc_unprotect_object ($4->self_scm ());
998 TRANSLATOR STRING '=' STRING {
999 Music * t = new Music (SCM_EOL);
1000 t->set_mus_property ("iterator-ctor",
1001 Change_iterator::constructor_cxx_function);
1002 t-> set_mus_property ("change-to-type", $2);
1003 t-> set_mus_property ("change-to-id", $4);
1006 $$->set_spot (THIS->here_input ());
1011 PROPERTY STRING '.' STRING '=' scalar {
1013 Music *t = set_property_music (scm_string_to_symbol ($4), $6);
1014 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1016 csm->set_mus_property ("element", t->self_scm ());
1017 scm_gc_unprotect_object (t->self_scm ());
1020 $$->set_spot (THIS->here_input ());
1022 csm-> set_mus_property ("context-type", $2);
1024 | PROPERTY STRING '.' STRING UNSET {
1025 Music *t = new Music (SCM_EOL);
1027 t->set_mus_property ("iterator-ctor",
1028 Property_unset_iterator::constructor_cxx_function);
1029 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1031 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1032 csm->set_mus_property ("element", t->self_scm ());
1033 scm_gc_unprotect_object (t->self_scm ());
1036 $$->set_spot (THIS->here_input ());
1038 csm-> set_mus_property ("context-type", $2);
1040 | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm {
1041 Music *t = new Music (SCM_EOL);
1042 t->set_mus_property ("iterator-ctor",
1043 Push_property_iterator::constructor_cxx_function);
1044 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1045 t->set_mus_property ("pop-first", SCM_BOOL_T);
1046 t->set_mus_property ("grob-property", $6);
1047 t->set_mus_property ("grob-value", $8);
1048 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1049 csm->set_mus_property ("element", t->self_scm ());
1050 scm_gc_unprotect_object (t->self_scm ());
1052 $$->set_spot (THIS->here_input ());
1054 csm-> set_mus_property ("context-type", $2);
1056 | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
1057 Music *t = new Music (SCM_EOL);
1058 t->set_mus_property ("iterator-ctor",
1059 Push_property_iterator::constructor_cxx_function);
1060 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1061 t->set_mus_property ("grob-property", $6);
1062 t->set_mus_property ("grob-value", $8);
1063 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1064 csm->set_mus_property ("element", t->self_scm ());
1065 scm_gc_unprotect_object (t->self_scm ());
1068 $$->set_spot (THIS->here_input ());
1070 csm-> set_mus_property ("context-type", $2);
1072 | PROPERTY STRING '.' STRING REVERT embedded_scm {
1073 Music *t = new Music (SCM_EOL);
1074 t->set_mus_property ("iterator-ctor",
1075 Pop_property_iterator::constructor_cxx_function);
1076 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1077 t->set_mus_property ("grob-property", $6);
1079 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1080 csm->set_mus_property ("element", t->self_scm ());
1081 scm_gc_unprotect_object (t->self_scm ());
1084 $$->set_spot (THIS->here_input ());
1086 csm-> set_mus_property ("context-type", $2);
1092 | bare_int { $$ = gh_int2scm ($1); }
1093 | embedded_scm { $$ = $1; }
1100 } /*cont */ simple_element post_requests {
1101 Music_sequence *l = dynamic_cast<Music_sequence*> ($3);
1104 for (int i=0; i < $1->size (); i++) {
1105 Music * m = $1->elem (i);
1106 l->append_music (m);
1118 $$ = new Request_chord (SCM_EOL);
1119 $$->set_mus_property ("elements", gh_cons ($1->self_scm (), SCM_EOL));
1120 $$-> set_spot (THIS->here_input ());
1121 $1-> set_spot (THIS->here_input ());
1124 $$ = new Music (gh_list (gh_cons (ly_symbol2scm ("name"), ly_symbol2scm ("separator")), SCM_UNDEFINED));
1125 $$->set_spot (THIS->here_input ());
1129 extern Music * get_barcheck();
1130 $$ = get_barcheck ();
1131 $$->set_spot (THIS->here_input ());
1134 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1136 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1137 csm->set_mus_property ("element", t->self_scm ());
1138 scm_gc_unprotect_object (t->self_scm ());
1141 $$->set_spot (THIS->here_input ());
1143 csm->set_mus_property ("context-type", ly_str02scm ("Score"));
1145 | PARTIAL duration_length {
1146 Moment m = - unsmob_duration ($2)->length_mom ();
1147 Music * p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1149 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1150 sp->set_mus_property ("element", p->self_scm ());
1151 scm_gc_unprotect_object (p->self_scm ());
1154 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1157 SCM func = scm_primitive_eval (ly_symbol2scm ("clef-name-to-properties"));
1158 SCM result = gh_call1 (func, $2);
1161 for (SCM s = result ; gh_pair_p (s); s = ly_cdr (s)) {
1162 Music * p = new Music (SCM_EOL);
1163 set_music_properties (p, ly_car (s));
1164 l = gh_cons (p->self_scm (), l);
1165 scm_gc_unprotect_object (p->self_scm ());
1167 Sequential_music * seq = new Sequential_music (SCM_EOL);
1168 seq->set_mus_property ("elements", l);
1170 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1171 sp->set_mus_property ("element", seq->self_scm ());
1172 scm_gc_unprotect_object (seq->self_scm ());
1175 sp-> set_mus_property ("context-type", ly_str02scm ("Staff"));
1178 Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2);
1180 int l = gh_scm2int (ly_car ($2));
1181 int o = gh_scm2int (ly_cdr ($2));
1183 Moment one_beat = Moment (1)/Moment (o);
1184 Moment len = Moment (l) * one_beat;
1187 Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ());
1188 Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ());
1190 SCM list = scm_list_n (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED);
1191 Sequential_music *seq = new Sequential_music (SCM_EOL);
1192 seq->set_mus_property ("elements", list);
1195 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1196 sp->set_mus_property ("element", seq->self_scm ());
1200 scm_gc_unprotect_object (p3->self_scm ());
1201 scm_gc_unprotect_object (p2->self_scm ());
1202 scm_gc_unprotect_object (p1->self_scm ());
1203 scm_gc_unprotect_object (seq->self_scm ());
1208 TODO: should make alias TimingContext for Score
1211 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1216 shorthand_command_req { $$ = $1; }
1217 | verbose_command_req { $$ = $1; }
1220 shorthand_command_req:
1231 Span_req*b= new Span_req;
1232 b->set_span_dir (START);
1233 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1237 THIS->last_beam_start_ = b->self_scm ();
1240 Span_req*b= new Span_req;
1241 b->set_span_dir ( STOP);
1242 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1246 $$ = new Breathing_sign_req;
1249 $$ = new Porrectus_req;
1253 verbose_command_req:
1254 COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1255 Span_req * sp_p = new Span_req;
1256 sp_p-> set_span_dir ( Direction ($2));
1257 sp_p->set_mus_property ("span-type",$3);
1258 sp_p->set_spot (THIS->here_input ());
1262 Mark_req * m = new Mark_req;
1266 Mark_req *m = new Mark_req;
1267 m->set_mus_property ("label", $2);
1272 Break_req * b = new Break_req;
1274 if (!gh_number_p (s))
1277 b->set_mus_property ("penalty", s);
1278 b->set_spot (THIS->here_input ());
1281 | SKIP duration_length {
1282 Skip_req * skip_p = new Skip_req;
1283 skip_p->set_mus_property ("duration", $2);
1291 Key_change_req *key_p= new Key_change_req;
1294 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1295 Key_change_req *key_p= new Key_change_req;
1297 key_p->set_mus_property ("pitch-alist", $3);
1298 ((Music*)key_p)->transpose (* unsmob_pitch ($2));
1305 $$ = new Link_array<Request>;
1307 | post_requests post_request {
1308 $2->set_spot (THIS->here_input ());
1320 request_that_take_dir:
1323 | script_abbreviation {
1324 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1325 Articulation_req *a = new Articulation_req;
1326 if (gh_string_p (s))
1327 a->set_mus_property ("articulation-type", s);
1328 else THIS->parser_error (_ ("Expecting string as script definition"));
1334 script_dir request_that_take_dir {
1335 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1336 gs->set_direction (Direction ($1));
1338 $2->origin ()->warning (_ ("Can't specify direction for this request"));
1344 REQUEST_IDENTIFIER {
1345 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1346 $$->set_spot (THIS->here_input ());
1348 | DYNAMICSCRIPT embedded_scm {
1350 TODO: junkme, use text-type == dynamic
1352 Text_script_req *d = new Text_script_req;
1353 SCM dyn = ly_symbol2scm ("dynamic");
1354 d->set_mus_property ("text-type" , dyn);
1355 d->set_mus_property ("text", $2);
1356 d->set_spot (THIS->here_input ());
1359 | SPANREQUEST bare_int STRING {
1360 Span_req * sp_p = new Span_req;
1361 sp_p->set_span_dir ( Direction ($2));
1362 sp_p->set_mus_property ("span-type", $3);
1363 sp_p->set_spot (THIS->here_input ());
1367 Tremolo_req* a = new Tremolo_req;
1368 a->set_spot (THIS->here_input ());
1369 a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1373 Articulation_req * a = new Articulation_req;
1374 a->set_mus_property ("articulation-type", $2);
1375 a->set_spot (THIS->here_input ());
1379 duh, junk this syntax from the parser, if possible.
1382 Arpeggio_req *a = new Arpeggio_req;
1383 a->set_spot (THIS->here_input ());
1387 Glissando_req *g = new Glissando_req;
1388 g->set_spot /* No pun intended */ (THIS->here_input ());
1415 | NOTENAME_PITCH sup_quotes {
1416 Pitch p = *unsmob_pitch ($1);
1418 $$ = p.smobbed_copy ();
1420 | NOTENAME_PITCH sub_quotes {
1421 Pitch p =* unsmob_pitch ($1);
1424 $$ = p.smobbed_copy ();
1437 | TONICNAME_PITCH sup_quotes {
1438 Pitch p = *unsmob_pitch ($1);
1440 $$ = p.smobbed_copy ();
1442 | TONICNAME_PITCH sub_quotes {
1443 Pitch p =* unsmob_pitch ($1);
1446 $$ = p.smobbed_copy ();
1461 PITCH embedded_scm {
1463 if (!unsmob_pitch ($2)) {
1464 THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1465 $$ = Pitch ().smobbed_copy ();
1471 DURATION embedded_scm {
1473 if (!unsmob_duration ($2))
1475 THIS->parser_error (_ ("Must have duration object"));
1476 $$ = Duration ().smobbed_copy ();
1483 if (!THIS->lexer_p_->lyric_state_b ())
1484 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1485 $$ = new Extender_req;
1491 if (!THIS->lexer_p_->lyric_state_b ())
1492 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1493 $$ = new Hyphen_req;
1498 close_request_parens {
1500 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1503 close_request_parens:
1505 Span_req* s= new Span_req;
1507 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1510 Span_req* s= new Span_req;
1512 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1515 Span_req*s =new Span_req;
1517 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1520 Span_req*s =new Span_req;
1522 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1528 open_request_parens {
1530 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1534 open_request_parens:
1536 Span_req *s = new Span_req;
1537 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1542 Span_req* s= new Span_req;
1544 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1547 Span_req* s= new Span_req;
1549 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1555 Text_script_req *t = new Text_script_req;
1556 t->set_mus_property ("text", $1);
1557 t->set_spot (THIS->here_input ());
1561 Text_script_req *t = new Text_script_req;
1562 t->set_mus_property ("text", $1);
1563 t->set_spot (THIS->here_input ());
1567 String ds = to_str ($1);
1568 Text_script_req* t = new Text_script_req;
1569 SCM finger = ly_symbol2scm ("finger");
1570 t->set_mus_property ("text", ly_str02scm (ds.ch_C ()));
1571 t->set_mus_property ("text-type" , finger);
1572 t->set_spot (THIS->here_input ());
1577 script_abbreviation:
1579 $$ = gh_str02scm ("Hat");
1582 $$ = gh_str02scm ("Plus");
1585 $$ = gh_str02scm ("Dash");
1588 $$ = gh_str02scm ("Bar");
1591 $$ = gh_str02scm ("Larger");
1594 $$ = gh_str02scm ("Dot");
1601 | '-' { $$ = CENTER; }
1606 $$ = new Link_array<Request>;
1608 | pre_requests open_request {
1620 multiplied_duration {
1623 | verbose_duration {
1628 optional_notemode_duration:
1630 Duration dd = THIS->default_duration_;
1631 $$ = dd.smobbed_copy ();
1633 THIS->beam_check ($$);
1635 | multiplied_duration {
1637 THIS->default_duration_ = *unsmob_duration ($$);
1639 THIS->beam_check ($$);
1641 | verbose_duration {
1643 THIS->default_duration_ = *unsmob_duration ($$);
1648 bare_unsigned dots {
1650 if (!is_duration_b ($1))
1651 THIS->parser_error (_f ("not a duration: %d", $1));
1655 $$ = Duration (l, $2).smobbed_copy ();
1657 | DURATION_IDENTIFIER dots {
1658 Duration *d =unsmob_duration ($1);
1659 Duration k (d->duration_log (),d->dot_count () + $2);
1660 $$ = k.smobbed_copy ();
1667 multiplied_duration:
1671 | multiplied_duration '*' bare_unsigned {
1672 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1674 | multiplied_duration '*' FRACTION {
1675 Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr ($3)));
1677 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1682 FRACTION { $$ = $1; }
1683 | UNSIGNED '/' UNSIGNED {
1684 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1702 | ':' bare_unsigned {
1703 if (!is_duration_b ($2))
1704 THIS->parser_error (_f ("not a duration: %d", $2));
1723 Bass_figure_req *bfr = new Bass_figure_req;
1724 $$ = bfr->self_scm();
1725 scm_gc_unprotect_object ($$);
1728 Bass_figure_req *bfr = new Bass_figure_req;
1729 $$ = bfr->self_scm();
1731 bfr->set_mus_property ("figure", gh_int2scm ($1));
1733 scm_gc_unprotect_object ($$);
1735 | bass_figure bass_mod {
1736 Music *m = unsmob_music ($1);
1738 SCM salter =m->get_mus_property ("alteration");
1739 int alter = gh_number_p( salter) ? gh_scm2int (salter) : 0;
1740 m->set_mus_property ("alteration",
1741 gh_int2scm (alter + $2));
1743 m->set_mus_property ("alteration", gh_int2scm (0));
1751 unsmob_music ($$)->set_mus_property ("bracket-start", SCM_BOOL_T);
1756 | br_bass_figure ']' {
1758 unsmob_music ($1)->set_mus_property ("bracket-stop", SCM_BOOL_T);
1766 | figure_list br_bass_figure {
1767 $$ = gh_cons ($2, $1);
1772 FIGURE_OPEN figure_list FIGURE_CLOSE {
1773 Music * m = new Request_chord (SCM_EOL);
1774 $2 = scm_reverse_x ($2, SCM_EOL);
1775 m->set_mus_property ("elements", $2);
1776 $$ = m->self_scm ();
1787 pitch exclamations questions optional_notemode_duration optional_rest {
1789 Input i = THIS->pop_spot ();
1790 if (!THIS->lexer_p_->note_state_b ())
1791 THIS->parser_error (_ ("Have to be in Note mode for notes"));
1799 n->set_mus_property ("pitch", $1);
1800 n->set_mus_property ("duration", $4);
1804 n->set_mus_property ("cautionary", SCM_BOOL_T);
1805 if ($2 % 2 || $3 % 2)
1806 n->set_mus_property ("force-accidental", SCM_BOOL_T);
1808 Simultaneous_music*v = new Request_chord (SCM_EOL);
1809 v->set_mus_property ("elements", scm_list_n (n->self_scm (), SCM_UNDEFINED));
1815 | figure_spec optional_notemode_duration {
1816 Music * m = unsmob_music ($1);
1817 Input i = THIS->pop_spot ();
1819 for (SCM s = m->get_mus_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
1821 unsmob_music (ly_car (s))->set_mus_property ("duration", $2);
1825 | RESTNAME optional_notemode_duration {
1827 Input i = THIS->pop_spot ();
1828 SCM e = SCM_UNDEFINED;
1829 if (ly_scm2string ($1) =="s") {
1831 Skip_req * skip_p = new Skip_req;
1832 skip_p->set_mus_property ("duration" ,$2);
1833 skip_p->set_spot (i);
1834 e = skip_p->self_scm ();
1837 Rest_req * rest_req_p = new Rest_req;
1838 rest_req_p->set_mus_property ("duration", $2);
1839 rest_req_p->set_spot (i);
1840 e = rest_req_p->self_scm ();
1842 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1843 velt_p-> set_mus_property ("elements", scm_list_n (e,SCM_UNDEFINED));
1844 velt_p->set_spot (i);
1848 | MULTI_MEASURE_REST optional_notemode_duration {
1849 Input i = THIS->pop_spot ();
1851 Skip_req * sk = new Skip_req;
1852 sk->set_mus_property ("duration", $2);
1853 Span_req *sp1 = new Span_req;
1854 Span_req *sp2 = new Span_req;
1855 sp1-> set_span_dir ( START);
1856 sp2-> set_span_dir ( STOP);
1857 SCM r = ly_str02scm ("rest");
1858 sp1->set_mus_property ("span-type", r);
1859 sp2->set_mus_property ("span-type", r);
1861 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1862 rqc1->set_mus_property ("elements", scm_list_n (sp1->self_scm (), SCM_UNDEFINED));
1863 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1864 rqc2->set_mus_property ("elements", scm_list_n (sk->self_scm (), SCM_UNDEFINED));;
1865 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1866 rqc3->set_mus_property ("elements", scm_list_n (sp2->self_scm (), SCM_UNDEFINED));;
1868 SCM ms = scm_list_n (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1870 $$ = new Sequential_music (SCM_EOL);
1871 $$->set_mus_property ("elements", ms);
1873 | STRING optional_notemode_duration {
1874 Input i = THIS->pop_spot ();
1876 Lyric_req* lreq_p = new Lyric_req;
1877 lreq_p->set_mus_property ("text", $1);
1878 lreq_p->set_mus_property ("duration",$2);
1879 lreq_p->set_spot (i);
1880 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1881 velt_p->set_mus_property ("elements", scm_list_n (lreq_p->self_scm (), SCM_UNDEFINED));
1886 Input i = THIS->pop_spot ();
1888 if (!THIS->lexer_p_->chord_state_b ())
1889 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1896 steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1897 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1898 $$->set_spot (THIS->here_input ());
1905 | CHORD_COLON chord_notes {
1914 | chord_notes '.' chord_step {
1915 $$ = gh_append2 ($$, $3);
1923 | CHORD_CARET chord_notes {
1933 | '/' steno_tonic_pitch {
1942 | CHORD_BASS steno_tonic_pitch {
1949 $$ = gh_cons ($1, SCM_EOL);
1951 | CHORDMODIFIER_PITCH {
1952 $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
1954 | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1955 $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
1963 m.notename_i_ = ($1 - 1) % 7;
1964 m.octave_i_ = $1 > 7 ? 1 : 0;
1965 m.alteration_i_ = 0;
1967 $$ = m.smobbed_copy ();
1969 | bare_unsigned '+' {
1971 m.notename_i_ = ($1 - 1) % 7;
1972 m.octave_i_ = $1 > 7 ? 1 : 0;
1973 m.alteration_i_ = 1;
1976 $$ = m.smobbed_copy ();
1978 | bare_unsigned CHORD_MINUS {
1980 m.notename_i_ = ($1 - 1) % 7;
1981 m.octave_i_ = $1 > 7 ? 1 : 0;
1982 m.alteration_i_ = -1;
1984 $$ = m.smobbed_copy ();
1992 number_expression '+' number_term {
1993 $$ = scm_sum ($1, $3);
1995 | number_expression '-' number_term {
1996 $$ = scm_difference ($1, $3);
2005 | number_factor '*' number_factor {
2006 $$ = scm_product ($1, $3);
2008 | number_factor '/' number_factor {
2009 $$ = scm_divide ($1, $3);
2014 '(' number_expression ')' {
2017 | '-' number_factor { /* %prec UNARY_MINUS */
2018 $$ = scm_difference ($2, SCM_UNDEFINED);
2026 $$ = gh_int2scm ($1);
2031 | NUMBER_IDENTIFIER {
2035 $$ = gh_double2scm (gh_scm2double ($1) CM );
2038 $$ = gh_double2scm (gh_scm2double ($1) PT);
2041 $$ = gh_double2scm (gh_scm2double ($1) INCH);
2044 $$ = gh_double2scm (gh_scm2double ($1) MM);
2047 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
2063 if (scm_integer_p ($1) == SCM_BOOL_T)
2065 int k = gh_scm2int ($1);
2069 THIS->parser_error (_ ("need integer number arg"));
2083 | STRING_IDENTIFIER {
2086 | string '+' string {
2087 $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
2094 | exclamations '!' { $$ ++; }
2099 | questions '?' { $$ ++; }
2106 My_lily_parser::set_yydebug (bool b)
2113 extern My_lily_parser * current_parser;
2116 My_lily_parser::do_yyparse ()
2119 current_parser = this;;
2120 yyparse ((void*)this);
2125 Should make this optional? It will also complain when you do
2129 which is entirely legitimate.
2131 Or we can scrap it. Barchecks should detect wrong durations, and
2132 skipTypesetting speeds it up a lot.
2135 My_lily_parser::beam_check (SCM dur)
2137 Duration *d = unsmob_duration (dur);
2138 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2140 Music * m = unsmob_music (last_beam_start_);
2141 m->origin ()->warning (_("Suspect duration found following this beam"));
2143 last_beam_start_ = SCM_EOL;