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 ()
120 #define YYERROR_VERBOSE 1
122 #define YYPARSE_PARAM my_lily_parser_l
123 #define YYLEX_PARAM my_lily_parser_l
125 ((My_lily_parser *) my_lily_parser_l)
127 #define yyerror THIS->parser_error
128 #define ARRAY_SIZE(a,s) if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
132 /* We use SCMs to do strings, because it saves us the trouble of
133 deleting them. Let's hope that a stack overflow doesnt trigger a move
134 of the parse stack onto the heap. */
139 Link_array<Request> *reqvec;
141 String *string; // needed by the lexer as temporary scratch area.
144 Scheme_hash_table *scmhash;
145 Music_output_def * outputdef;
157 yylex (YYSTYPE *s, void * v_l)
159 My_lily_parser *pars_l = (My_lily_parser*) v_l;
160 My_lily_lexer * lex_l = pars_l->lexer_p_;
162 lex_l->lexval_l = (void*) s;
163 return lex_l->yylex ();
171 /* tokens which are not keywords */
181 %token CHORDMODIFIERS
189 %token GROBDESCRIPTIONS
195 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
196 %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
206 %token MULTI_MEASURE_REST
218 %token OVERRIDE SET REVERT
231 %token COMMANDSPANREQUEST
233 %token OUTPUTPROPERTY
244 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
245 %token E_LEFTSQUARE E_RIGHTSQUARE E_TILDE
247 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
251 %type <i> exclamations questions dots optional_rest
252 %type <i> bass_number bass_mod
253 %type <scm> br_bass_figure bass_figure figure_list figure_spec
255 %token <scm> NOTENAME_PITCH
256 %token <scm> TONICNAME_PITCH
257 %token <scm> CHORDMODIFIER_PITCH
258 %token <scm> DURATION_IDENTIFIER
259 %token <scm> FRACTION
260 %token <id> IDENTIFIER
263 %token <scm> SCORE_IDENTIFIER
264 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
266 %token <scm> NUMBER_IDENTIFIER
267 %token <scm> REQUEST_IDENTIFIER
268 %token <scm> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
269 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
270 %token <scm> RESTNAME
276 %type <outputdef> output_def
277 %type <scmhash> lilypond_header lilypond_header_body
278 %type <request> open_request_parens close_request_parens open_request close_request
279 %type <request> request_with_dir request_that_take_dir verbose_request
280 %type <i> sub_quotes sup_quotes
281 %type <music> simple_element request_chord command_element Simple_music Composite_music
282 %type <music> Repeated_music
283 %type <scm> Alternative_music
284 %type <i> tremolo_type
285 %type <i> bare_int bare_unsigned
288 %type <scm> identifier_init
290 %type <scm> steno_duration optional_notemode_duration multiplied_duration
291 %type <scm> verbose_duration
293 %type <reqvec> pre_requests post_requests
294 %type <request> gen_text_def
295 %type <scm> steno_pitch pitch absolute_pitch
296 %type <scm> explicit_pitch steno_tonic_pitch
298 %type <scm> chord_additions chord_subtractions chord_notes chord_step
300 %type <scm> chord_note chord_inversion chord_bass
301 %type <scm> duration_length fraction
303 %type <scm> embedded_scm scalar
304 %type <music> Music Sequential_music Simultaneous_music
305 %type <music> relative_music re_rhythmed_music part_combined_music
306 %type <music> property_def translator_change
307 %type <scm> Music_list
308 %type <outputdef> music_output_def_body
309 %type <request> shorthand_command_req
310 %type <request> post_request
311 %type <music> command_req verbose_command_req
312 %type <request> extender_req
313 %type <request> hyphen_req
314 %type <scm> string bare_number number_expression number_term number_factor
316 %type <score> score_block score_body
318 %type <scm> translator_spec_block translator_spec_body
319 %type <tempo> tempo_request
320 %type <scm> notenames_body notenames_block chordmodifiers_block
321 %type <scm> script_abbreviation
327 /* We don't assign precedence to / and *, because we might need varied
328 prec levels in different prods */
334 lilypond: /* empty */
335 | lilypond toplevel_expression {}
336 | lilypond assignment { }
338 THIS->error_level_i_ = 1;
341 THIS->error_level_i_ = 1;
347 THIS->lexer_p_->pitchname_tab_ = $1;
349 | chordmodifiers_block {
350 THIS->lexer_p_->chordmodifier_tab_ = $1;
354 scm_gc_unprotect_object (global_header_p->self_scm ());
355 global_header_p = $1;
358 score_global_array.push ($1);
361 if (dynamic_cast<Paper_def*> ($1))
362 THIS->lexer_p_->set_identifier (gh_str02scm ("$defaultpaper"), $1->self_scm ());
363 else if (dynamic_cast<Midi_def*> ($1))
364 THIS->lexer_p_->set_identifier (gh_str02scm ("$defaultmidi"), $1->self_scm ());
377 chordmodifiers_block:
378 CHORDMODIFIERS notenames_body { $$ = $2; }
382 PITCHNAMES notenames_body { $$ = $2; }
387 int i = scm_ilength ($1);
389 SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
390 for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) {
391 SCM pt = ly_cdar (s);
392 if (!unsmob_pitch (pt))
393 THIS->parser_error ("Need pitch object.");
395 scm_hashq_set_x (tab, ly_caar (s), pt);
402 lilypond_header_body:
404 $$ = new Scheme_hash_table;
405 THIS->lexer_p_-> scope_l_arr_.push ($$);
407 | lilypond_header_body assignment {
413 HEADER '{' lilypond_header_body '}' {
415 THIS->lexer_p_->scope_l_arr_.pop ();
427 /* cont */ '=' identifier_init {
430 Should find generic way of associating input with objects.
432 Input ip = THIS->pop_spot ();
434 if (! regular_identifier_b ($1))
436 ip.warning (_ ("Identifier should have alphabetic characters only"));
439 THIS->lexer_p_->set_identifier ($1, $4);
442 TODO: devise standard for protection in parser.
444 The parser stack lives on the C-stack, which means that
445 all objects can be unprotected as soon as they're here.
455 $$ = $1->self_scm ();
456 scm_gc_unprotect_object ($$);
459 $$ = $1->self_scm ();
460 scm_gc_unprotect_object ($$);
462 | translator_spec_block {
466 $$ = $1->self_scm ();
467 scm_gc_unprotect_object ($$);
470 $$ = $1->self_scm ();
471 scm_gc_unprotect_object ($$);
476 | number_expression {
487 translator_spec_block:
488 TRANSLATOR '{' translator_spec_body '}'
494 translator_spec_body:
495 TRANSLATOR_IDENTIFIER {
496 $$ = unsmob_translator_def ($1)->clone_scm ();
497 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
500 $$ = Translator_def::make_scm ();
501 Translator_def*td = unsmob_translator_def ($$);
502 td->translator_group_type_ = $2;
503 td->set_spot (THIS->here_input ());
505 | translator_spec_body STRING '=' embedded_scm {
506 unsmob_translator_def ($$)->add_property_assign ($2, $4);
508 | translator_spec_body STRING OVERRIDE embedded_scm '=' embedded_scm {
509 unsmob_translator_def ($$)
510 ->add_push_property (scm_string_to_symbol ($2), $4, $6);
512 | translator_spec_body STRING REVERT embedded_scm {
513 unsmob_translator_def ($$)->add_pop_property (
514 scm_string_to_symbol ($2), $4);
516 | translator_spec_body NAME STRING {
517 unsmob_translator_def ($$)->type_name_ = $3;
519 | translator_spec_body CONSISTS STRING {
520 unsmob_translator_def ($$)->add_element ($3);
522 | translator_spec_body ALIAS STRING {
523 Translator_def*td = unsmob_translator_def ($$);
524 td->type_aliases_ = gh_cons ($3, td->type_aliases_);
526 | translator_spec_body GROBDESCRIPTIONS embedded_scm {
527 Translator_def*td = unsmob_translator_def($$);
528 // td->add_property_assign (ly_symbol2scm ("allGrobDescriptions"), $3);
529 for (SCM p = $3; gh_pair_p (p); p = ly_cdr (p))
530 td->add_property_assign (scm_symbol_to_string (ly_caar (p)), ly_cdar (p));
532 | translator_spec_body CONSISTSEND STRING {
533 unsmob_translator_def ($$)->add_last_element ( $3);
535 | translator_spec_body ACCEPTS STRING {
536 unsmob_translator_def ($$)->set_acceptor ($3,true);
538 | translator_spec_body DENIES STRING {
539 unsmob_translator_def ($$)->set_acceptor ($3,false);
541 | translator_spec_body REMOVE STRING {
542 unsmob_translator_def ($$)->remove_element ($3);
553 /*cont*/ '{' score_body '}' {
556 if (!$$->def_p_arr_.size ())
558 Music_output_def *id =
559 unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
560 $$->add_output (id ? id->clone () : new Paper_def );
569 $$->set_spot (THIS->here_input ());
570 SCM m = $1->self_scm ();
571 scm_gc_unprotect_object (m);
575 $$ = new Score (*unsmob_score ($1));
576 $$->set_spot (THIS->here_input ());
578 | score_body lilypond_header {
579 scm_gc_unprotect_object ($2->self_scm ());
582 | score_body output_def {
595 music_output_def_body '}' {
597 THIS-> lexer_p_-> scope_l_arr_.pop ();
601 music_output_def_body:
603 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
608 p = dynamic_cast<Midi_def*> (id->clone ());
613 THIS->lexer_p_->scope_l_arr_.push (p->variable_tab_);
616 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
619 p = dynamic_cast<Paper_def*> (id->clone ());
622 THIS-> lexer_p_-> scope_l_arr_.push (p->variable_tab_);
625 | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
626 Music_output_def *p = unsmob_music_output_def ($3);
628 THIS->lexer_p_->scope_l_arr_.push (p->variable_tab_);
631 | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
632 Music_output_def *p = unsmob_music_output_def ($3);
635 THIS->lexer_p_->scope_l_arr_.push (p->variable_tab_);
638 | music_output_def_body assignment {
641 | music_output_def_body translator_spec_block {
642 $$->assign_translator ($2);
644 | music_output_def_body STYLESHEET embedded_scm {
645 dynamic_cast<Paper_def*> ($$)-> style_sheet_ = $3;
647 | music_output_def_body tempo_request {
649 junk this ? there already is tempo stuff in
652 int m = gh_scm2int ( $2->get_mus_property ("metronome-count"));
653 Duration *d = unsmob_duration ($2->get_mus_property ("duration"));
654 dynamic_cast<Midi_def*> ($$)->set_tempo (d->length_mom (), m);
656 | music_output_def_body error {
662 TEMPO steno_duration '=' bare_unsigned {
664 $$->set_mus_property ("duration", $2);
665 $$->set_mus_property ("metronome-count", gh_int2scm ( $4));
670 The representation of a list is the
674 to have efficient append.
676 Music_list: /* empty */ {
677 $$ = gh_cons (SCM_EOL, SCM_EOL);
681 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
682 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
683 if (gh_pair_p (ly_cdr (s)))
684 gh_set_cdr_x (ly_cdr (s), c); /* append */
686 gh_set_car_x (s, c); /* set first cons */
687 gh_set_cdr_x (s, c) ; /* remember last cell */
703 | ALTERNATIVE '{' Music_list '}' {
709 REPEAT string bare_unsigned Music Alternative_music
713 SCM alts = gh_pair_p ($5) ? gh_car ($5) : SCM_EOL;
714 if (times < scm_ilength (alts)) {
715 unsmob_music (gh_car (alts))
716 ->origin ()->warning (
717 _("More alternatives than repeats. Junking excess alternatives."));
718 alts = ly_truncate_list (times, alts);
721 Repeated_music * r = new Repeated_music (SCM_EOL);
724 r-> set_mus_property ("element", beg->self_scm ());
725 scm_gc_unprotect_object (beg->self_scm ());
727 r->set_mus_property ("repeat-count", gh_int2scm (times >? 1));
729 r-> set_mus_property ("elements",alts);
730 SCM func = scm_primitive_eval (ly_symbol2scm ("repeat-name-to-ctor"));
731 SCM result = gh_call1 (func, $2);
733 set_music_properties (r, result);
735 r->set_spot (*$4->origin ());
741 SEQUENTIAL '{' Music_list '}' {
742 $$ = new Sequential_music (SCM_EOL);
743 $$->set_mus_property ("elements", ly_car ($3));
745 | '{' Music_list '}' {
746 $$ = new Sequential_music (SCM_EOL);
747 $$->set_mus_property ("elements", ly_car ($2));
752 SIMULTANEOUS '{' Music_list '}'{
753 $$ = new Simultaneous_music (SCM_EOL);
754 $$->set_mus_property ("elements", ly_car ($3));
757 | '<' Music_list '>' {
758 $$ = new Simultaneous_music (SCM_EOL);
759 $$->set_mus_property ("elements", ly_car ($2));
764 request_chord { $$ = $1; }
765 | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm {
767 if (!gh_symbol_p ($3))
769 THIS->parser_error (_ ("Second argument must be a symbol"));
771 /*hould check # args */
772 if (!gh_procedure_p (pred))
774 THIS->parser_error (_ ("First argument must be a procedure taking 1 argument"));
777 Music *m = new Music (SCM_EOL);
778 m->set_mus_property ("predicate", pred);
779 m->set_mus_property ("grob-property", $3);
780 m->set_mus_property ("grob-value", $5);
781 m->set_mus_property ("iterator-ctor",
782 Output_property_music_iterator::constructor_cxx_function);
787 $$ = unsmob_music ($1)->clone ();
789 $$->set_spot (THIS->here_input());
797 CONTEXT STRING Music {
798 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
799 csm->set_mus_property ("element", $3->self_scm ());
800 scm_gc_unprotect_object ($3->self_scm ());
802 csm->set_mus_property ("context-type",$2);
803 csm->set_mus_property ("context-id", ly_str02scm (""));
807 | AUTOCHANGE STRING Music {
808 Music * chm = new Music_wrapper (SCM_EOL);
809 chm->set_mus_property ("element", $3->self_scm ());
810 chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_cxx_function);
812 scm_gc_unprotect_object ($3->self_scm ());
813 chm->set_mus_property ("what", $2);
816 chm->set_spot (*$3->origin ());
821 The other version is for easier debugging of
822 Sequential_music_iterator in combination with grace notes.
825 SCM start = THIS->lexer_p_->lookup_identifier ("startGraceMusic");
826 SCM stop = THIS->lexer_p_->lookup_identifier ("stopGraceMusic");
827 Music *startm = unsmob_music (start);
828 Music *stopm = unsmob_music (stop);
832 stopm = stopm->clone ();
833 ms = gh_cons (stopm->self_scm (), ms);
834 scm_gc_unprotect_object (stopm->self_scm ());
836 ms = gh_cons ($2->self_scm (), ms);
837 scm_gc_unprotect_object ($2->self_scm());
839 startm = startm->clone ();
840 ms = gh_cons (startm->self_scm () , ms);
841 scm_gc_unprotect_object (startm->self_scm ());
844 Music* seq = new Sequential_music (SCM_EOL);
845 seq->set_mus_property ("elements", ms);
847 $$ = new Grace_music (SCM_EOL);
848 $$->set_mus_property ("element", seq->self_scm ());
849 scm_gc_unprotect_object (seq->self_scm ());
851 $$ = new Grace_music (SCM_EOL);
852 $$->set_mus_property ("element", $2->self_scm ());
853 scm_gc_unprotect_object ($2->self_scm ());
856 | CONTEXT string '=' string Music {
857 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
858 csm->set_mus_property ("element", $5->self_scm ());
859 scm_gc_unprotect_object ($5->self_scm ());
861 csm->set_mus_property ("context-type", $2);
862 csm->set_mus_property ("context-id", $4);
873 int n = gh_scm2int (ly_car ($3)); int d = gh_scm2int (ly_cdr ($3));
875 $$ = new Time_scaled_music (SCM_EOL);
876 $$->set_spot (THIS->pop_spot ());
879 $$->set_mus_property ("element", mp->self_scm ());
880 scm_gc_unprotect_object (mp->self_scm ());
881 $$->set_mus_property ("numerator", gh_int2scm (n));
882 $$->set_mus_property ("denominator", gh_int2scm (d));
883 $$->compress (Moment (Rational (n,d)));
886 | Repeated_music { $$ = $1; }
887 | Simultaneous_music { $$ = $1; }
888 | Sequential_music { $$ = $1; }
889 | TRANSPOSE pitch Music {
890 $$ = new Transposed_music (SCM_EOL);
892 Pitch pit = *unsmob_pitch ($2);
895 $$->set_mus_property ("element", p->self_scm ());
896 scm_gc_unprotect_object (p->self_scm ());
898 | TRANSPOSE steno_tonic_pitch Music {
899 $$ = new Transposed_music (SCM_EOL);
901 Pitch pit = *unsmob_pitch ($2);
904 $$->set_mus_property ("element", p->self_scm ());
905 scm_gc_unprotect_object (p->self_scm ());
908 | APPLY embedded_scm Music {
909 SCM ret = gh_call1 ($2, $3->self_scm ());
910 Music *m = unsmob_music (ret);
912 THIS->parser_error ("\\apply must return a Music");
913 m = new Music (SCM_EOL);
918 { THIS->lexer_p_->push_note_state (); }
921 THIS->lexer_p_->pop_state ();
924 { THIS->lexer_p_->push_figuredbass_state (); }
927 Music * chm = new Untransposable_music () ;
928 chm->set_mus_property ("element", $3->self_scm ());
931 THIS->lexer_p_->pop_state ();
934 { THIS->lexer_p_->push_chord_state (); }
937 Music * chm = new Un_relativable_music ;
938 chm->set_mus_property ("element", $3->self_scm ());
941 THIS->lexer_p_->pop_state ();
944 { THIS->lexer_p_->push_lyric_state (); }
948 THIS->lexer_p_->pop_state ();
950 | relative_music { $$ = $1; }
951 | re_rhythmed_music { $$ = $1; }
952 | part_combined_music { $$ = $1; }
956 RELATIVE absolute_pitch Music {
958 Pitch pit = *unsmob_pitch ($2);
959 $$ = new Relative_octave_music (SCM_EOL);
961 $$->set_mus_property ("element", p->self_scm ());
962 scm_gc_unprotect_object (p->self_scm ());
964 $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ());
970 ADDLYRICS Music Music {
971 Lyric_combine_music * l = new Lyric_combine_music (SCM_EOL);
972 l->set_mus_property ("elements", gh_list ($2->self_scm (), $3->self_scm (), SCM_UNDEFINED));
973 scm_gc_unprotect_object ($3->self_scm ());
974 scm_gc_unprotect_object ($2->self_scm ());
980 PARTCOMBINE STRING Music Music {
981 Part_combine_music * p = new Part_combine_music (SCM_EOL);
983 p->set_mus_property ("what", $2);
984 p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED));
986 scm_gc_unprotect_object ($3->self_scm ());
987 scm_gc_unprotect_object ($4->self_scm ());
994 TRANSLATOR STRING '=' STRING {
995 Music * t = new Music (SCM_EOL);
996 t->set_mus_property ("iterator-ctor",
997 Change_iterator::constructor_cxx_function);
998 t-> set_mus_property ("change-to-type", $2);
999 t-> set_mus_property ("change-to-id", $4);
1002 $$->set_spot (THIS->here_input ());
1007 PROPERTY STRING '.' STRING '=' scalar {
1009 Music *t = set_property_music (scm_string_to_symbol ($4), $6);
1010 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1012 csm->set_mus_property ("element", t->self_scm ());
1013 scm_gc_unprotect_object (t->self_scm ());
1016 $$->set_spot (THIS->here_input ());
1018 csm-> set_mus_property ("context-type", $2);
1020 | PROPERTY STRING '.' STRING UNSET {
1021 Music *t = new Music (SCM_EOL);
1023 t->set_mus_property ("iterator-ctor",
1024 Property_unset_iterator::constructor_cxx_function);
1025 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1027 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1028 csm->set_mus_property ("element", t->self_scm ());
1029 scm_gc_unprotect_object (t->self_scm ());
1032 $$->set_spot (THIS->here_input ());
1034 csm-> set_mus_property ("context-type", $2);
1036 | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm {
1037 Music *t = new Music (SCM_EOL);
1038 t->set_mus_property ("iterator-ctor",
1039 Push_property_iterator::constructor_cxx_function);
1040 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1041 t->set_mus_property ("pop-first", SCM_BOOL_T);
1042 t->set_mus_property ("grob-property", $6);
1043 t->set_mus_property ("grob-value", $8);
1044 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1045 csm->set_mus_property ("element", t->self_scm ());
1046 scm_gc_unprotect_object (t->self_scm ());
1048 $$->set_spot (THIS->here_input ());
1050 csm-> set_mus_property ("context-type", $2);
1052 | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
1053 Music *t = new Music (SCM_EOL);
1054 t->set_mus_property ("iterator-ctor",
1055 Push_property_iterator::constructor_cxx_function);
1056 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1057 t->set_mus_property ("grob-property", $6);
1058 t->set_mus_property ("grob-value", $8);
1059 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1060 csm->set_mus_property ("element", t->self_scm ());
1061 scm_gc_unprotect_object (t->self_scm ());
1064 $$->set_spot (THIS->here_input ());
1066 csm-> set_mus_property ("context-type", $2);
1068 | PROPERTY STRING '.' STRING REVERT embedded_scm {
1069 Music *t = new Music (SCM_EOL);
1070 t->set_mus_property ("iterator-ctor",
1071 Pop_property_iterator::constructor_cxx_function);
1072 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1073 t->set_mus_property ("grob-property", $6);
1075 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1076 csm->set_mus_property ("element", t->self_scm ());
1077 scm_gc_unprotect_object (t->self_scm ());
1080 $$->set_spot (THIS->here_input ());
1082 csm-> set_mus_property ("context-type", $2);
1088 | bare_int { $$ = gh_int2scm ($1); }
1089 | embedded_scm { $$ = $1; }
1096 } /*cont */ simple_element post_requests {
1097 Music_sequence *l = dynamic_cast<Music_sequence*> ($3);
1100 for (int i=0; i < $1->size (); i++) {
1101 Music * m = $1->elem (i);
1102 l->append_music (m);
1114 $$ = new Request_chord (SCM_EOL);
1115 $$->set_mus_property ("elements", gh_cons ($1->self_scm (), SCM_EOL));
1116 $$-> set_spot (THIS->here_input ());
1117 $1-> set_spot (THIS->here_input ());
1120 $$ = new Music (gh_list (gh_cons (ly_symbol2scm ("name"), ly_symbol2scm ("separator")), SCM_UNDEFINED));
1121 $$->set_spot (THIS->here_input ());
1125 extern Music * get_barcheck();
1126 $$ = get_barcheck ();
1127 $$->set_spot (THIS->here_input ());
1130 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1132 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1133 csm->set_mus_property ("element", t->self_scm ());
1134 scm_gc_unprotect_object (t->self_scm ());
1137 $$->set_spot (THIS->here_input ());
1139 csm->set_mus_property ("context-type", ly_str02scm ("Score"));
1141 | PARTIAL duration_length {
1142 Moment m = - unsmob_duration ($2)->length_mom ();
1143 Music * p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1145 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1146 sp->set_mus_property ("element", p->self_scm ());
1147 scm_gc_unprotect_object (p->self_scm ());
1150 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1153 SCM func = scm_primitive_eval (ly_symbol2scm ("clef-name-to-properties"));
1154 SCM result = gh_call1 (func, $2);
1157 for (SCM s = result ; gh_pair_p (s); s = ly_cdr (s)) {
1158 Music * p = new Music (SCM_EOL);
1159 set_music_properties (p, ly_car (s));
1160 l = gh_cons (p->self_scm (), l);
1161 scm_gc_unprotect_object (p->self_scm ());
1163 Sequential_music * seq = new Sequential_music (SCM_EOL);
1164 seq->set_mus_property ("elements", l);
1166 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1167 sp->set_mus_property ("element", seq->self_scm ());
1168 scm_gc_unprotect_object (seq->self_scm ());
1171 sp-> set_mus_property ("context-type", ly_str02scm ("Staff"));
1174 Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2);
1176 int l = gh_scm2int (ly_car ($2));
1177 int o = gh_scm2int (ly_cdr ($2));
1179 Moment one_beat = Moment (1)/Moment (o);
1180 Moment len = Moment (l) * one_beat;
1183 Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ());
1184 Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ());
1186 SCM list = scm_list_n (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED);
1187 Sequential_music *seq = new Sequential_music (SCM_EOL);
1188 seq->set_mus_property ("elements", list);
1191 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1192 sp->set_mus_property ("element", seq->self_scm ());
1196 scm_gc_unprotect_object (p3->self_scm ());
1197 scm_gc_unprotect_object (p2->self_scm ());
1198 scm_gc_unprotect_object (p1->self_scm ());
1199 scm_gc_unprotect_object (seq->self_scm ());
1204 TODO: should make alias TimingContext for Score
1207 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1212 shorthand_command_req { $$ = $1; }
1213 | verbose_command_req { $$ = $1; }
1216 shorthand_command_req:
1227 Span_req*b= new Span_req;
1228 b->set_span_dir (START);
1229 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1233 THIS->last_beam_start_ = b->self_scm ();
1236 Span_req*b= new Span_req;
1237 b->set_span_dir ( STOP);
1238 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1242 Span_req *b = new Span_req;
1243 b->set_span_dir (START);
1244 b->set_mus_property ("span-type", ly_str02scm ("ligature-bracket"));
1246 THIS->last_ligature_start_ = b->self_scm ();
1249 Span_req *b = new Span_req;
1250 b->set_span_dir (STOP);
1251 b->set_mus_property ("span-type", ly_str02scm ("ligature-bracket"));
1255 $$ = new Breathing_sign_req;
1258 $$ = new Porrectus_req;
1262 verbose_command_req:
1263 COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1264 Span_req * sp_p = new Span_req;
1265 sp_p-> set_span_dir ( Direction ($2));
1266 sp_p->set_mus_property ("span-type",$3);
1267 sp_p->set_spot (THIS->here_input ());
1271 Mark_req * m = new Mark_req;
1275 Mark_req *m = new Mark_req;
1276 m->set_mus_property ("label", $2);
1281 Break_req * b = new Break_req;
1283 if (!gh_number_p (s))
1286 b->set_mus_property ("penalty", s);
1287 b->set_spot (THIS->here_input ());
1290 | SKIP duration_length {
1291 Skip_req * skip_p = new Skip_req;
1292 skip_p->set_mus_property ("duration", $2);
1300 Key_change_req *key_p= new Key_change_req;
1303 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1304 Key_change_req *key_p= new Key_change_req;
1306 key_p->set_mus_property ("pitch-alist", $3);
1307 ((Music*)key_p)->transpose (* unsmob_pitch ($2));
1314 $$ = new Link_array<Request>;
1316 | post_requests post_request {
1317 $2->set_spot (THIS->here_input ());
1329 request_that_take_dir:
1332 | script_abbreviation {
1333 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1334 Articulation_req *a = new Articulation_req;
1335 if (gh_string_p (s))
1336 a->set_mus_property ("articulation-type", s);
1337 else THIS->parser_error (_ ("Expecting string as script definition"));
1343 script_dir request_that_take_dir {
1344 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1345 gs->set_direction (Direction ($1));
1347 $2->origin ()->warning (_ ("Can't specify direction for this request"));
1353 REQUEST_IDENTIFIER {
1354 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1355 $$->set_spot (THIS->here_input ());
1357 | DYNAMICSCRIPT embedded_scm {
1359 TODO: junkme, use text-type == dynamic
1361 Text_script_req *d = new Text_script_req;
1362 SCM dyn = ly_symbol2scm ("dynamic");
1363 d->set_mus_property ("text-type" , dyn);
1364 d->set_mus_property ("text", $2);
1365 d->set_spot (THIS->here_input ());
1368 | SPANREQUEST bare_int STRING {
1369 Span_req * sp_p = new Span_req;
1370 sp_p->set_span_dir ( Direction ($2));
1371 sp_p->set_mus_property ("span-type", $3);
1372 sp_p->set_spot (THIS->here_input ());
1376 Tremolo_req* a = new Tremolo_req;
1377 a->set_spot (THIS->here_input ());
1378 a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1382 Articulation_req * a = new Articulation_req;
1383 a->set_mus_property ("articulation-type", $2);
1384 a->set_spot (THIS->here_input ());
1388 duh, junk this syntax from the parser, if possible.
1391 Arpeggio_req *a = new Arpeggio_req;
1392 a->set_spot (THIS->here_input ());
1396 Glissando_req *g = new Glissando_req;
1397 g->set_spot /* No pun intended */ (THIS->here_input ());
1424 | NOTENAME_PITCH sup_quotes {
1425 Pitch p = *unsmob_pitch ($1);
1427 $$ = p.smobbed_copy ();
1429 | NOTENAME_PITCH sub_quotes {
1430 Pitch p =* unsmob_pitch ($1);
1433 $$ = p.smobbed_copy ();
1446 | TONICNAME_PITCH sup_quotes {
1447 Pitch p = *unsmob_pitch ($1);
1449 $$ = p.smobbed_copy ();
1451 | TONICNAME_PITCH sub_quotes {
1452 Pitch p =* unsmob_pitch ($1);
1455 $$ = p.smobbed_copy ();
1470 PITCH embedded_scm {
1472 if (!unsmob_pitch ($2)) {
1473 THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1474 $$ = Pitch ().smobbed_copy ();
1480 DURATION embedded_scm {
1482 if (!unsmob_duration ($2))
1484 THIS->parser_error (_ ("Must have duration object"));
1485 $$ = Duration ().smobbed_copy ();
1492 if (!THIS->lexer_p_->lyric_state_b ())
1493 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1494 $$ = new Extender_req;
1500 if (!THIS->lexer_p_->lyric_state_b ())
1501 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1502 $$ = new Hyphen_req;
1507 close_request_parens {
1509 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1513 close_request_parens:
1515 Span_req* s= new Span_req;
1517 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1520 Span_req* s= new Span_req;
1522 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1525 Span_req*s =new Span_req;
1527 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1530 Span_req*s =new Span_req;
1532 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1538 open_request_parens {
1540 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1544 open_request_parens:
1546 Span_req *s = new Span_req;
1547 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1552 Span_req* s= new Span_req;
1554 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1557 Span_req* s= new Span_req;
1559 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1565 Text_script_req *t = new Text_script_req;
1566 t->set_mus_property ("text", $1);
1567 t->set_spot (THIS->here_input ());
1571 Text_script_req *t = new Text_script_req;
1572 t->set_mus_property ("text", $1);
1573 t->set_spot (THIS->here_input ());
1577 String ds = to_str ($1);
1578 Text_script_req* t = new Text_script_req;
1579 SCM finger = ly_symbol2scm ("finger");
1580 t->set_mus_property ("text", ly_str02scm (ds.ch_C ()));
1581 t->set_mus_property ("text-type" , finger);
1582 t->set_spot (THIS->here_input ());
1587 script_abbreviation:
1589 $$ = gh_str02scm ("Hat");
1592 $$ = gh_str02scm ("Plus");
1595 $$ = gh_str02scm ("Dash");
1598 $$ = gh_str02scm ("Bar");
1601 $$ = gh_str02scm ("Larger");
1604 $$ = gh_str02scm ("Dot");
1611 | '-' { $$ = CENTER; }
1616 $$ = new Link_array<Request>;
1618 | pre_requests open_request {
1630 multiplied_duration {
1633 | verbose_duration {
1638 optional_notemode_duration:
1640 Duration dd = THIS->default_duration_;
1641 $$ = dd.smobbed_copy ();
1643 THIS->beam_check ($$);
1645 | multiplied_duration {
1647 THIS->default_duration_ = *unsmob_duration ($$);
1649 THIS->beam_check ($$);
1651 | verbose_duration {
1653 THIS->default_duration_ = *unsmob_duration ($$);
1658 bare_unsigned dots {
1660 if (!is_duration_b ($1))
1661 THIS->parser_error (_f ("not a duration: %d", $1));
1665 $$ = Duration (l, $2).smobbed_copy ();
1667 | DURATION_IDENTIFIER dots {
1668 Duration *d =unsmob_duration ($1);
1669 Duration k (d->duration_log (),d->dot_count () + $2);
1670 $$ = k.smobbed_copy ();
1677 multiplied_duration:
1681 | multiplied_duration '*' bare_unsigned {
1682 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1684 | multiplied_duration '*' FRACTION {
1685 Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr ($3)));
1687 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1692 FRACTION { $$ = $1; }
1693 | UNSIGNED '/' UNSIGNED {
1694 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1712 | ':' bare_unsigned {
1713 if (!is_duration_b ($2))
1714 THIS->parser_error (_f ("not a duration: %d", $2));
1733 Bass_figure_req *bfr = new Bass_figure_req;
1734 $$ = bfr->self_scm();
1735 scm_gc_unprotect_object ($$);
1738 Bass_figure_req *bfr = new Bass_figure_req;
1739 $$ = bfr->self_scm();
1741 bfr->set_mus_property ("figure", gh_int2scm ($1));
1743 scm_gc_unprotect_object ($$);
1745 | bass_figure bass_mod {
1746 Music *m = unsmob_music ($1);
1748 SCM salter =m->get_mus_property ("alteration");
1749 int alter = gh_number_p( salter) ? gh_scm2int (salter) : 0;
1750 m->set_mus_property ("alteration",
1751 gh_int2scm (alter + $2));
1753 m->set_mus_property ("alteration", gh_int2scm (0));
1761 unsmob_music ($$)->set_mus_property ("bracket-start", SCM_BOOL_T);
1766 | br_bass_figure ']' {
1768 unsmob_music ($1)->set_mus_property ("bracket-stop", SCM_BOOL_T);
1776 | figure_list br_bass_figure {
1777 $$ = gh_cons ($2, $1);
1782 FIGURE_OPEN figure_list FIGURE_CLOSE {
1783 Music * m = new Request_chord (SCM_EOL);
1784 $2 = scm_reverse_x ($2, SCM_EOL);
1785 m->set_mus_property ("elements", $2);
1786 $$ = m->self_scm ();
1797 pitch exclamations questions optional_notemode_duration optional_rest {
1799 Input i = THIS->pop_spot ();
1800 if (!THIS->lexer_p_->note_state_b ())
1801 THIS->parser_error (_ ("Have to be in Note mode for notes"));
1809 n->set_mus_property ("pitch", $1);
1810 n->set_mus_property ("duration", $4);
1814 n->set_mus_property ("cautionary", SCM_BOOL_T);
1815 if ($2 % 2 || $3 % 2)
1816 n->set_mus_property ("force-accidental", SCM_BOOL_T);
1818 Simultaneous_music*v = new Request_chord (SCM_EOL);
1819 v->set_mus_property ("elements", scm_list_n (n->self_scm (), SCM_UNDEFINED));
1825 | figure_spec optional_notemode_duration {
1826 Music * m = unsmob_music ($1);
1827 Input i = THIS->pop_spot ();
1829 for (SCM s = m->get_mus_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
1831 unsmob_music (ly_car (s))->set_mus_property ("duration", $2);
1835 | RESTNAME optional_notemode_duration {
1837 Input i = THIS->pop_spot ();
1838 SCM e = SCM_UNDEFINED;
1839 if (ly_scm2string ($1) =="s") {
1841 Skip_req * skip_p = new Skip_req;
1842 skip_p->set_mus_property ("duration" ,$2);
1843 skip_p->set_spot (i);
1844 e = skip_p->self_scm ();
1847 Rest_req * rest_req_p = new Rest_req;
1848 rest_req_p->set_mus_property ("duration", $2);
1849 rest_req_p->set_spot (i);
1850 e = rest_req_p->self_scm ();
1852 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1853 velt_p-> set_mus_property ("elements", scm_list_n (e,SCM_UNDEFINED));
1854 velt_p->set_spot (i);
1858 | MULTI_MEASURE_REST optional_notemode_duration {
1859 Input i = THIS->pop_spot ();
1861 Skip_req * sk = new Skip_req;
1862 sk->set_mus_property ("duration", $2);
1863 Span_req *sp1 = new Span_req;
1864 Span_req *sp2 = new Span_req;
1865 sp1-> set_span_dir ( START);
1866 sp2-> set_span_dir ( STOP);
1867 SCM r = ly_str02scm ("rest");
1868 sp1->set_mus_property ("span-type", r);
1869 sp2->set_mus_property ("span-type", r);
1871 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1872 rqc1->set_mus_property ("elements", scm_list_n (sp1->self_scm (), SCM_UNDEFINED));
1873 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1874 rqc2->set_mus_property ("elements", scm_list_n (sk->self_scm (), SCM_UNDEFINED));;
1875 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1876 rqc3->set_mus_property ("elements", scm_list_n (sp2->self_scm (), SCM_UNDEFINED));;
1878 SCM ms = scm_list_n (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1880 $$ = new Sequential_music (SCM_EOL);
1881 $$->set_mus_property ("elements", ms);
1883 | STRING optional_notemode_duration {
1884 Input i = THIS->pop_spot ();
1886 Lyric_req* lreq_p = new Lyric_req;
1887 lreq_p->set_mus_property ("text", $1);
1888 lreq_p->set_mus_property ("duration",$2);
1889 lreq_p->set_spot (i);
1890 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1891 velt_p->set_mus_property ("elements", scm_list_n (lreq_p->self_scm (), SCM_UNDEFINED));
1896 Input i = THIS->pop_spot ();
1898 if (!THIS->lexer_p_->chord_state_b ())
1899 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1906 steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1907 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1908 $$->set_spot (THIS->here_input ());
1915 | CHORD_COLON chord_notes {
1924 | chord_notes '.' chord_step {
1925 $$ = gh_append2 ($$, $3);
1933 | CHORD_CARET chord_notes {
1943 | '/' steno_tonic_pitch {
1952 | CHORD_BASS steno_tonic_pitch {
1959 $$ = gh_cons ($1, SCM_EOL);
1961 | CHORDMODIFIER_PITCH {
1962 $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
1964 | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1965 $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
1973 m.notename_i_ = ($1 - 1) % 7;
1974 m.octave_i_ = $1 > 7 ? 1 : 0;
1975 m.alteration_i_ = 0;
1977 $$ = m.smobbed_copy ();
1979 | bare_unsigned '+' {
1981 m.notename_i_ = ($1 - 1) % 7;
1982 m.octave_i_ = $1 > 7 ? 1 : 0;
1983 m.alteration_i_ = 1;
1986 $$ = m.smobbed_copy ();
1988 | bare_unsigned CHORD_MINUS {
1990 m.notename_i_ = ($1 - 1) % 7;
1991 m.octave_i_ = $1 > 7 ? 1 : 0;
1992 m.alteration_i_ = -1;
1994 $$ = m.smobbed_copy ();
2002 number_expression '+' number_term {
2003 $$ = scm_sum ($1, $3);
2005 | number_expression '-' number_term {
2006 $$ = scm_difference ($1, $3);
2015 | number_factor '*' number_factor {
2016 $$ = scm_product ($1, $3);
2018 | number_factor '/' number_factor {
2019 $$ = scm_divide ($1, $3);
2024 '(' number_expression ')' {
2027 | '-' number_factor { /* %prec UNARY_MINUS */
2028 $$ = scm_difference ($2, SCM_UNDEFINED);
2036 $$ = gh_int2scm ($1);
2041 | NUMBER_IDENTIFIER {
2045 $$ = gh_double2scm (gh_scm2double ($1) CM );
2048 $$ = gh_double2scm (gh_scm2double ($1) PT);
2051 $$ = gh_double2scm (gh_scm2double ($1) INCH);
2054 $$ = gh_double2scm (gh_scm2double ($1) MM);
2057 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
2073 if (scm_integer_p ($1) == SCM_BOOL_T)
2075 int k = gh_scm2int ($1);
2079 THIS->parser_error (_ ("need integer number arg"));
2093 | STRING_IDENTIFIER {
2096 | string '+' string {
2097 $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
2104 | exclamations '!' { $$ ++; }
2109 | questions '?' { $$ ++; }
2116 My_lily_parser::set_yydebug (bool )
2123 extern My_lily_parser * current_parser;
2126 My_lily_parser::do_yyparse ()
2129 current_parser = this;;
2130 yyparse ((void*)this);
2135 Should make this optional? It will also complain when you do
2139 which is entirely legitimate.
2141 Or we can scrap it. Barchecks should detect wrong durations, and
2142 skipTypesetting speeds it up a lot.
2145 My_lily_parser::beam_check (SCM dur)
2147 Duration *d = unsmob_duration (dur);
2148 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2150 Music * m = unsmob_music (last_beam_start_);
2151 m->origin ()->warning (_("Suspect duration found following this beam"));
2153 last_beam_start_ = SCM_EOL;