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 E_TILDE
249 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
253 %type <i> exclamations questions dots optional_rest
254 %type <i> bass_number bass_mod
255 %type <scm> br_bass_figure bass_figure figure_list figure_spec
257 %token <scm> NOTENAME_PITCH
258 %token <scm> TONICNAME_PITCH
259 %token <scm> CHORDMODIFIER_PITCH
260 %token <scm> DURATION_IDENTIFIER
261 %token <scm> FRACTION
262 %token <id> IDENTIFIER
265 %token <scm> SCORE_IDENTIFIER
266 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
268 %token <scm> NUMBER_IDENTIFIER
269 %token <scm> REQUEST_IDENTIFIER
270 %token <scm> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
271 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
272 %token <scm> RESTNAME
278 %type <outputdef> output_def
279 %type <scmhash> lilypond_header lilypond_header_body
280 %type <request> open_request_parens close_request_parens open_request close_request
281 %type <request> request_with_dir request_that_take_dir verbose_request
282 %type <i> sub_quotes sup_quotes
283 %type <music> simple_element request_chord command_element Simple_music Composite_music
284 %type <music> Repeated_music
285 %type <scm> Alternative_music
286 %type <i> tremolo_type
287 %type <i> bare_int bare_unsigned
290 %type <scm> identifier_init
292 %type <scm> steno_duration optional_notemode_duration multiplied_duration
293 %type <scm> verbose_duration
295 %type <reqvec> pre_requests post_requests
296 %type <request> gen_text_def
297 %type <scm> steno_pitch pitch absolute_pitch
298 %type <scm> explicit_pitch steno_tonic_pitch
300 %type <scm> chord_additions chord_subtractions chord_notes chord_step
302 %type <scm> chord_note chord_inversion chord_bass
303 %type <scm> duration_length fraction
305 %type <scm> embedded_scm scalar
306 %type <music> Music Sequential_music Simultaneous_music
307 %type <music> relative_music re_rhythmed_music part_combined_music
308 %type <music> property_def translator_change
309 %type <scm> Music_list
310 %type <outputdef> music_output_def_body
311 %type <request> shorthand_command_req
312 %type <request> post_request
313 %type <music> command_req verbose_command_req
314 %type <request> extender_req
315 %type <request> hyphen_req
316 %type <scm> string bare_number number_expression number_term number_factor
318 %type <score> score_block score_body
320 %type <scm> translator_spec_block translator_spec_body
321 %type <tempo> tempo_request
322 %type <scm> notenames_body notenames_block chordmodifiers_block
323 %type <scm> script_abbreviation
329 /* We don't assign precedence to / and *, because we might need varied
330 prec levels in different prods */
336 lilypond: /* empty */
337 | lilypond toplevel_expression {}
338 | lilypond assignment { }
340 THIS->error_level_i_ = 1;
343 THIS->error_level_i_ = 1;
349 THIS->lexer_p_->pitchname_tab_ = $1;
351 | chordmodifiers_block {
352 THIS->lexer_p_->chordmodifier_tab_ = $1;
356 scm_gc_unprotect_object (global_header_p->self_scm ());
357 global_header_p = $1;
360 score_global_array.push ($1);
363 if (dynamic_cast<Paper_def*> ($1))
364 THIS->lexer_p_->set_identifier (gh_str02scm ("$defaultpaper"), $1->self_scm ());
365 else if (dynamic_cast<Midi_def*> ($1))
366 THIS->lexer_p_->set_identifier (gh_str02scm ("$defaultmidi"), $1->self_scm ());
379 chordmodifiers_block:
380 CHORDMODIFIERS notenames_body { $$ = $2; }
384 PITCHNAMES notenames_body { $$ = $2; }
389 int i = scm_ilength ($1);
391 SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
392 for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) {
393 SCM pt = ly_cdar (s);
394 if (!unsmob_pitch (pt))
395 THIS->parser_error ("Need pitch object.");
397 scm_hashq_set_x (tab, ly_caar (s), pt);
404 lilypond_header_body:
406 $$ = new Scheme_hash_table;
407 THIS->lexer_p_-> scope_l_arr_.push ($$);
409 | lilypond_header_body assignment {
415 HEADER '{' lilypond_header_body '}' {
417 THIS->lexer_p_->scope_l_arr_.pop ();
429 /* cont */ '=' identifier_init {
432 Should find generic way of associating input with objects.
434 Input ip = THIS->pop_spot ();
436 if (! regular_identifier_b ($1))
438 ip.warning (_ ("Identifier should have alphabetic characters only"));
441 THIS->lexer_p_->set_identifier ($1, $4);
444 TODO: devise standard for protection in parser.
446 The parser stack lives on the C-stack, which means that
447 all objects can be unprotected as soon as they're here.
457 $$ = $1->self_scm ();
458 scm_gc_unprotect_object ($$);
461 $$ = $1->self_scm ();
462 scm_gc_unprotect_object ($$);
464 | translator_spec_block {
468 $$ = $1->self_scm ();
469 scm_gc_unprotect_object ($$);
472 $$ = $1->self_scm ();
473 scm_gc_unprotect_object ($$);
478 | number_expression {
489 translator_spec_block:
490 TRANSLATOR '{' translator_spec_body '}'
496 translator_spec_body:
497 TRANSLATOR_IDENTIFIER {
498 $$ = unsmob_translator_def ($1)->clone_scm ();
499 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
502 $$ = Translator_def::make_scm ();
503 Translator_def*td = unsmob_translator_def ($$);
504 td->translator_group_type_ = $2;
505 td->set_spot (THIS->here_input ());
507 | translator_spec_body STRING '=' embedded_scm {
508 unsmob_translator_def ($$)->add_property_assign ($2, $4);
510 | translator_spec_body STRING OVERRIDE embedded_scm '=' embedded_scm {
511 unsmob_translator_def ($$)
512 ->add_push_property (scm_string_to_symbol ($2), $4, $6);
514 | translator_spec_body STRING REVERT embedded_scm {
515 unsmob_translator_def ($$)->add_pop_property (
516 scm_string_to_symbol ($2), $4);
518 | translator_spec_body NAME STRING {
519 unsmob_translator_def ($$)->type_name_ = $3;
521 | translator_spec_body CONSISTS STRING {
522 unsmob_translator_def ($$)->add_element ($3);
524 | translator_spec_body ALIAS STRING {
525 Translator_def*td = unsmob_translator_def ($$);
526 td->type_aliases_ = gh_cons ($3, td->type_aliases_);
528 | translator_spec_body GROBDESCRIPTIONS embedded_scm {
529 Translator_def*td = unsmob_translator_def($$);
530 // td->add_property_assign (ly_symbol2scm ("allGrobDescriptions"), $3);
531 for (SCM p = $3; gh_pair_p (p); p = ly_cdr (p))
532 td->add_property_assign (scm_symbol_to_string (ly_caar (p)), ly_cdar (p));
534 | translator_spec_body CONSISTSEND STRING {
535 unsmob_translator_def ($$)->add_last_element ( $3);
537 | translator_spec_body ACCEPTS STRING {
538 unsmob_translator_def ($$)->set_acceptor ($3,true);
540 | translator_spec_body DENIES STRING {
541 unsmob_translator_def ($$)->set_acceptor ($3,false);
543 | translator_spec_body REMOVE STRING {
544 unsmob_translator_def ($$)->remove_element ($3);
555 /*cont*/ '{' score_body '}' {
558 if (!$$->def_p_arr_.size ())
560 Music_output_def *id =
561 unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
562 $$->add_output (id ? id->clone () : new Paper_def );
571 $$->set_spot (THIS->here_input ());
572 SCM m = $1->self_scm ();
573 scm_gc_unprotect_object (m);
577 $$ = new Score (*unsmob_score ($1));
578 $$->set_spot (THIS->here_input ());
580 | score_body lilypond_header {
581 scm_gc_unprotect_object ($2->self_scm ());
584 | score_body output_def {
597 music_output_def_body '}' {
599 THIS-> lexer_p_-> scope_l_arr_.pop ();
603 music_output_def_body:
605 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
610 p = dynamic_cast<Midi_def*> (id->clone ());
615 THIS->lexer_p_->scope_l_arr_.push (p->variable_tab_);
618 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
621 p = dynamic_cast<Paper_def*> (id->clone ());
624 THIS-> lexer_p_-> scope_l_arr_.push (p->variable_tab_);
627 | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
628 Music_output_def *p = unsmob_music_output_def ($3);
630 THIS->lexer_p_->scope_l_arr_.push (p->variable_tab_);
633 | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
634 Music_output_def *p = unsmob_music_output_def ($3);
637 THIS->lexer_p_->scope_l_arr_.push (p->variable_tab_);
640 | music_output_def_body assignment {
643 | music_output_def_body translator_spec_block {
644 $$->assign_translator ($2);
646 | music_output_def_body STYLESHEET embedded_scm {
647 dynamic_cast<Paper_def*> ($$)-> style_sheet_ = $3;
649 | music_output_def_body tempo_request {
651 junk this ? there already is tempo stuff in
654 int m = gh_scm2int ( $2->get_mus_property ("metronome-count"));
655 Duration *d = unsmob_duration ($2->get_mus_property ("duration"));
656 dynamic_cast<Midi_def*> ($$)->set_tempo (d->length_mom (), m);
658 | music_output_def_body error {
664 TEMPO steno_duration '=' bare_unsigned {
666 $$->set_mus_property ("duration", $2);
667 $$->set_mus_property ("metronome-count", gh_int2scm ( $4));
672 The representation of a list is the
676 to have efficient append.
678 Music_list: /* empty */ {
679 $$ = gh_cons (SCM_EOL, SCM_EOL);
683 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
684 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
685 if (gh_pair_p (ly_cdr (s)))
686 gh_set_cdr_x (ly_cdr (s), c); /* append */
688 gh_set_car_x (s, c); /* set first cons */
689 gh_set_cdr_x (s, c) ; /* remember last cell */
705 | ALTERNATIVE '{' Music_list '}' {
711 REPEAT string bare_unsigned Music Alternative_music
715 SCM alts = gh_pair_p ($5) ? gh_car ($5) : SCM_EOL;
716 if (times < scm_ilength (alts)) {
717 unsmob_music (gh_car (alts))
718 ->origin ()->warning (
719 _("More alternatives than repeats. Junking excess alternatives."));
720 alts = ly_truncate_list (times, alts);
723 Repeated_music * r = new Repeated_music (SCM_EOL);
726 r-> set_mus_property ("element", beg->self_scm ());
727 scm_gc_unprotect_object (beg->self_scm ());
729 r->set_mus_property ("repeat-count", gh_int2scm (times >? 1));
731 r-> set_mus_property ("elements",alts);
732 SCM func = scm_primitive_eval (ly_symbol2scm ("repeat-name-to-ctor"));
733 SCM result = gh_call1 (func, $2);
735 set_music_properties (r, result);
737 r->set_spot (*$4->origin ());
743 SEQUENTIAL '{' Music_list '}' {
744 $$ = new Sequential_music (SCM_EOL);
745 $$->set_mus_property ("elements", ly_car ($3));
747 | '{' Music_list '}' {
748 $$ = new Sequential_music (SCM_EOL);
749 $$->set_mus_property ("elements", ly_car ($2));
754 SIMULTANEOUS '{' Music_list '}'{
755 $$ = new Simultaneous_music (SCM_EOL);
756 $$->set_mus_property ("elements", ly_car ($3));
759 | '<' Music_list '>' {
760 $$ = new Simultaneous_music (SCM_EOL);
761 $$->set_mus_property ("elements", ly_car ($2));
766 request_chord { $$ = $1; }
767 | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm {
769 if (!gh_symbol_p ($3))
771 THIS->parser_error (_ ("Second argument must be a symbol"));
773 /*hould check # args */
774 if (!gh_procedure_p (pred))
776 THIS->parser_error (_ ("First argument must be a procedure taking 1 argument"));
779 Music *m = new Music (SCM_EOL);
780 m->set_mus_property ("predicate", pred);
781 m->set_mus_property ("grob-property", $3);
782 m->set_mus_property ("grob-value", $5);
783 m->set_mus_property ("iterator-ctor",
784 Output_property_music_iterator::constructor_cxx_function);
789 $$ = unsmob_music ($1)->clone ();
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 $$ = new Breathing_sign_req;
1245 $$ = new Porrectus_req;
1249 verbose_command_req:
1250 COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1251 Span_req * sp_p = new Span_req;
1252 sp_p-> set_span_dir ( Direction ($2));
1253 sp_p->set_mus_property ("span-type",$3);
1254 sp_p->set_spot (THIS->here_input ());
1258 Mark_req * m = new Mark_req;
1262 Mark_req *m = new Mark_req;
1263 m->set_mus_property ("label", $2);
1268 Break_req * b = new Break_req;
1270 if (!gh_number_p (s))
1273 b->set_mus_property ("penalty", s);
1274 b->set_spot (THIS->here_input ());
1277 | SKIP duration_length {
1278 Skip_req * skip_p = new Skip_req;
1279 skip_p->set_mus_property ("duration", $2);
1287 Key_change_req *key_p= new Key_change_req;
1290 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1291 Key_change_req *key_p= new Key_change_req;
1293 key_p->set_mus_property ("pitch-alist", $3);
1294 ((Music*)key_p)->transpose (* unsmob_pitch ($2));
1301 $$ = new Link_array<Request>;
1303 | post_requests post_request {
1304 $2->set_spot (THIS->here_input ());
1316 request_that_take_dir:
1319 | script_abbreviation {
1320 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1321 Articulation_req *a = new Articulation_req;
1322 if (gh_string_p (s))
1323 a->set_mus_property ("articulation-type", s);
1324 else THIS->parser_error (_ ("Expecting string as script definition"));
1330 script_dir request_that_take_dir {
1331 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1332 gs->set_direction (Direction ($1));
1334 $2->origin ()->warning (_ ("Can't specify direction for this request"));
1340 REQUEST_IDENTIFIER {
1341 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1342 $$->set_spot (THIS->here_input ());
1344 | DYNAMICSCRIPT embedded_scm {
1346 TODO: junkme, use text-type == dynamic
1348 Text_script_req *d = new Text_script_req;
1349 SCM dyn = ly_symbol2scm ("dynamic");
1350 d->set_mus_property ("text-type" , dyn);
1351 d->set_mus_property ("text", $2);
1352 d->set_spot (THIS->here_input ());
1355 | SPANREQUEST bare_int STRING {
1356 Span_req * sp_p = new Span_req;
1357 sp_p->set_span_dir ( Direction ($2));
1358 sp_p->set_mus_property ("span-type", $3);
1359 sp_p->set_spot (THIS->here_input ());
1363 Tremolo_req* a = new Tremolo_req;
1364 a->set_spot (THIS->here_input ());
1365 a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1369 Articulation_req * a = new Articulation_req;
1370 a->set_mus_property ("articulation-type", $2);
1371 a->set_spot (THIS->here_input ());
1375 duh, junk this syntax from the parser, if possible.
1378 Arpeggio_req *a = new Arpeggio_req;
1379 a->set_spot (THIS->here_input ());
1383 Glissando_req *g = new Glissando_req;
1384 g->set_spot /* No pun intended */ (THIS->here_input ());
1411 | NOTENAME_PITCH sup_quotes {
1412 Pitch p = *unsmob_pitch ($1);
1414 $$ = p.smobbed_copy ();
1416 | NOTENAME_PITCH sub_quotes {
1417 Pitch p =* unsmob_pitch ($1);
1420 $$ = p.smobbed_copy ();
1433 | TONICNAME_PITCH sup_quotes {
1434 Pitch p = *unsmob_pitch ($1);
1436 $$ = p.smobbed_copy ();
1438 | TONICNAME_PITCH sub_quotes {
1439 Pitch p =* unsmob_pitch ($1);
1442 $$ = p.smobbed_copy ();
1457 PITCH embedded_scm {
1459 if (!unsmob_pitch ($2)) {
1460 THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1461 $$ = Pitch ().smobbed_copy ();
1467 DURATION embedded_scm {
1469 if (!unsmob_duration ($2))
1471 THIS->parser_error (_ ("Must have duration object"));
1472 $$ = Duration ().smobbed_copy ();
1479 if (!THIS->lexer_p_->lyric_state_b ())
1480 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1481 $$ = new Extender_req;
1487 if (!THIS->lexer_p_->lyric_state_b ())
1488 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1489 $$ = new Hyphen_req;
1494 close_request_parens {
1496 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1499 close_request_parens:
1501 Span_req* s= new Span_req;
1503 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1506 Span_req* s= new Span_req;
1508 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1511 Span_req*s =new Span_req;
1513 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1516 Span_req*s =new Span_req;
1518 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1524 open_request_parens {
1526 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1530 open_request_parens:
1532 Span_req *s = new Span_req;
1533 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1538 Span_req* s= new Span_req;
1540 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1543 Span_req* s= new Span_req;
1545 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1551 Text_script_req *t = new Text_script_req;
1552 t->set_mus_property ("text", $1);
1553 t->set_spot (THIS->here_input ());
1557 Text_script_req *t = new Text_script_req;
1558 t->set_mus_property ("text", $1);
1559 t->set_spot (THIS->here_input ());
1563 String ds = to_str ($1);
1564 Text_script_req* t = new Text_script_req;
1565 SCM finger = ly_symbol2scm ("finger");
1566 t->set_mus_property ("text", ly_str02scm (ds.ch_C ()));
1567 t->set_mus_property ("text-type" , finger);
1568 t->set_spot (THIS->here_input ());
1573 script_abbreviation:
1575 $$ = gh_str02scm ("Hat");
1578 $$ = gh_str02scm ("Plus");
1581 $$ = gh_str02scm ("Dash");
1584 $$ = gh_str02scm ("Bar");
1587 $$ = gh_str02scm ("Larger");
1590 $$ = gh_str02scm ("Dot");
1597 | '-' { $$ = CENTER; }
1602 $$ = new Link_array<Request>;
1604 | pre_requests open_request {
1616 multiplied_duration {
1619 | verbose_duration {
1624 optional_notemode_duration:
1626 Duration dd = THIS->default_duration_;
1627 $$ = dd.smobbed_copy ();
1629 THIS->beam_check ($$);
1631 | multiplied_duration {
1633 THIS->default_duration_ = *unsmob_duration ($$);
1635 THIS->beam_check ($$);
1637 | verbose_duration {
1639 THIS->default_duration_ = *unsmob_duration ($$);
1644 bare_unsigned dots {
1646 if (!is_duration_b ($1))
1647 THIS->parser_error (_f ("not a duration: %d", $1));
1651 $$ = Duration (l, $2).smobbed_copy ();
1653 | DURATION_IDENTIFIER dots {
1654 Duration *d =unsmob_duration ($1);
1655 Duration k (d->duration_log (),d->dot_count () + $2);
1656 $$ = k.smobbed_copy ();
1663 multiplied_duration:
1667 | multiplied_duration '*' bare_unsigned {
1668 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1670 | multiplied_duration '*' FRACTION {
1671 Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr ($3)));
1673 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1678 FRACTION { $$ = $1; }
1679 | UNSIGNED '/' UNSIGNED {
1680 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1698 | ':' bare_unsigned {
1699 if (!is_duration_b ($2))
1700 THIS->parser_error (_f ("not a duration: %d", $2));
1719 Bass_figure_req *bfr = new Bass_figure_req;
1720 $$ = bfr->self_scm();
1721 scm_gc_unprotect_object ($$);
1724 Bass_figure_req *bfr = new Bass_figure_req;
1725 $$ = bfr->self_scm();
1727 bfr->set_mus_property ("figure", gh_int2scm ($1));
1729 scm_gc_unprotect_object ($$);
1731 | bass_figure bass_mod {
1732 Music *m = unsmob_music ($1);
1734 SCM salter =m->get_mus_property ("alteration");
1735 int alter = gh_number_p( salter) ? gh_scm2int (salter) : 0;
1736 m->set_mus_property ("alteration",
1737 gh_int2scm (alter + $2));
1739 m->set_mus_property ("alteration", gh_int2scm (0));
1747 unsmob_music ($$)->set_mus_property ("bracket-start", SCM_BOOL_T);
1752 | br_bass_figure ']' {
1754 unsmob_music ($1)->set_mus_property ("bracket-stop", SCM_BOOL_T);
1762 | figure_list br_bass_figure {
1763 $$ = gh_cons ($2, $1);
1768 FIGURE_OPEN figure_list FIGURE_CLOSE {
1769 Music * m = new Request_chord (SCM_EOL);
1770 $2 = scm_reverse_x ($2, SCM_EOL);
1771 m->set_mus_property ("elements", $2);
1772 $$ = m->self_scm ();
1783 pitch exclamations questions optional_notemode_duration optional_rest {
1785 Input i = THIS->pop_spot ();
1786 if (!THIS->lexer_p_->note_state_b ())
1787 THIS->parser_error (_ ("Have to be in Note mode for notes"));
1795 n->set_mus_property ("pitch", $1);
1796 n->set_mus_property ("duration", $4);
1800 n->set_mus_property ("cautionary", SCM_BOOL_T);
1801 if ($2 % 2 || $3 % 2)
1802 n->set_mus_property ("force-accidental", SCM_BOOL_T);
1804 Simultaneous_music*v = new Request_chord (SCM_EOL);
1805 v->set_mus_property ("elements", scm_list_n (n->self_scm (), SCM_UNDEFINED));
1811 | figure_spec optional_notemode_duration {
1812 Music * m = unsmob_music ($1);
1813 Input i = THIS->pop_spot ();
1815 for (SCM s = m->get_mus_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
1817 unsmob_music (ly_car (s))->set_mus_property ("duration", $2);
1821 | RESTNAME optional_notemode_duration {
1823 Input i = THIS->pop_spot ();
1824 SCM e = SCM_UNDEFINED;
1825 if (ly_scm2string ($1) =="s") {
1827 Skip_req * skip_p = new Skip_req;
1828 skip_p->set_mus_property ("duration" ,$2);
1829 skip_p->set_spot (i);
1830 e = skip_p->self_scm ();
1833 Rest_req * rest_req_p = new Rest_req;
1834 rest_req_p->set_mus_property ("duration", $2);
1835 rest_req_p->set_spot (i);
1836 e = rest_req_p->self_scm ();
1838 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1839 velt_p-> set_mus_property ("elements", scm_list_n (e,SCM_UNDEFINED));
1840 velt_p->set_spot (i);
1844 | MULTI_MEASURE_REST optional_notemode_duration {
1845 Input i = THIS->pop_spot ();
1847 Skip_req * sk = new Skip_req;
1848 sk->set_mus_property ("duration", $2);
1849 Span_req *sp1 = new Span_req;
1850 Span_req *sp2 = new Span_req;
1851 sp1-> set_span_dir ( START);
1852 sp2-> set_span_dir ( STOP);
1853 SCM r = ly_str02scm ("rest");
1854 sp1->set_mus_property ("span-type", r);
1855 sp2->set_mus_property ("span-type", r);
1857 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1858 rqc1->set_mus_property ("elements", scm_list_n (sp1->self_scm (), SCM_UNDEFINED));
1859 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1860 rqc2->set_mus_property ("elements", scm_list_n (sk->self_scm (), SCM_UNDEFINED));;
1861 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1862 rqc3->set_mus_property ("elements", scm_list_n (sp2->self_scm (), SCM_UNDEFINED));;
1864 SCM ms = scm_list_n (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1866 $$ = new Sequential_music (SCM_EOL);
1867 $$->set_mus_property ("elements", ms);
1869 | STRING optional_notemode_duration {
1870 Input i = THIS->pop_spot ();
1872 Lyric_req* lreq_p = new Lyric_req;
1873 lreq_p->set_mus_property ("text", $1);
1874 lreq_p->set_mus_property ("duration",$2);
1875 lreq_p->set_spot (i);
1876 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1877 velt_p->set_mus_property ("elements", scm_list_n (lreq_p->self_scm (), SCM_UNDEFINED));
1882 Input i = THIS->pop_spot ();
1884 if (!THIS->lexer_p_->chord_state_b ())
1885 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1892 steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1893 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1894 $$->set_spot (THIS->here_input ());
1901 | CHORD_COLON chord_notes {
1910 | chord_notes '.' chord_step {
1911 $$ = gh_append2 ($$, $3);
1919 | CHORD_CARET chord_notes {
1929 | '/' steno_tonic_pitch {
1938 | CHORD_BASS steno_tonic_pitch {
1945 $$ = gh_cons ($1, SCM_EOL);
1947 | CHORDMODIFIER_PITCH {
1948 $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
1950 | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1951 $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
1959 m.notename_i_ = ($1 - 1) % 7;
1960 m.octave_i_ = $1 > 7 ? 1 : 0;
1961 m.alteration_i_ = 0;
1963 $$ = m.smobbed_copy ();
1965 | bare_unsigned '+' {
1967 m.notename_i_ = ($1 - 1) % 7;
1968 m.octave_i_ = $1 > 7 ? 1 : 0;
1969 m.alteration_i_ = 1;
1972 $$ = m.smobbed_copy ();
1974 | bare_unsigned CHORD_MINUS {
1976 m.notename_i_ = ($1 - 1) % 7;
1977 m.octave_i_ = $1 > 7 ? 1 : 0;
1978 m.alteration_i_ = -1;
1980 $$ = m.smobbed_copy ();
1988 number_expression '+' number_term {
1989 $$ = scm_sum ($1, $3);
1991 | number_expression '-' number_term {
1992 $$ = scm_difference ($1, $3);
2001 | number_factor '*' number_factor {
2002 $$ = scm_product ($1, $3);
2004 | number_factor '/' number_factor {
2005 $$ = scm_divide ($1, $3);
2010 '(' number_expression ')' {
2013 | '-' number_factor { /* %prec UNARY_MINUS */
2014 $$ = scm_difference ($2, SCM_UNDEFINED);
2022 $$ = gh_int2scm ($1);
2027 | NUMBER_IDENTIFIER {
2031 $$ = gh_double2scm (gh_scm2double ($1) CM );
2034 $$ = gh_double2scm (gh_scm2double ($1) PT);
2037 $$ = gh_double2scm (gh_scm2double ($1) INCH);
2040 $$ = gh_double2scm (gh_scm2double ($1) MM);
2043 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
2059 if (scm_integer_p ($1) == SCM_BOOL_T)
2061 int k = gh_scm2int ($1);
2065 THIS->parser_error (_ ("need integer number arg"));
2079 | STRING_IDENTIFIER {
2082 | string '+' string {
2083 $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
2090 | exclamations '!' { $$ ++; }
2095 | questions '?' { $$ ++; }
2102 My_lily_parser::set_yydebug (bool b)
2109 extern My_lily_parser * current_parser;
2112 My_lily_parser::do_yyparse ()
2115 current_parser = this;;
2116 yyparse ((void*)this);
2121 Should make this optional? It will also complain when you do
2125 which is entirely legitimate.
2127 Or we can scrap it. Barchecks should detect wrong durations, and
2128 skipTypesetting speeds it up a lot.
2131 My_lily_parser::beam_check (SCM dur)
2133 Duration *d = unsmob_duration (dur);
2134 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2136 Music * m = unsmob_music (last_beam_start_);
2137 m->origin ()->warning (_("Suspect duration found following this beam"));
2139 last_beam_start_ = SCM_EOL;