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
198 %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
208 %token MULTI_MEASURE_REST
220 %token OVERRIDE SET REVERT
233 %token COMMANDSPANREQUEST
235 %token OUTPUTPROPERTY
246 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE E_TILDE
248 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
252 %type <i> exclamations questions dots optional_rest
253 %type <i> bass_number bass_mod
254 %type <scm> br_bass_figure bass_figure figure_list figure_spec
256 %token <scm> NOTENAME_PITCH
257 %token <scm> TONICNAME_PITCH
258 %token <scm> CHORDMODIFIER_PITCH
259 %token <scm> DURATION_IDENTIFIER
260 %token <scm> FRACTION
261 %token <id> IDENTIFIER
264 %token <scm> SCORE_IDENTIFIER
265 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
267 %token <scm> NUMBER_IDENTIFIER
268 %token <scm> REQUEST_IDENTIFIER
269 %token <scm> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
270 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
271 %token <scm> RESTNAME
277 %type <outputdef> output_def
278 %type <scmhash> lilypond_header lilypond_header_body
279 %type <request> open_request_parens close_request_parens open_request close_request
280 %type <request> request_with_dir request_that_take_dir verbose_request
281 %type <i> sub_quotes sup_quotes
282 %type <music> simple_element request_chord command_element Simple_music Composite_music
283 %type <music> Repeated_music
284 %type <scm> Alternative_music
285 %type <i> tremolo_type
286 %type <i> bare_int bare_unsigned
289 %type <scm> identifier_init
291 %type <scm> steno_duration optional_notemode_duration multiplied_duration
292 %type <scm> verbose_duration
294 %type <reqvec> pre_requests post_requests
295 %type <request> gen_text_def
296 %type <scm> steno_pitch pitch absolute_pitch
297 %type <scm> explicit_pitch steno_tonic_pitch
299 %type <scm> chord_additions chord_subtractions chord_notes chord_step
301 %type <scm> chord_note chord_inversion chord_bass
302 %type <scm> duration_length fraction
304 %type <scm> embedded_scm scalar
305 %type <music> Music Sequential_music Simultaneous_music
306 %type <music> relative_music re_rhythmed_music part_combined_music
307 %type <music> property_def translator_change
308 %type <scm> Music_list
309 %type <outputdef> music_output_def_body
310 %type <request> shorthand_command_req
311 %type <request> post_request
312 %type <music> command_req verbose_command_req
313 %type <request> extender_req
314 %type <request> hyphen_req
315 %type <scm> string bare_number number_expression number_term number_factor
317 %type <score> score_block score_body
319 %type <scm> translator_spec_block translator_spec_body
320 %type <tempo> tempo_request
321 %type <scm> notenames_body notenames_block chordmodifiers_block
322 %type <scm> script_abbreviation
328 /* We don't assign precedence to / and *, because we might need varied
329 prec levels in different prods */
335 lilypond: /* empty */
336 | lilypond toplevel_expression {}
337 | lilypond assignment { }
339 THIS->error_level_i_ = 1;
342 THIS->error_level_i_ = 1;
348 THIS->lexer_p_->pitchname_tab_ = $1;
350 | chordmodifiers_block {
351 THIS->lexer_p_->chordmodifier_tab_ = $1;
355 scm_gc_unprotect_object (global_header_p->self_scm ());
356 global_header_p = $1;
359 score_global_array.push ($1);
362 if (dynamic_cast<Paper_def*> ($1))
363 THIS->lexer_p_->set_identifier ("$defaultpaper", $1->self_scm ());
364 else if (dynamic_cast<Midi_def*> ($1))
365 THIS->lexer_p_->set_identifier ("$defaultmidi", $1->self_scm ());
378 chordmodifiers_block:
379 CHORDMODIFIERS notenames_body { $$ = $2; }
383 PITCHNAMES notenames_body { $$ = $2; }
388 int i = scm_ilength ($1);
390 SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
391 for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) {
392 SCM pt = ly_cdar (s);
393 if (!unsmob_pitch (pt))
394 THIS->parser_error ("Need pitch object.");
396 scm_hashq_set_x (tab, ly_caar (s), pt);
403 lilypond_header_body:
405 $$ = new Scheme_hash_table;
407 Scope *sc = new Scope ($$);
408 THIS->lexer_p_-> scope_l_arr_.push (sc);
410 | lilypond_header_body assignment {
416 HEADER '{' lilypond_header_body '}' {
418 delete THIS->lexer_p_-> scope_l_arr_.pop ();
430 /* cont */ '=' identifier_init {
433 Should find generic way of associating input with objects.
435 Input ip = THIS->pop_spot ();
437 if (! regular_identifier_b ($1))
439 ip.warning (_ ("Identifier should have alphabetic characters only"));
442 THIS->lexer_p_->set_identifier (ly_scm2string ($1), $4);
445 TODO: devise standard for protection in parser.
447 The parser stack lives on the C-stack, which means that
448 all objects can be unprotected as soon as they're here.
458 $$ = $1->self_scm ();
459 scm_gc_unprotect_object ($$);
462 $$ = $1->self_scm ();
463 scm_gc_unprotect_object ($$);
465 | translator_spec_block {
469 $$ = $1->self_scm ();
470 scm_gc_unprotect_object ($$);
473 $$ = $1->self_scm ();
474 scm_gc_unprotect_object ($$);
479 | number_expression {
490 translator_spec_block:
491 TRANSLATOR '{' translator_spec_body '}'
497 translator_spec_body:
498 TRANSLATOR_IDENTIFIER {
499 $$ = unsmob_translator_def ($1)->clone_scm ();
500 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
503 $$ = Translator_def::make_scm ();
504 Translator_def*td = unsmob_translator_def ($$);
505 td->translator_group_type_ = $2;
506 td->set_spot (THIS->here_input ());
508 | translator_spec_body STRING '=' embedded_scm {
509 unsmob_translator_def ($$)->add_property_assign ($2, $4);
511 | translator_spec_body STRING OVERRIDE embedded_scm '=' embedded_scm {
512 unsmob_translator_def ($$)
513 ->add_push_property (scm_string_to_symbol ($2), $4, $6);
515 | translator_spec_body STRING REVERT embedded_scm {
516 unsmob_translator_def ($$)->add_pop_property (
517 scm_string_to_symbol ($2), $4);
519 | translator_spec_body NAME STRING {
520 unsmob_translator_def ($$)->type_name_ = $3;
522 | translator_spec_body CONSISTS STRING {
523 unsmob_translator_def ($$)->add_element ($3);
525 | translator_spec_body ALIAS STRING {
526 Translator_def*td = unsmob_translator_def ($$);
527 td->type_aliases_ = gh_cons ($3, td->type_aliases_);
529 | translator_spec_body GROBDESCRIPTIONS embedded_scm {
530 Translator_def*td = unsmob_translator_def($$);
531 // td->add_property_assign (ly_symbol2scm ("allGrobDescriptions"), $3);
532 for (SCM p = $3; gh_pair_p (p); p = ly_cdr (p))
533 td->add_property_assign (scm_symbol_to_string (ly_caar (p)), ly_cdar (p));
535 | translator_spec_body CONSISTSEND STRING {
536 unsmob_translator_def ($$)->add_last_element ( $3);
538 | translator_spec_body ACCEPTS STRING {
539 unsmob_translator_def ($$)->set_acceptor ($3,true);
541 | translator_spec_body DENIES STRING {
542 unsmob_translator_def ($$)->set_acceptor ($3,false);
544 | translator_spec_body REMOVE STRING {
545 unsmob_translator_def ($$)->remove_element ($3);
556 /*cont*/ '{' score_body '}' {
559 if (!$$->def_p_arr_.size ())
561 Music_output_def *id =
562 unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
563 $$->add_output (id ? id->clone () : new Paper_def );
572 $$->set_spot (THIS->here_input ());
573 SCM m = $1->self_scm ();
574 scm_gc_unprotect_object (m);
578 $$ = new Score (*unsmob_score ($1));
579 $$->set_spot (THIS->here_input ());
581 | score_body lilypond_header {
582 scm_gc_unprotect_object ($2->self_scm ());
585 | score_body output_def {
598 music_output_def_body '}' {
600 THIS-> lexer_p_-> scope_l_arr_.pop ();
604 music_output_def_body:
606 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
611 p = dynamic_cast<Midi_def*> (id->clone ());
616 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
619 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
622 p = dynamic_cast<Paper_def*> (id->clone ());
625 THIS-> lexer_p_-> scope_l_arr_.push (p->scope_p_);
628 | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
629 Music_output_def *p = unsmob_music_output_def ($3);
631 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
634 | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
635 Music_output_def *p = unsmob_music_output_def ($3);
638 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
641 | music_output_def_body assignment {
644 | music_output_def_body translator_spec_block {
645 $$->assign_translator ($2);
647 | music_output_def_body STYLESHEET embedded_scm {
648 dynamic_cast<Paper_def*> ($$)-> style_sheet_ = $3;
650 | music_output_def_body tempo_request {
652 junk this ? there already is tempo stuff in
655 int m = gh_scm2int ( $2->get_mus_property ("metronome-count"));
656 Duration *d = unsmob_duration ($2->get_mus_property ("duration"));
657 dynamic_cast<Midi_def*> ($$)->set_tempo (d->length_mom (), m);
659 | music_output_def_body error {
665 TEMPO steno_duration '=' bare_unsigned {
667 $$->set_mus_property ("duration", $2);
668 $$->set_mus_property ("metronome-count", gh_int2scm ( $4));
673 The representation of a list is the
677 to have efficient append.
679 Music_list: /* empty */ {
680 $$ = gh_cons (SCM_EOL, SCM_EOL);
684 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
685 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
686 if (gh_pair_p (ly_cdr (s)))
687 gh_set_cdr_x (ly_cdr (s), c); /* append */
689 gh_set_car_x (s, c); /* set first cons */
690 gh_set_cdr_x (s, c) ; /* remember last cell */
706 | ALTERNATIVE '{' Music_list '}' {
712 REPEAT string bare_unsigned Music Alternative_music
716 SCM alts = gh_pair_p ($5) ? gh_car ($5) : SCM_EOL;
717 if (times < scm_ilength (alts)) {
718 unsmob_music (gh_car (alts))
719 ->origin ()->warning (
720 _("More alternatives than repeats. Junking excess alternatives."));
721 alts = ly_truncate_list (times, alts);
724 Repeated_music * r = new Repeated_music (SCM_EOL);
727 r-> set_mus_property ("element", beg->self_scm ());
728 scm_gc_unprotect_object (beg->self_scm ());
730 r->set_mus_property ("repeat-count", gh_int2scm (times >? 1));
732 r-> set_mus_property ("elements",alts);
733 SCM func = scm_primitive_eval (ly_symbol2scm ("repeat-name-to-ctor"));
734 SCM result = gh_call1 (func, $2);
736 set_music_properties (r, result);
738 r->set_spot (*$4->origin ());
744 SEQUENTIAL '{' Music_list '}' {
745 $$ = new Sequential_music (SCM_EOL);
746 $$->set_mus_property ("elements", ly_car ($3));
748 | '{' Music_list '}' {
749 $$ = new Sequential_music (SCM_EOL);
750 $$->set_mus_property ("elements", ly_car ($2));
755 SIMULTANEOUS '{' Music_list '}'{
756 $$ = new Simultaneous_music (SCM_EOL);
757 $$->set_mus_property ("elements", ly_car ($3));
760 | '<' Music_list '>' {
761 $$ = new Simultaneous_music (SCM_EOL);
762 $$->set_mus_property ("elements", ly_car ($2));
767 request_chord { $$ = $1; }
768 | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm {
770 if (!gh_symbol_p ($3))
772 THIS->parser_error (_ ("Second argument must be a symbol"));
774 /*hould check # args */
775 if (!gh_procedure_p (pred))
777 THIS->parser_error (_ ("First argument must be a procedure taking 1 argument"));
780 Music *m = new Music (SCM_EOL);
781 m->set_mus_property ("predicate", pred);
782 m->set_mus_property ("grob-property", $3);
783 m->set_mus_property ("grob-value", $5);
784 m->set_mus_property ("iterator-ctor",
785 Output_property_music_iterator::constructor_cxx_function);
790 $$ = unsmob_music ($1)->clone ();
798 CONTEXT STRING Music {
799 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
800 csm->set_mus_property ("element", $3->self_scm ());
801 scm_gc_unprotect_object ($3->self_scm ());
803 csm->set_mus_property ("context-type",$2);
804 csm->set_mus_property ("context-id", ly_str02scm (""));
808 | AUTOCHANGE STRING Music {
809 Music * chm = new Music_wrapper (SCM_EOL);
810 chm->set_mus_property ("element", $3->self_scm ());
811 chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_cxx_function);
813 scm_gc_unprotect_object ($3->self_scm ());
814 chm->set_mus_property ("what", $2);
817 chm->set_spot (*$3->origin ());
822 The other version is for easier debugging of
823 Sequential_music_iterator in combination with grace notes.
826 SCM start = THIS->lexer_p_->lookup_identifier ("startGraceMusic");
827 SCM stop = THIS->lexer_p_->lookup_identifier ("stopGraceMusic");
828 Music *startm = unsmob_music (start);
829 Music *stopm = unsmob_music (stop);
833 stopm = stopm->clone ();
834 ms = gh_cons (stopm->self_scm (), ms);
835 scm_gc_unprotect_object (stopm->self_scm ());
837 ms = gh_cons ($2->self_scm (), ms);
838 scm_gc_unprotect_object ($2->self_scm());
840 startm = startm->clone ();
841 ms = gh_cons (startm->self_scm () , ms);
842 scm_gc_unprotect_object (startm->self_scm ());
845 Music* seq = new Sequential_music (SCM_EOL);
846 seq->set_mus_property ("elements", ms);
848 $$ = new Grace_music (SCM_EOL);
849 $$->set_mus_property ("element", seq->self_scm ());
850 scm_gc_unprotect_object (seq->self_scm ());
852 $$ = new Grace_music (SCM_EOL);
853 $$->set_mus_property ("element", $2->self_scm ());
854 scm_gc_unprotect_object ($2->self_scm ());
857 | CONTEXT string '=' string Music {
858 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
859 csm->set_mus_property ("element", $5->self_scm ());
860 scm_gc_unprotect_object ($5->self_scm ());
862 csm->set_mus_property ("context-type", $2);
863 csm->set_mus_property ("context-id", $4);
874 int n = gh_scm2int (ly_car ($3)); int d = gh_scm2int (ly_cdr ($3));
876 $$ = new Time_scaled_music (SCM_EOL);
877 $$->set_spot (THIS->pop_spot ());
880 $$->set_mus_property ("element", mp->self_scm ());
881 scm_gc_unprotect_object (mp->self_scm ());
882 $$->set_mus_property ("numerator", gh_int2scm (n));
883 $$->set_mus_property ("denominator", gh_int2scm (d));
884 $$->compress (Moment (Rational (n,d)));
887 | Repeated_music { $$ = $1; }
888 | Simultaneous_music { $$ = $1; }
889 | Sequential_music { $$ = $1; }
890 | TRANSPOSE pitch Music {
891 $$ = new Transposed_music (SCM_EOL);
893 Pitch pit = *unsmob_pitch ($2);
896 $$->set_mus_property ("element", p->self_scm ());
897 scm_gc_unprotect_object (p->self_scm ());
899 | TRANSPOSE steno_tonic_pitch Music {
900 $$ = new Transposed_music (SCM_EOL);
902 Pitch pit = *unsmob_pitch ($2);
905 $$->set_mus_property ("element", p->self_scm ());
906 scm_gc_unprotect_object (p->self_scm ());
909 | APPLY embedded_scm Music {
910 SCM ret = gh_call1 ($2, $3->self_scm ());
911 Music *m = unsmob_music (ret);
913 THIS->parser_error ("\\apply must return a Music");
914 m = new Music (SCM_EOL);
919 { THIS->lexer_p_->push_note_state (); }
922 THIS->lexer_p_->pop_state ();
925 { THIS->lexer_p_->push_figuredbass_state (); }
928 Music * chm = new Untransposable_music () ;
929 chm->set_mus_property ("element", $3->self_scm ());
932 THIS->lexer_p_->pop_state ();
935 { THIS->lexer_p_->push_chord_state (); }
938 Music * chm = new Un_relativable_music ;
939 chm->set_mus_property ("element", $3->self_scm ());
942 THIS->lexer_p_->pop_state ();
945 { THIS->lexer_p_->push_lyric_state (); }
949 THIS->lexer_p_->pop_state ();
951 | relative_music { $$ = $1; }
952 | re_rhythmed_music { $$ = $1; }
953 | part_combined_music { $$ = $1; }
957 RELATIVE absolute_pitch Music {
959 Pitch pit = *unsmob_pitch ($2);
960 $$ = new Relative_octave_music (SCM_EOL);
962 $$->set_mus_property ("element", p->self_scm ());
963 scm_gc_unprotect_object (p->self_scm ());
965 $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ());
971 ADDLYRICS Music Music {
972 Lyric_combine_music * l = new Lyric_combine_music (SCM_EOL);
973 l->set_mus_property ("elements", gh_list ($2->self_scm (), $3->self_scm (), SCM_UNDEFINED));
974 scm_gc_unprotect_object ($3->self_scm ());
975 scm_gc_unprotect_object ($2->self_scm ());
981 PARTCOMBINE STRING Music Music {
982 Part_combine_music * p = new Part_combine_music (SCM_EOL);
984 p->set_mus_property ("what", $2);
985 p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED));
987 scm_gc_unprotect_object ($3->self_scm ());
988 scm_gc_unprotect_object ($4->self_scm ());
995 TRANSLATOR STRING '=' STRING {
996 Music * t = new Music (SCM_EOL);
997 t->set_mus_property ("iterator-ctor",
998 Change_iterator::constructor_cxx_function);
999 t-> set_mus_property ("change-to-type", $2);
1000 t-> set_mus_property ("change-to-id", $4);
1003 $$->set_spot (THIS->here_input ());
1008 PROPERTY STRING '.' STRING '=' scalar {
1010 Music *t = set_property_music (scm_string_to_symbol ($4), $6);
1011 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1013 csm->set_mus_property ("element", t->self_scm ());
1014 scm_gc_unprotect_object (t->self_scm ());
1017 $$->set_spot (THIS->here_input ());
1019 csm-> set_mus_property ("context-type", $2);
1021 | PROPERTY STRING '.' STRING UNSET {
1022 Music *t = new Music (SCM_EOL);
1024 t->set_mus_property ("iterator-ctor",
1025 Property_unset_iterator::constructor_cxx_function);
1026 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1028 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1029 csm->set_mus_property ("element", t->self_scm ());
1030 scm_gc_unprotect_object (t->self_scm ());
1033 $$->set_spot (THIS->here_input ());
1035 csm-> set_mus_property ("context-type", $2);
1037 | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm {
1038 Music *t = new Music (SCM_EOL);
1039 t->set_mus_property ("iterator-ctor",
1040 Push_property_iterator::constructor_cxx_function);
1041 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1042 t->set_mus_property ("pop-first", SCM_BOOL_T);
1043 t->set_mus_property ("grob-property", $6);
1044 t->set_mus_property ("grob-value", $8);
1045 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1046 csm->set_mus_property ("element", t->self_scm ());
1047 scm_gc_unprotect_object (t->self_scm ());
1049 $$->set_spot (THIS->here_input ());
1051 csm-> set_mus_property ("context-type", $2);
1053 | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
1054 Music *t = new Music (SCM_EOL);
1055 t->set_mus_property ("iterator-ctor",
1056 Push_property_iterator::constructor_cxx_function);
1057 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1058 t->set_mus_property ("grob-property", $6);
1059 t->set_mus_property ("grob-value", $8);
1060 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1061 csm->set_mus_property ("element", t->self_scm ());
1062 scm_gc_unprotect_object (t->self_scm ());
1065 $$->set_spot (THIS->here_input ());
1067 csm-> set_mus_property ("context-type", $2);
1069 | PROPERTY STRING '.' STRING REVERT embedded_scm {
1070 Music *t = new Music (SCM_EOL);
1071 t->set_mus_property ("iterator-ctor",
1072 Pop_property_iterator::constructor_cxx_function);
1073 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1074 t->set_mus_property ("grob-property", $6);
1076 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1077 csm->set_mus_property ("element", t->self_scm ());
1078 scm_gc_unprotect_object (t->self_scm ());
1081 $$->set_spot (THIS->here_input ());
1083 csm-> set_mus_property ("context-type", $2);
1089 | bare_int { $$ = gh_int2scm ($1); }
1090 | embedded_scm { $$ = $1; }
1097 } /*cont */ simple_element post_requests {
1098 Music_sequence *l = dynamic_cast<Music_sequence*> ($3);
1101 for (int i=0; i < $1->size (); i++) {
1102 Music * m = $1->elem (i);
1103 l->append_music (m);
1115 $$ = new Request_chord (SCM_EOL);
1116 $$->set_mus_property ("elements", gh_cons ($1->self_scm (), SCM_EOL));
1117 $$-> set_spot (THIS->here_input ());
1118 $1-> set_spot (THIS->here_input ());
1121 $$ = new Music (gh_list (gh_cons (ly_symbol2scm ("name"), ly_symbol2scm ("separator")), SCM_UNDEFINED));
1122 $$->set_spot (THIS->here_input ());
1126 extern Music * get_barcheck();
1127 $$ = get_barcheck ();
1128 $$->set_spot (THIS->here_input ());
1131 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1133 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1134 csm->set_mus_property ("element", t->self_scm ());
1135 scm_gc_unprotect_object (t->self_scm ());
1138 $$->set_spot (THIS->here_input ());
1140 csm->set_mus_property ("context-type", ly_str02scm ("Score"));
1142 | PARTIAL duration_length {
1143 Moment m = - unsmob_duration ($2)->length_mom ();
1144 Music * p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1146 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1147 sp->set_mus_property ("element", p->self_scm ());
1148 scm_gc_unprotect_object (p->self_scm ());
1151 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1154 SCM func = scm_primitive_eval (ly_symbol2scm ("clef-name-to-properties"));
1155 SCM result = gh_call1 (func, $2);
1158 for (SCM s = result ; gh_pair_p (s); s = ly_cdr (s)) {
1159 Music * p = new Music (SCM_EOL);
1160 set_music_properties (p, ly_car (s));
1161 l = gh_cons (p->self_scm (), l);
1162 scm_gc_unprotect_object (p->self_scm ());
1164 Sequential_music * seq = new Sequential_music (SCM_EOL);
1165 seq->set_mus_property ("elements", l);
1167 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1168 sp->set_mus_property ("element", seq->self_scm ());
1169 scm_gc_unprotect_object (seq->self_scm ());
1172 sp-> set_mus_property ("context-type", ly_str02scm ("Staff"));
1175 Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2);
1177 int l = gh_scm2int (ly_car ($2));
1178 int o = gh_scm2int (ly_cdr ($2));
1180 Moment one_beat = Moment (1)/Moment (o);
1181 Moment len = Moment (l) * one_beat;
1184 Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ());
1185 Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ());
1187 SCM list = scm_list_n (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED);
1188 Sequential_music *seq = new Sequential_music (SCM_EOL);
1189 seq->set_mus_property ("elements", list);
1192 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1193 sp->set_mus_property ("element", seq->self_scm ());
1197 scm_gc_unprotect_object (p3->self_scm ());
1198 scm_gc_unprotect_object (p2->self_scm ());
1199 scm_gc_unprotect_object (p1->self_scm ());
1200 scm_gc_unprotect_object (seq->self_scm ());
1205 TODO: should make alias TimingContext for Score
1208 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1213 shorthand_command_req { $$ = $1; }
1214 | verbose_command_req { $$ = $1; }
1217 shorthand_command_req:
1228 Span_req*b= new Span_req;
1229 b->set_span_dir (START);
1230 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1234 THIS->last_beam_start_ = b->self_scm ();
1237 Span_req*b= new Span_req;
1238 b->set_span_dir ( STOP);
1239 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1243 $$ = new Breathing_sign_req;
1246 $$ = new Porrectus_req;
1250 verbose_command_req:
1251 COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1252 Span_req * sp_p = new Span_req;
1253 sp_p-> set_span_dir ( Direction ($2));
1254 sp_p->set_mus_property ("span-type",$3);
1255 sp_p->set_spot (THIS->here_input ());
1259 Mark_req * m = new Mark_req;
1263 Mark_req *m = new Mark_req;
1264 m->set_mus_property ("label", $2);
1269 Break_req * b = new Break_req;
1271 if (!gh_number_p (s))
1274 b->set_mus_property ("penalty", s);
1275 b->set_spot (THIS->here_input ());
1278 | SKIP duration_length {
1279 Skip_req * skip_p = new Skip_req;
1280 skip_p->set_mus_property ("duration", $2);
1288 Key_change_req *key_p= new Key_change_req;
1291 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1292 Key_change_req *key_p= new Key_change_req;
1294 key_p->set_mus_property ("pitch-alist", $3);
1295 ((Music*)key_p)->transpose (* unsmob_pitch ($2));
1302 $$ = new Link_array<Request>;
1304 | post_requests post_request {
1305 $2->set_spot (THIS->here_input ());
1317 request_that_take_dir:
1320 | script_abbreviation {
1321 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1322 Articulation_req *a = new Articulation_req;
1323 if (gh_string_p (s))
1324 a->set_mus_property ("articulation-type", s);
1325 else THIS->parser_error (_ ("Expecting string as script definition"));
1331 script_dir request_that_take_dir {
1332 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1333 gs->set_direction (Direction ($1));
1335 $2->origin ()->warning (_ ("Can't specify direction for this request"));
1341 REQUEST_IDENTIFIER {
1342 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1343 $$->set_spot (THIS->here_input ());
1345 | DYNAMICSCRIPT embedded_scm {
1347 TODO: junkme, use text-type == dynamic
1349 Text_script_req *d = new Text_script_req;
1350 SCM dyn = ly_symbol2scm ("dynamic");
1351 d->set_mus_property ("text-type" , dyn);
1352 d->set_mus_property ("text", $2);
1353 d->set_spot (THIS->here_input ());
1356 | SPANREQUEST bare_int STRING {
1357 Span_req * sp_p = new Span_req;
1358 sp_p->set_span_dir ( Direction ($2));
1359 sp_p->set_mus_property ("span-type", $3);
1360 sp_p->set_spot (THIS->here_input ());
1364 Tremolo_req* a = new Tremolo_req;
1365 a->set_spot (THIS->here_input ());
1366 a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1370 Articulation_req * a = new Articulation_req;
1371 a->set_mus_property ("articulation-type", $2);
1372 a->set_spot (THIS->here_input ());
1376 duh, junk this syntax from the parser, if possible.
1379 Arpeggio_req *a = new Arpeggio_req;
1380 a->set_spot (THIS->here_input ());
1384 Glissando_req *g = new Glissando_req;
1385 g->set_spot /* No pun intended */ (THIS->here_input ());
1412 | NOTENAME_PITCH sup_quotes {
1413 Pitch p = *unsmob_pitch ($1);
1415 $$ = p.smobbed_copy ();
1417 | NOTENAME_PITCH sub_quotes {
1418 Pitch p =* unsmob_pitch ($1);
1421 $$ = p.smobbed_copy ();
1434 | TONICNAME_PITCH sup_quotes {
1435 Pitch p = *unsmob_pitch ($1);
1437 $$ = p.smobbed_copy ();
1439 | TONICNAME_PITCH sub_quotes {
1440 Pitch p =* unsmob_pitch ($1);
1443 $$ = p.smobbed_copy ();
1458 PITCH embedded_scm {
1460 if (!unsmob_pitch ($2)) {
1461 THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1462 $$ = Pitch ().smobbed_copy ();
1468 DURATION embedded_scm {
1470 if (!unsmob_duration ($2))
1472 THIS->parser_error (_ ("Must have duration object"));
1473 $$ = Duration ().smobbed_copy ();
1480 if (!THIS->lexer_p_->lyric_state_b ())
1481 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1482 $$ = new Extender_req;
1488 if (!THIS->lexer_p_->lyric_state_b ())
1489 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1490 $$ = new Hyphen_req;
1495 close_request_parens {
1497 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1500 close_request_parens:
1502 Span_req* s= new Span_req;
1504 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1507 Span_req* s= new Span_req;
1509 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1512 Span_req*s =new Span_req;
1514 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1517 Span_req*s =new Span_req;
1519 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1525 open_request_parens {
1527 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1531 open_request_parens:
1533 Span_req *s = new Span_req;
1534 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1539 Span_req* s= new Span_req;
1541 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1544 Span_req* s= new Span_req;
1546 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1552 Text_script_req *t = new Text_script_req;
1553 t->set_mus_property ("text", $1);
1554 t->set_spot (THIS->here_input ());
1558 Text_script_req *t = new Text_script_req;
1559 t->set_mus_property ("text", $1);
1560 t->set_spot (THIS->here_input ());
1564 String ds = to_str ($1);
1565 Text_script_req* t = new Text_script_req;
1566 SCM finger = ly_symbol2scm ("finger");
1567 t->set_mus_property ("text", ly_str02scm (ds.ch_C ()));
1568 t->set_mus_property ("text-type" , finger);
1569 t->set_spot (THIS->here_input ());
1574 script_abbreviation:
1576 $$ = gh_str02scm ("Hat");
1579 $$ = gh_str02scm ("Plus");
1582 $$ = gh_str02scm ("Dash");
1585 $$ = gh_str02scm ("Bar");
1588 $$ = gh_str02scm ("Larger");
1591 $$ = gh_str02scm ("Dot");
1598 | '-' { $$ = CENTER; }
1603 $$ = new Link_array<Request>;
1605 | pre_requests open_request {
1617 multiplied_duration {
1620 | verbose_duration {
1625 optional_notemode_duration:
1627 Duration dd = THIS->default_duration_;
1628 $$ = dd.smobbed_copy ();
1630 THIS->beam_check ($$);
1632 | multiplied_duration {
1634 THIS->default_duration_ = *unsmob_duration ($$);
1636 THIS->beam_check ($$);
1638 | verbose_duration {
1640 THIS->default_duration_ = *unsmob_duration ($$);
1645 bare_unsigned dots {
1647 if (!is_duration_b ($1))
1648 THIS->parser_error (_f ("not a duration: %d", $1));
1652 $$ = Duration (l, $2).smobbed_copy ();
1654 | DURATION_IDENTIFIER dots {
1655 Duration *d =unsmob_duration ($1);
1656 Duration k (d->duration_log (),d->dot_count () + $2);
1657 $$ = k.smobbed_copy ();
1664 multiplied_duration:
1668 | multiplied_duration '*' bare_unsigned {
1669 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1671 | multiplied_duration '*' FRACTION {
1672 Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr ($3)));
1674 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1679 FRACTION { $$ = $1; }
1680 | UNSIGNED '/' UNSIGNED {
1681 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1699 | ':' bare_unsigned {
1700 if (!is_duration_b ($2))
1701 THIS->parser_error (_f ("not a duration: %d", $2));
1720 Bass_figure_req *bfr = new Bass_figure_req;
1721 $$ = bfr->self_scm();
1722 scm_gc_unprotect_object ($$);
1725 Bass_figure_req *bfr = new Bass_figure_req;
1726 $$ = bfr->self_scm();
1728 bfr->set_mus_property ("figure", gh_int2scm ($1));
1730 scm_gc_unprotect_object ($$);
1732 | bass_figure bass_mod {
1733 Music *m = unsmob_music ($1);
1735 SCM salter =m->get_mus_property ("alteration");
1736 int alter = gh_number_p( salter) ? gh_scm2int (salter) : 0;
1737 m->set_mus_property ("alteration",
1738 gh_int2scm (alter + $2));
1740 m->set_mus_property ("alteration", gh_int2scm (0));
1748 unsmob_music ($$)->set_mus_property ("bracket-start", SCM_BOOL_T);
1753 | br_bass_figure ']' {
1755 unsmob_music ($1)->set_mus_property ("bracket-stop", SCM_BOOL_T);
1763 | figure_list br_bass_figure {
1764 $$ = gh_cons ($2, $1);
1769 FIGURE_OPEN figure_list FIGURE_CLOSE {
1770 Music * m = new Request_chord (SCM_EOL);
1771 $2 = scm_reverse_x ($2, SCM_EOL);
1772 m->set_mus_property ("elements", $2);
1773 $$ = m->self_scm ();
1784 pitch exclamations questions optional_notemode_duration optional_rest {
1786 Input i = THIS->pop_spot ();
1787 if (!THIS->lexer_p_->note_state_b ())
1788 THIS->parser_error (_ ("Have to be in Note mode for notes"));
1796 n->set_mus_property ("pitch", $1);
1797 n->set_mus_property ("duration", $4);
1801 n->set_mus_property ("cautionary", SCM_BOOL_T);
1802 if ($2 % 2 || $3 % 2)
1803 n->set_mus_property ("force-accidental", SCM_BOOL_T);
1805 Simultaneous_music*v = new Request_chord (SCM_EOL);
1806 v->set_mus_property ("elements", scm_list_n (n->self_scm (), SCM_UNDEFINED));
1812 | figure_spec optional_notemode_duration {
1813 Music * m = unsmob_music ($1);
1814 Input i = THIS->pop_spot ();
1816 for (SCM s = m->get_mus_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
1818 unsmob_music (ly_car (s))->set_mus_property ("duration", $2);
1822 | RESTNAME optional_notemode_duration {
1824 Input i = THIS->pop_spot ();
1825 SCM e = SCM_UNDEFINED;
1826 if (ly_scm2string ($1) =="s") {
1828 Skip_req * skip_p = new Skip_req;
1829 skip_p->set_mus_property ("duration" ,$2);
1830 skip_p->set_spot (i);
1831 e = skip_p->self_scm ();
1834 Rest_req * rest_req_p = new Rest_req;
1835 rest_req_p->set_mus_property ("duration", $2);
1836 rest_req_p->set_spot (i);
1837 e = rest_req_p->self_scm ();
1839 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1840 velt_p-> set_mus_property ("elements", scm_list_n (e,SCM_UNDEFINED));
1841 velt_p->set_spot (i);
1845 | MULTI_MEASURE_REST optional_notemode_duration {
1846 Input i = THIS->pop_spot ();
1848 Skip_req * sk = new Skip_req;
1849 sk->set_mus_property ("duration", $2);
1850 Span_req *sp1 = new Span_req;
1851 Span_req *sp2 = new Span_req;
1852 sp1-> set_span_dir ( START);
1853 sp2-> set_span_dir ( STOP);
1854 SCM r = ly_str02scm ("rest");
1855 sp1->set_mus_property ("span-type", r);
1856 sp2->set_mus_property ("span-type", r);
1858 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1859 rqc1->set_mus_property ("elements", scm_list_n (sp1->self_scm (), SCM_UNDEFINED));
1860 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1861 rqc2->set_mus_property ("elements", scm_list_n (sk->self_scm (), SCM_UNDEFINED));;
1862 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1863 rqc3->set_mus_property ("elements", scm_list_n (sp2->self_scm (), SCM_UNDEFINED));;
1865 SCM ms = scm_list_n (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1867 $$ = new Sequential_music (SCM_EOL);
1868 $$->set_mus_property ("elements", ms);
1870 | STRING optional_notemode_duration {
1871 Input i = THIS->pop_spot ();
1873 Lyric_req* lreq_p = new Lyric_req;
1874 lreq_p->set_mus_property ("text", $1);
1875 lreq_p->set_mus_property ("duration",$2);
1876 lreq_p->set_spot (i);
1877 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1878 velt_p->set_mus_property ("elements", scm_list_n (lreq_p->self_scm (), SCM_UNDEFINED));
1883 Input i = THIS->pop_spot ();
1885 if (!THIS->lexer_p_->chord_state_b ())
1886 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1893 steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1894 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1895 $$->set_spot (THIS->here_input ());
1902 | CHORD_COLON chord_notes {
1911 | chord_notes '.' chord_step {
1912 $$ = gh_append2 ($$, $3);
1920 | CHORD_CARET chord_notes {
1930 | '/' steno_tonic_pitch {
1939 | CHORD_BASS steno_tonic_pitch {
1946 $$ = gh_cons ($1, SCM_EOL);
1948 | CHORDMODIFIER_PITCH {
1949 $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
1951 | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1952 $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
1960 m.notename_i_ = ($1 - 1) % 7;
1961 m.octave_i_ = $1 > 7 ? 1 : 0;
1962 m.alteration_i_ = 0;
1964 $$ = m.smobbed_copy ();
1966 | bare_unsigned '+' {
1968 m.notename_i_ = ($1 - 1) % 7;
1969 m.octave_i_ = $1 > 7 ? 1 : 0;
1970 m.alteration_i_ = 1;
1973 $$ = m.smobbed_copy ();
1975 | bare_unsigned CHORD_MINUS {
1977 m.notename_i_ = ($1 - 1) % 7;
1978 m.octave_i_ = $1 > 7 ? 1 : 0;
1979 m.alteration_i_ = -1;
1981 $$ = m.smobbed_copy ();
1989 number_expression '+' number_term {
1990 $$ = scm_sum ($1, $3);
1992 | number_expression '-' number_term {
1993 $$ = scm_difference ($1, $3);
2002 | number_factor '*' number_factor {
2003 $$ = scm_product ($1, $3);
2005 | number_factor '/' number_factor {
2006 $$ = scm_divide ($1, $3);
2011 '(' number_expression ')' {
2014 | '-' number_factor { /* %prec UNARY_MINUS */
2015 $$ = scm_difference ($2, SCM_UNDEFINED);
2023 $$ = gh_int2scm ($1);
2028 | NUMBER_IDENTIFIER {
2032 $$ = gh_double2scm (gh_scm2double ($1) CM );
2035 $$ = gh_double2scm (gh_scm2double ($1) PT);
2038 $$ = gh_double2scm (gh_scm2double ($1) INCH);
2041 $$ = gh_double2scm (gh_scm2double ($1) MM);
2044 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
2060 if (scm_integer_p ($1) == SCM_BOOL_T)
2062 int k = gh_scm2int ($1);
2066 THIS->parser_error (_ ("need integer number arg"));
2080 | STRING_IDENTIFIER {
2083 | string '+' string {
2084 $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
2091 | exclamations '!' { $$ ++; }
2096 | questions '?' { $$ ++; }
2103 My_lily_parser::set_yydebug (bool b)
2110 extern My_lily_parser * current_parser;
2113 My_lily_parser::do_yyparse ()
2116 current_parser = this;;
2117 yyparse ((void*)this);
2122 Should make this optional? It will also complain when you do
2126 which is entirely legitimate.
2128 Or we can scrap it. Barchecks should detect wrong durations, and
2129 skipTypesetting speeds it up a lot.
2132 My_lily_parser::beam_check (SCM dur)
2134 Duration *d = unsmob_duration (dur);
2135 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2137 Music * m = unsmob_music (last_beam_start_);
2138 m->origin ()->warning (_("Suspect duration found following this beam"));
2140 last_beam_start_ = SCM_EOL;