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"
50 #include "relative-music.hh"
51 #include "lyric-combine-music.hh"
52 #include "transposed-music.hh"
53 #include "time-scaled-music.hh"
54 #include "repeated-music.hh"
55 #include "untransposable-music.hh"
56 #include "lilypond-input-version.hh"
57 #include "grace-music.hh"
58 #include "part-combine-music.hh"
59 #include "scm-hash.hh"
60 #include "auto-change-iterator.hh"
61 #include "un-relativable-music.hh"
65 regular_identifier_b (SCM id)
67 String str = ly_scm2string (id);
68 char const *s = str.ch_C() ;
73 v = v && isalpha (*s);
81 set_property_music (SCM sym, SCM value)
83 Music * p = new Music (SCM_EOL);
84 p->set_mus_property ("symbol", sym);
85 p->set_mus_property ("iterator-ctor",
86 Property_iterator::constructor_cxx_function);
88 p->set_mus_property ("value", value);
95 return t && t == 1 << intlog2 (t);
99 set_music_properties (Music *p, SCM a)
101 for (SCM k = a; gh_pair_p (k); k = ly_cdr (k))
103 p->internal_set_mus_property (ly_caar (k), ly_cdar (k));
113 // needed for bison.simple's malloc () and free ()
123 #define YYERROR_VERBOSE 1
125 #define YYPARSE_PARAM my_lily_parser_l
126 #define YYLEX_PARAM my_lily_parser_l
128 ((My_lily_parser *) my_lily_parser_l)
130 #define yyerror THIS->parser_error
131 #define ARRAY_SIZE(a,s) if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
135 /* We use SCMs to do strings, because it saves us the trouble of
136 deleting them. Let's hope that a stack overflow doesnt trigger a move
137 of the parse stack onto the heap. */
142 Link_array<Request> *reqvec;
144 String *string; // needed by the lexer as temporary scratch area.
147 Scheme_hash_table *scmhash;
148 Music_output_def * outputdef;
160 yylex (YYSTYPE *s, void * v_l)
162 My_lily_parser *pars_l = (My_lily_parser*) v_l;
163 My_lily_lexer * lex_l = pars_l->lexer_p_;
165 lex_l->lexval_l = (void*) s;
166 return lex_l->yylex ();
174 /* tokens which are not keywords */
184 %token CHORDMODIFIERS
192 %token GROBDESCRIPTIONS
198 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
199 %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
209 %token MULTI_MEASURE_REST
221 %token OVERRIDE SET REVERT
234 %token COMMANDSPANREQUEST
236 %token OUTPUTPROPERTY
247 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
248 %token E_LEFTSQUARE E_RIGHTSQUARE E_TILDE
250 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
254 %type <i> exclamations questions dots optional_rest
255 %type <i> bass_number bass_mod
256 %type <scm> br_bass_figure bass_figure figure_list figure_spec
258 %token <scm> NOTENAME_PITCH
259 %token <scm> TONICNAME_PITCH
260 %token <scm> CHORDMODIFIER_PITCH
261 %token <scm> DURATION_IDENTIFIER
262 %token <scm> FRACTION
263 %token <id> IDENTIFIER
266 %token <scm> SCORE_IDENTIFIER
267 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
269 %token <scm> NUMBER_IDENTIFIER
270 %token <scm> REQUEST_IDENTIFIER
271 %token <scm> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
272 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
273 %token <scm> RESTNAME
279 %type <outputdef> output_def
280 %type <scmhash> lilypond_header lilypond_header_body
281 %type <request> open_request_parens close_request_parens open_request close_request
282 %type <request> request_with_dir request_that_take_dir verbose_request
283 %type <i> sub_quotes sup_quotes
284 %type <music> simple_element request_chord command_element Simple_music Composite_music
285 %type <music> Repeated_music
286 %type <scm> Alternative_music
287 %type <i> tremolo_type
288 %type <i> bare_int bare_unsigned
291 %type <scm> identifier_init
293 %type <scm> steno_duration optional_notemode_duration multiplied_duration
294 %type <scm> verbose_duration
296 %type <reqvec> pre_requests post_requests
297 %type <request> gen_text_def
298 %type <scm> steno_pitch pitch absolute_pitch
299 %type <scm> explicit_pitch steno_tonic_pitch
301 %type <scm> chord_additions chord_subtractions chord_notes chord_step
303 %type <scm> chord_note chord_inversion chord_bass
304 %type <scm> duration_length fraction
306 %type <scm> embedded_scm scalar
307 %type <music> Music Sequential_music Simultaneous_music
308 %type <music> relative_music re_rhythmed_music part_combined_music
309 %type <music> property_def translator_change
310 %type <scm> Music_list
311 %type <outputdef> music_output_def_body
312 %type <request> shorthand_command_req
313 %type <request> post_request
314 %type <music> command_req verbose_command_req
315 %type <request> extender_req
316 %type <request> hyphen_req
317 %type <scm> string bare_number number_expression number_term number_factor
319 %type <score> score_block score_body
321 %type <scm> translator_spec_block translator_spec_body
322 %type <tempo> tempo_request
323 %type <scm> notenames_body notenames_block chordmodifiers_block
324 %type <scm> script_abbreviation
330 /* We don't assign precedence to / and *, because we might need varied
331 prec levels in different prods */
337 lilypond: /* empty */
338 | lilypond toplevel_expression {}
339 | lilypond assignment { }
341 THIS->error_level_i_ = 1;
344 THIS->error_level_i_ = 1;
350 THIS->lexer_p_->pitchname_tab_ = $1;
352 | chordmodifiers_block {
353 THIS->lexer_p_->chordmodifier_tab_ = $1;
357 scm_gc_unprotect_object (global_header_p->self_scm ());
358 global_header_p = $1;
361 score_global_array.push ($1);
364 if (dynamic_cast<Paper_def*> ($1))
365 THIS->lexer_p_->set_identifier (gh_str02scm ("$defaultpaper"), $1->self_scm ());
366 else if (dynamic_cast<Midi_def*> ($1))
367 THIS->lexer_p_->set_identifier (gh_str02scm ("$defaultmidi"), $1->self_scm ());
380 chordmodifiers_block:
381 CHORDMODIFIERS notenames_body { $$ = $2; }
385 PITCHNAMES notenames_body { $$ = $2; }
390 int i = scm_ilength ($1);
392 SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
393 for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) {
394 SCM pt = ly_cdar (s);
395 if (!unsmob_pitch (pt))
396 THIS->parser_error ("Need pitch object.");
398 scm_hashq_set_x (tab, ly_caar (s), pt);
405 lilypond_header_body:
407 $$ = new Scheme_hash_table;
408 THIS->lexer_p_-> scope_l_arr_.push ($$);
410 | lilypond_header_body assignment {
416 HEADER '{' lilypond_header_body '}' {
418 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 ($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->variable_tab_);
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->variable_tab_);
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->variable_tab_);
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->variable_tab_);
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 ();
792 $$->set_spot (THIS->here_input());
800 CONTEXT STRING Music {
801 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
802 csm->set_mus_property ("element", $3->self_scm ());
803 scm_gc_unprotect_object ($3->self_scm ());
805 csm->set_mus_property ("context-type",$2);
806 csm->set_mus_property ("context-id", ly_str02scm (""));
810 | AUTOCHANGE STRING Music {
811 Music * chm = new Music_wrapper (SCM_EOL);
812 chm->set_mus_property ("element", $3->self_scm ());
813 chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_cxx_function);
815 scm_gc_unprotect_object ($3->self_scm ());
816 chm->set_mus_property ("what", $2);
819 chm->set_spot (*$3->origin ());
824 The other version is for easier debugging of
825 Sequential_music_iterator in combination with grace notes.
828 SCM start = THIS->lexer_p_->lookup_identifier ("startGraceMusic");
829 SCM stop = THIS->lexer_p_->lookup_identifier ("stopGraceMusic");
830 Music *startm = unsmob_music (start);
831 Music *stopm = unsmob_music (stop);
835 stopm = stopm->clone ();
836 ms = gh_cons (stopm->self_scm (), ms);
837 scm_gc_unprotect_object (stopm->self_scm ());
839 ms = gh_cons ($2->self_scm (), ms);
840 scm_gc_unprotect_object ($2->self_scm());
842 startm = startm->clone ();
843 ms = gh_cons (startm->self_scm () , ms);
844 scm_gc_unprotect_object (startm->self_scm ());
847 Music* seq = new Sequential_music (SCM_EOL);
848 seq->set_mus_property ("elements", ms);
850 $$ = new Grace_music (SCM_EOL);
851 $$->set_mus_property ("element", seq->self_scm ());
852 scm_gc_unprotect_object (seq->self_scm ());
854 $$ = new Grace_music (SCM_EOL);
855 $$->set_mus_property ("element", $2->self_scm ());
856 scm_gc_unprotect_object ($2->self_scm ());
859 | CONTEXT string '=' string Music {
860 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
861 csm->set_mus_property ("element", $5->self_scm ());
862 scm_gc_unprotect_object ($5->self_scm ());
864 csm->set_mus_property ("context-type", $2);
865 csm->set_mus_property ("context-id", $4);
876 int n = gh_scm2int (ly_car ($3)); int d = gh_scm2int (ly_cdr ($3));
878 $$ = new Time_scaled_music (SCM_EOL);
879 $$->set_spot (THIS->pop_spot ());
882 $$->set_mus_property ("element", mp->self_scm ());
883 scm_gc_unprotect_object (mp->self_scm ());
884 $$->set_mus_property ("numerator", gh_int2scm (n));
885 $$->set_mus_property ("denominator", gh_int2scm (d));
886 $$->compress (Moment (Rational (n,d)));
889 | Repeated_music { $$ = $1; }
890 | Simultaneous_music { $$ = $1; }
891 | Sequential_music { $$ = $1; }
892 | TRANSPOSE pitch Music {
893 $$ = new Transposed_music (SCM_EOL);
895 Pitch pit = *unsmob_pitch ($2);
898 $$->set_mus_property ("element", p->self_scm ());
899 scm_gc_unprotect_object (p->self_scm ());
901 | TRANSPOSE steno_tonic_pitch Music {
902 $$ = new Transposed_music (SCM_EOL);
904 Pitch pit = *unsmob_pitch ($2);
907 $$->set_mus_property ("element", p->self_scm ());
908 scm_gc_unprotect_object (p->self_scm ());
911 | APPLY embedded_scm Music {
912 SCM ret = gh_call1 ($2, $3->self_scm ());
913 Music *m = unsmob_music (ret);
915 THIS->parser_error ("\\apply must return a Music");
916 m = new Music (SCM_EOL);
921 { THIS->lexer_p_->push_note_state (); }
924 THIS->lexer_p_->pop_state ();
927 { THIS->lexer_p_->push_figuredbass_state (); }
930 Music * chm = new Untransposable_music () ;
931 chm->set_mus_property ("element", $3->self_scm ());
934 THIS->lexer_p_->pop_state ();
937 { THIS->lexer_p_->push_chord_state (); }
940 Music * chm = new Un_relativable_music ;
941 chm->set_mus_property ("element", $3->self_scm ());
944 THIS->lexer_p_->pop_state ();
947 { THIS->lexer_p_->push_lyric_state (); }
951 THIS->lexer_p_->pop_state ();
953 | relative_music { $$ = $1; }
954 | re_rhythmed_music { $$ = $1; }
955 | part_combined_music { $$ = $1; }
959 RELATIVE absolute_pitch Music {
961 Pitch pit = *unsmob_pitch ($2);
962 $$ = new Relative_octave_music (SCM_EOL);
964 $$->set_mus_property ("element", p->self_scm ());
965 scm_gc_unprotect_object (p->self_scm ());
967 $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ());
973 ADDLYRICS Music Music {
974 Lyric_combine_music * l = new Lyric_combine_music (SCM_EOL);
975 l->set_mus_property ("elements", gh_list ($2->self_scm (), $3->self_scm (), SCM_UNDEFINED));
976 scm_gc_unprotect_object ($3->self_scm ());
977 scm_gc_unprotect_object ($2->self_scm ());
983 PARTCOMBINE STRING Music Music {
984 Part_combine_music * p = new Part_combine_music (SCM_EOL);
986 p->set_mus_property ("what", $2);
987 p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED));
989 scm_gc_unprotect_object ($3->self_scm ());
990 scm_gc_unprotect_object ($4->self_scm ());
997 TRANSLATOR STRING '=' STRING {
998 Music * t = new Music (SCM_EOL);
999 t->set_mus_property ("iterator-ctor",
1000 Change_iterator::constructor_cxx_function);
1001 t-> set_mus_property ("change-to-type", $2);
1002 t-> set_mus_property ("change-to-id", $4);
1005 $$->set_spot (THIS->here_input ());
1010 PROPERTY STRING '.' STRING '=' scalar {
1012 Music *t = set_property_music (scm_string_to_symbol ($4), $6);
1013 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1015 csm->set_mus_property ("element", t->self_scm ());
1016 scm_gc_unprotect_object (t->self_scm ());
1019 $$->set_spot (THIS->here_input ());
1021 csm-> set_mus_property ("context-type", $2);
1023 | PROPERTY STRING '.' STRING UNSET {
1024 Music *t = new Music (SCM_EOL);
1026 t->set_mus_property ("iterator-ctor",
1027 Property_unset_iterator::constructor_cxx_function);
1028 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1030 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1031 csm->set_mus_property ("element", t->self_scm ());
1032 scm_gc_unprotect_object (t->self_scm ());
1035 $$->set_spot (THIS->here_input ());
1037 csm-> set_mus_property ("context-type", $2);
1039 | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm {
1040 Music *t = new Music (SCM_EOL);
1041 t->set_mus_property ("iterator-ctor",
1042 Push_property_iterator::constructor_cxx_function);
1043 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1044 t->set_mus_property ("pop-first", SCM_BOOL_T);
1045 t->set_mus_property ("grob-property", $6);
1046 t->set_mus_property ("grob-value", $8);
1047 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1048 csm->set_mus_property ("element", t->self_scm ());
1049 scm_gc_unprotect_object (t->self_scm ());
1051 $$->set_spot (THIS->here_input ());
1053 csm-> set_mus_property ("context-type", $2);
1055 | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
1056 Music *t = new Music (SCM_EOL);
1057 t->set_mus_property ("iterator-ctor",
1058 Push_property_iterator::constructor_cxx_function);
1059 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1060 t->set_mus_property ("grob-property", $6);
1061 t->set_mus_property ("grob-value", $8);
1062 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1063 csm->set_mus_property ("element", t->self_scm ());
1064 scm_gc_unprotect_object (t->self_scm ());
1067 $$->set_spot (THIS->here_input ());
1069 csm-> set_mus_property ("context-type", $2);
1071 | PROPERTY STRING '.' STRING REVERT embedded_scm {
1072 Music *t = new Music (SCM_EOL);
1073 t->set_mus_property ("iterator-ctor",
1074 Pop_property_iterator::constructor_cxx_function);
1075 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1076 t->set_mus_property ("grob-property", $6);
1078 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1079 csm->set_mus_property ("element", t->self_scm ());
1080 scm_gc_unprotect_object (t->self_scm ());
1083 $$->set_spot (THIS->here_input ());
1085 csm-> set_mus_property ("context-type", $2);
1091 | bare_int { $$ = gh_int2scm ($1); }
1092 | embedded_scm { $$ = $1; }
1099 } /*cont */ simple_element post_requests {
1100 Music_sequence *l = dynamic_cast<Music_sequence*> ($3);
1103 for (int i=0; i < $1->size (); i++) {
1104 Music * m = $1->elem (i);
1105 l->append_music (m);
1117 $$ = new Request_chord (SCM_EOL);
1118 $$->set_mus_property ("elements", gh_cons ($1->self_scm (), SCM_EOL));
1119 $$-> set_spot (THIS->here_input ());
1120 $1-> set_spot (THIS->here_input ());
1123 $$ = new Music (gh_list (gh_cons (ly_symbol2scm ("name"), ly_symbol2scm ("separator")), SCM_UNDEFINED));
1124 $$->set_spot (THIS->here_input ());
1128 extern Music * get_barcheck();
1129 $$ = get_barcheck ();
1130 $$->set_spot (THIS->here_input ());
1133 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1135 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1136 csm->set_mus_property ("element", t->self_scm ());
1137 scm_gc_unprotect_object (t->self_scm ());
1140 $$->set_spot (THIS->here_input ());
1142 csm->set_mus_property ("context-type", ly_str02scm ("Score"));
1144 | PARTIAL duration_length {
1145 Moment m = - unsmob_duration ($2)->length_mom ();
1146 Music * p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1148 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1149 sp->set_mus_property ("element", p->self_scm ());
1150 scm_gc_unprotect_object (p->self_scm ());
1153 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1156 SCM func = scm_primitive_eval (ly_symbol2scm ("clef-name-to-properties"));
1157 SCM result = gh_call1 (func, $2);
1160 for (SCM s = result ; gh_pair_p (s); s = ly_cdr (s)) {
1161 Music * p = new Music (SCM_EOL);
1162 set_music_properties (p, ly_car (s));
1163 l = gh_cons (p->self_scm (), l);
1164 scm_gc_unprotect_object (p->self_scm ());
1166 Sequential_music * seq = new Sequential_music (SCM_EOL);
1167 seq->set_mus_property ("elements", l);
1169 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1170 sp->set_mus_property ("element", seq->self_scm ());
1171 scm_gc_unprotect_object (seq->self_scm ());
1174 sp-> set_mus_property ("context-type", ly_str02scm ("Staff"));
1177 Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2);
1179 int l = gh_scm2int (ly_car ($2));
1180 int o = gh_scm2int (ly_cdr ($2));
1182 Moment one_beat = Moment (1)/Moment (o);
1183 Moment len = Moment (l) * one_beat;
1186 Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ());
1187 Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ());
1189 SCM list = scm_list_n (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED);
1190 Sequential_music *seq = new Sequential_music (SCM_EOL);
1191 seq->set_mus_property ("elements", list);
1194 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1195 sp->set_mus_property ("element", seq->self_scm ());
1199 scm_gc_unprotect_object (p3->self_scm ());
1200 scm_gc_unprotect_object (p2->self_scm ());
1201 scm_gc_unprotect_object (p1->self_scm ());
1202 scm_gc_unprotect_object (seq->self_scm ());
1207 TODO: should make alias TimingContext for Score
1210 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1215 shorthand_command_req { $$ = $1; }
1216 | verbose_command_req { $$ = $1; }
1219 shorthand_command_req:
1230 Span_req*b= new Span_req;
1231 b->set_span_dir (START);
1232 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1236 THIS->last_beam_start_ = b->self_scm ();
1239 Span_req*b= new Span_req;
1240 b->set_span_dir ( STOP);
1241 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1245 Span_req *b = new Span_req;
1246 b->set_span_dir (START);
1247 b->set_mus_property ("span-type", ly_str02scm ("ligature-bracket"));
1249 THIS->last_ligature_start_ = b->self_scm ();
1252 Span_req *b = new Span_req;
1253 b->set_span_dir (STOP);
1254 b->set_mus_property ("span-type", ly_str02scm ("ligature-bracket"));
1258 $$ = new Breathing_sign_req;
1261 $$ = new Porrectus_req;
1265 verbose_command_req:
1266 COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1267 Span_req * sp_p = new Span_req;
1268 sp_p-> set_span_dir ( Direction ($2));
1269 sp_p->set_mus_property ("span-type",$3);
1270 sp_p->set_spot (THIS->here_input ());
1274 Mark_req * m = new Mark_req;
1278 Mark_req *m = new Mark_req;
1279 m->set_mus_property ("label", $2);
1284 Break_req * b = new Break_req;
1286 if (!gh_number_p (s))
1289 b->set_mus_property ("penalty", s);
1290 b->set_spot (THIS->here_input ());
1293 | SKIP duration_length {
1294 Skip_req * skip_p = new Skip_req;
1295 skip_p->set_mus_property ("duration", $2);
1303 Key_change_req *key_p= new Key_change_req;
1306 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1307 Key_change_req *key_p= new Key_change_req;
1309 key_p->set_mus_property ("pitch-alist", $3);
1310 ((Music*)key_p)->transpose (* unsmob_pitch ($2));
1317 $$ = new Link_array<Request>;
1319 | post_requests post_request {
1320 $2->set_spot (THIS->here_input ());
1332 request_that_take_dir:
1335 | script_abbreviation {
1336 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1337 Articulation_req *a = new Articulation_req;
1338 if (gh_string_p (s))
1339 a->set_mus_property ("articulation-type", s);
1340 else THIS->parser_error (_ ("Expecting string as script definition"));
1346 script_dir request_that_take_dir {
1347 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1348 gs->set_direction (Direction ($1));
1350 $2->origin ()->warning (_ ("Can't specify direction for this request"));
1356 REQUEST_IDENTIFIER {
1357 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1358 $$->set_spot (THIS->here_input ());
1360 | DYNAMICSCRIPT embedded_scm {
1362 TODO: junkme, use text-type == dynamic
1364 Text_script_req *d = new Text_script_req;
1365 SCM dyn = ly_symbol2scm ("dynamic");
1366 d->set_mus_property ("text-type" , dyn);
1367 d->set_mus_property ("text", $2);
1368 d->set_spot (THIS->here_input ());
1371 | SPANREQUEST bare_int STRING {
1372 Span_req * sp_p = new Span_req;
1373 sp_p->set_span_dir ( Direction ($2));
1374 sp_p->set_mus_property ("span-type", $3);
1375 sp_p->set_spot (THIS->here_input ());
1379 Tremolo_req* a = new Tremolo_req;
1380 a->set_spot (THIS->here_input ());
1381 a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1385 Articulation_req * a = new Articulation_req;
1386 a->set_mus_property ("articulation-type", $2);
1387 a->set_spot (THIS->here_input ());
1391 duh, junk this syntax from the parser, if possible.
1394 Arpeggio_req *a = new Arpeggio_req;
1395 a->set_spot (THIS->here_input ());
1399 Glissando_req *g = new Glissando_req;
1400 g->set_spot /* No pun intended */ (THIS->here_input ());
1427 | NOTENAME_PITCH sup_quotes {
1428 Pitch p = *unsmob_pitch ($1);
1430 $$ = p.smobbed_copy ();
1432 | NOTENAME_PITCH sub_quotes {
1433 Pitch p =* unsmob_pitch ($1);
1436 $$ = p.smobbed_copy ();
1449 | TONICNAME_PITCH sup_quotes {
1450 Pitch p = *unsmob_pitch ($1);
1452 $$ = p.smobbed_copy ();
1454 | TONICNAME_PITCH sub_quotes {
1455 Pitch p =* unsmob_pitch ($1);
1458 $$ = p.smobbed_copy ();
1473 PITCH embedded_scm {
1475 if (!unsmob_pitch ($2)) {
1476 THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1477 $$ = Pitch ().smobbed_copy ();
1483 DURATION embedded_scm {
1485 if (!unsmob_duration ($2))
1487 THIS->parser_error (_ ("Must have duration object"));
1488 $$ = Duration ().smobbed_copy ();
1495 if (!THIS->lexer_p_->lyric_state_b ())
1496 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1497 $$ = new Extender_req;
1503 if (!THIS->lexer_p_->lyric_state_b ())
1504 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1505 $$ = new Hyphen_req;
1510 close_request_parens {
1512 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1515 close_request_parens:
1517 Span_req* s= new Span_req;
1519 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1522 Span_req* s= new Span_req;
1524 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1527 Span_req*s =new Span_req;
1529 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1532 Span_req*s =new Span_req;
1534 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1540 open_request_parens {
1542 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1546 open_request_parens:
1548 Span_req *s = new Span_req;
1549 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1554 Span_req* s= new Span_req;
1556 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1559 Span_req* s= new Span_req;
1561 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1567 Text_script_req *t = new Text_script_req;
1568 t->set_mus_property ("text", $1);
1569 t->set_spot (THIS->here_input ());
1573 Text_script_req *t = new Text_script_req;
1574 t->set_mus_property ("text", $1);
1575 t->set_spot (THIS->here_input ());
1579 String ds = to_str ($1);
1580 Text_script_req* t = new Text_script_req;
1581 SCM finger = ly_symbol2scm ("finger");
1582 t->set_mus_property ("text", ly_str02scm (ds.ch_C ()));
1583 t->set_mus_property ("text-type" , finger);
1584 t->set_spot (THIS->here_input ());
1589 script_abbreviation:
1591 $$ = gh_str02scm ("Hat");
1594 $$ = gh_str02scm ("Plus");
1597 $$ = gh_str02scm ("Dash");
1600 $$ = gh_str02scm ("Bar");
1603 $$ = gh_str02scm ("Larger");
1606 $$ = gh_str02scm ("Dot");
1613 | '-' { $$ = CENTER; }
1618 $$ = new Link_array<Request>;
1620 | pre_requests open_request {
1632 multiplied_duration {
1635 | verbose_duration {
1640 optional_notemode_duration:
1642 Duration dd = THIS->default_duration_;
1643 $$ = dd.smobbed_copy ();
1645 THIS->beam_check ($$);
1647 | multiplied_duration {
1649 THIS->default_duration_ = *unsmob_duration ($$);
1651 THIS->beam_check ($$);
1653 | verbose_duration {
1655 THIS->default_duration_ = *unsmob_duration ($$);
1660 bare_unsigned dots {
1662 if (!is_duration_b ($1))
1663 THIS->parser_error (_f ("not a duration: %d", $1));
1667 $$ = Duration (l, $2).smobbed_copy ();
1669 | DURATION_IDENTIFIER dots {
1670 Duration *d =unsmob_duration ($1);
1671 Duration k (d->duration_log (),d->dot_count () + $2);
1672 $$ = k.smobbed_copy ();
1679 multiplied_duration:
1683 | multiplied_duration '*' bare_unsigned {
1684 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1686 | multiplied_duration '*' FRACTION {
1687 Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr ($3)));
1689 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1694 FRACTION { $$ = $1; }
1695 | UNSIGNED '/' UNSIGNED {
1696 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1714 | ':' bare_unsigned {
1715 if (!is_duration_b ($2))
1716 THIS->parser_error (_f ("not a duration: %d", $2));
1735 Bass_figure_req *bfr = new Bass_figure_req;
1736 $$ = bfr->self_scm();
1737 scm_gc_unprotect_object ($$);
1740 Bass_figure_req *bfr = new Bass_figure_req;
1741 $$ = bfr->self_scm();
1743 bfr->set_mus_property ("figure", gh_int2scm ($1));
1745 scm_gc_unprotect_object ($$);
1747 | bass_figure bass_mod {
1748 Music *m = unsmob_music ($1);
1750 SCM salter =m->get_mus_property ("alteration");
1751 int alter = gh_number_p( salter) ? gh_scm2int (salter) : 0;
1752 m->set_mus_property ("alteration",
1753 gh_int2scm (alter + $2));
1755 m->set_mus_property ("alteration", gh_int2scm (0));
1763 unsmob_music ($$)->set_mus_property ("bracket-start", SCM_BOOL_T);
1768 | br_bass_figure ']' {
1770 unsmob_music ($1)->set_mus_property ("bracket-stop", SCM_BOOL_T);
1778 | figure_list br_bass_figure {
1779 $$ = gh_cons ($2, $1);
1784 FIGURE_OPEN figure_list FIGURE_CLOSE {
1785 Music * m = new Request_chord (SCM_EOL);
1786 $2 = scm_reverse_x ($2, SCM_EOL);
1787 m->set_mus_property ("elements", $2);
1788 $$ = m->self_scm ();
1799 pitch exclamations questions optional_notemode_duration optional_rest {
1801 Input i = THIS->pop_spot ();
1802 if (!THIS->lexer_p_->note_state_b ())
1803 THIS->parser_error (_ ("Have to be in Note mode for notes"));
1811 n->set_mus_property ("pitch", $1);
1812 n->set_mus_property ("duration", $4);
1816 n->set_mus_property ("cautionary", SCM_BOOL_T);
1817 if ($2 % 2 || $3 % 2)
1818 n->set_mus_property ("force-accidental", SCM_BOOL_T);
1820 Simultaneous_music*v = new Request_chord (SCM_EOL);
1821 v->set_mus_property ("elements", scm_list_n (n->self_scm (), SCM_UNDEFINED));
1827 | figure_spec optional_notemode_duration {
1828 Music * m = unsmob_music ($1);
1829 Input i = THIS->pop_spot ();
1831 for (SCM s = m->get_mus_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
1833 unsmob_music (ly_car (s))->set_mus_property ("duration", $2);
1837 | RESTNAME optional_notemode_duration {
1839 Input i = THIS->pop_spot ();
1840 SCM e = SCM_UNDEFINED;
1841 if (ly_scm2string ($1) =="s") {
1843 Skip_req * skip_p = new Skip_req;
1844 skip_p->set_mus_property ("duration" ,$2);
1845 skip_p->set_spot (i);
1846 e = skip_p->self_scm ();
1849 Rest_req * rest_req_p = new Rest_req;
1850 rest_req_p->set_mus_property ("duration", $2);
1851 rest_req_p->set_spot (i);
1852 e = rest_req_p->self_scm ();
1854 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1855 velt_p-> set_mus_property ("elements", scm_list_n (e,SCM_UNDEFINED));
1856 velt_p->set_spot (i);
1860 | MULTI_MEASURE_REST optional_notemode_duration {
1861 Input i = THIS->pop_spot ();
1863 Skip_req * sk = new Skip_req;
1864 sk->set_mus_property ("duration", $2);
1865 Span_req *sp1 = new Span_req;
1866 Span_req *sp2 = new Span_req;
1867 sp1-> set_span_dir ( START);
1868 sp2-> set_span_dir ( STOP);
1869 SCM r = ly_str02scm ("rest");
1870 sp1->set_mus_property ("span-type", r);
1871 sp2->set_mus_property ("span-type", r);
1873 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1874 rqc1->set_mus_property ("elements", scm_list_n (sp1->self_scm (), SCM_UNDEFINED));
1875 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1876 rqc2->set_mus_property ("elements", scm_list_n (sk->self_scm (), SCM_UNDEFINED));;
1877 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1878 rqc3->set_mus_property ("elements", scm_list_n (sp2->self_scm (), SCM_UNDEFINED));;
1880 SCM ms = scm_list_n (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1882 $$ = new Sequential_music (SCM_EOL);
1883 $$->set_mus_property ("elements", ms);
1885 | STRING optional_notemode_duration {
1886 Input i = THIS->pop_spot ();
1888 Lyric_req* lreq_p = new Lyric_req;
1889 lreq_p->set_mus_property ("text", $1);
1890 lreq_p->set_mus_property ("duration",$2);
1891 lreq_p->set_spot (i);
1892 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1893 velt_p->set_mus_property ("elements", scm_list_n (lreq_p->self_scm (), SCM_UNDEFINED));
1898 Input i = THIS->pop_spot ();
1900 if (!THIS->lexer_p_->chord_state_b ())
1901 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1908 steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1909 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1910 $$->set_spot (THIS->here_input ());
1917 | CHORD_COLON chord_notes {
1926 | chord_notes '.' chord_step {
1927 $$ = gh_append2 ($$, $3);
1935 | CHORD_CARET chord_notes {
1945 | '/' steno_tonic_pitch {
1954 | CHORD_BASS steno_tonic_pitch {
1961 $$ = gh_cons ($1, SCM_EOL);
1963 | CHORDMODIFIER_PITCH {
1964 $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
1966 | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1967 $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
1975 m.notename_i_ = ($1 - 1) % 7;
1976 m.octave_i_ = $1 > 7 ? 1 : 0;
1977 m.alteration_i_ = 0;
1979 $$ = m.smobbed_copy ();
1981 | bare_unsigned '+' {
1983 m.notename_i_ = ($1 - 1) % 7;
1984 m.octave_i_ = $1 > 7 ? 1 : 0;
1985 m.alteration_i_ = 1;
1988 $$ = m.smobbed_copy ();
1990 | bare_unsigned CHORD_MINUS {
1992 m.notename_i_ = ($1 - 1) % 7;
1993 m.octave_i_ = $1 > 7 ? 1 : 0;
1994 m.alteration_i_ = -1;
1996 $$ = m.smobbed_copy ();
2004 number_expression '+' number_term {
2005 $$ = scm_sum ($1, $3);
2007 | number_expression '-' number_term {
2008 $$ = scm_difference ($1, $3);
2017 | number_factor '*' number_factor {
2018 $$ = scm_product ($1, $3);
2020 | number_factor '/' number_factor {
2021 $$ = scm_divide ($1, $3);
2026 '(' number_expression ')' {
2029 | '-' number_factor { /* %prec UNARY_MINUS */
2030 $$ = scm_difference ($2, SCM_UNDEFINED);
2038 $$ = gh_int2scm ($1);
2043 | NUMBER_IDENTIFIER {
2047 $$ = gh_double2scm (gh_scm2double ($1) CM );
2050 $$ = gh_double2scm (gh_scm2double ($1) PT);
2053 $$ = gh_double2scm (gh_scm2double ($1) INCH);
2056 $$ = gh_double2scm (gh_scm2double ($1) MM);
2059 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
2075 if (scm_integer_p ($1) == SCM_BOOL_T)
2077 int k = gh_scm2int ($1);
2081 THIS->parser_error (_ ("need integer number arg"));
2095 | STRING_IDENTIFIER {
2098 | string '+' string {
2099 $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
2106 | exclamations '!' { $$ ++; }
2111 | questions '?' { $$ ++; }
2118 My_lily_parser::set_yydebug (bool b)
2125 extern My_lily_parser * current_parser;
2128 My_lily_parser::do_yyparse ()
2131 current_parser = this;;
2132 yyparse ((void*)this);
2137 Should make this optional? It will also complain when you do
2141 which is entirely legitimate.
2143 Or we can scrap it. Barchecks should detect wrong durations, and
2144 skipTypesetting speeds it up a lot.
2147 My_lily_parser::beam_check (SCM dur)
2149 Duration *d = unsmob_duration (dur);
2150 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2152 Music * m = unsmob_music (last_beam_start_);
2153 m->origin ()->warning (_("Suspect duration found following this beam"));
2155 last_beam_start_ = SCM_EOL;