1 %{ // -*-Fundamental-*-
4 parser.yy -- Bison/C++ parser for lilypond
6 source file of the GNU LilyPond music typesetter
8 (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 Jan Nieuwenhuizen <janneke@gnu.org>
13 Two shift/reduce problems:
20 the rules for who is protecting what are very shady. TODO: uniformise
29 #include "translator-def.hh"
30 #include "lily-guile.hh"
31 #include "change-iterator.hh"
33 #include "my-lily-lexer.hh"
34 #include "paper-def.hh"
35 #include "midi-def.hh"
37 #include "file-path.hh"
39 #include "dimensions.hh"
40 #include "command-request.hh"
41 #include "musical-request.hh"
42 #include "my-lily-parser.hh"
43 #include "context-specced-music.hh"
45 #include "music-list.hh"
46 #include "output-property-music-iterator.hh"
47 #include "property-iterator.hh"
48 #include "file-results.hh"
51 #include "relative-music.hh"
52 #include "lyric-combine-music.hh"
53 #include "transposed-music.hh"
54 #include "time-scaled-music.hh"
55 #include "repeated-music.hh"
56 #include "untransposable-music.hh"
57 #include "lilypond-input-version.hh"
58 #include "grace-music.hh"
59 #include "part-combine-music.hh"
60 #include "scm-hash.hh"
61 #include "auto-change-iterator.hh"
62 #include "un-relativable-music.hh"
66 regular_identifier_b (SCM id)
68 String str = ly_scm2string (id);
69 char const *s = str.ch_C() ;
74 v = v && isalpha (*s);
82 set_property_music (SCM sym, SCM value)
84 Music * p = new Music (SCM_EOL);
85 p->set_mus_property ("symbol", sym);
86 p->set_mus_property ("iterator-ctor",
87 Property_iterator::constructor_cxx_function);
89 p->set_mus_property ("value", value);
96 return t && t == 1 << intlog2 (t);
100 set_music_properties (Music *p, SCM a)
102 for (SCM k = a; gh_pair_p (k); k = ly_cdr (k))
104 p->internal_set_mus_property (ly_caar (k), ly_cdar (k));
114 // needed for bison.simple's malloc () and free ()
121 #define YYERROR_VERBOSE 1
123 #define YYPARSE_PARAM my_lily_parser_l
124 #define YYLEX_PARAM my_lily_parser_l
126 ((My_lily_parser *) my_lily_parser_l)
128 #define yyerror THIS->parser_error
129 #define ARRAY_SIZE(a,s) if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
136 Link_array<Request> *reqvec;
138 String *string; // needed by the lexer as temporary scratch area.
142 Scheme_hash_table *scmhash;
143 Music_output_def * outputdef;
147 /* We use SCMs to do strings, because it saves us the trouble of
148 deleting them. Let's hope that a stack overflow doesnt trigger a move
149 of the parse stack onto the heap. */
159 yylex (YYSTYPE *s, void * v_l)
161 My_lily_parser *pars_l = (My_lily_parser*) v_l;
162 My_lily_lexer * lex_l = pars_l->lexer_p_;
164 lex_l->lexval_l = (void*) s;
165 return lex_l->yylex ();
173 /* tokens which are not keywords */
183 %token CHORDMODIFIERS
191 %token GROBDESCRIPTIONS
197 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
207 %token MULTI_MEASURE_REST
219 %token OVERRIDE SET REVERT
232 %token COMMANDSPANREQUEST
234 %token OUTPUTPROPERTY
244 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE E_TILDE
245 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
247 %type <i> exclamations questions dots
248 %type <i> bass_number bass_mod
249 %type <scm> bass_figure figure_list figure_spec
251 %token <scm> NOTENAME_PITCH
252 %token <scm> TONICNAME_PITCH
253 %token <scm> CHORDMODIFIER_PITCH
254 %token <scm> DURATION_IDENTIFIER
255 %token <scm> FRACTION
256 %token <id> IDENTIFIER
259 %token <scm> SCORE_IDENTIFIER
260 %token <scm> MUSIC_OUTPUT_DEF_IDENTIFIER
262 %token <scm> NUMBER_IDENTIFIER
263 %token <scm> REQUEST_IDENTIFIER
264 %token <scm> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
265 %token <scm> STRING_IDENTIFIER SCM_IDENTIFIER
266 %token <scm> RESTNAME
272 %type <outputdef> output_def
273 %type <scmhash> lilypond_header lilypond_header_body
274 %type <request> open_request_parens close_request_parens open_request close_request
275 %type <request> request_with_dir request_that_take_dir verbose_request
276 %type <i> sub_quotes sup_quotes
277 %type <music> simple_element request_chord command_element Simple_music Composite_music
278 %type <music> Repeated_music
279 %type <scm> Alternative_music
280 %type <i> tremolo_type
281 %type <i> bare_int bare_unsigned
284 %type <scm> identifier_init
286 %type <scm> steno_duration optional_notemode_duration multiplied_duration
287 %type <scm> verbose_duration
289 %type <reqvec> pre_requests post_requests
290 %type <request> gen_text_def
291 %type <scm> steno_pitch pitch absolute_pitch
292 %type <scm> explicit_pitch steno_tonic_pitch
294 %type <scm> chord_additions chord_subtractions chord_notes chord_step
296 %type <scm> chord_note chord_inversion chord_bass
297 %type <scm> duration_length fraction
299 %type <scm> embedded_scm scalar
300 %type <music> Music Sequential_music Simultaneous_music
301 %type <music> relative_music re_rhythmed_music part_combined_music
302 %type <music> property_def translator_change
303 %type <scm> Music_list
304 %type <outputdef> music_output_def_body
305 %type <request> shorthand_command_req
306 %type <request> post_request
307 %type <music> command_req verbose_command_req
308 %type <request> extender_req
309 %type <request> hyphen_req
310 %type <scm> string bare_number number_expression number_term number_factor
312 %type <score> score_block score_body
314 %type <scm> translator_spec_block translator_spec_body
315 %type <tempo> tempo_request
316 %type <scm> notenames_body notenames_block chordmodifiers_block
317 %type <scm> script_abbreviation
323 /* We don't assign precedence to / and *, because we might need varied
324 prec levels in different prods */
330 lilypond: /* empty */
331 | lilypond toplevel_expression {}
332 | lilypond assignment { }
334 THIS->error_level_i_ = 1;
337 THIS->error_level_i_ = 1;
343 THIS->lexer_p_->pitchname_tab_ = $1;
345 | chordmodifiers_block {
346 THIS->lexer_p_->chordmodifier_tab_ = $1;
350 scm_gc_unprotect_object (global_header_p->self_scm ());
351 global_header_p = $1;
354 score_global_array.push ($1);
357 if (dynamic_cast<Paper_def*> ($1))
358 THIS->lexer_p_->set_identifier ("$defaultpaper", $1->self_scm ());
359 else if (dynamic_cast<Midi_def*> ($1))
360 THIS->lexer_p_->set_identifier ("$defaultmidi", $1->self_scm ());
373 chordmodifiers_block:
374 CHORDMODIFIERS notenames_body { $$ = $2; }
378 PITCHNAMES notenames_body { $$ = $2; }
383 int i = scm_ilength ($1);
385 SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
386 for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) {
387 SCM pt = ly_cdar (s);
388 if (!unsmob_pitch (pt))
389 THIS->parser_error ("Need pitch object.");
391 scm_hashq_set_x (tab, ly_caar (s), pt);
398 lilypond_header_body:
400 $$ = new Scheme_hash_table;
402 Scope *sc = new Scope ($$);
403 THIS->lexer_p_-> scope_l_arr_.push (sc);
405 | lilypond_header_body assignment {
411 HEADER '{' lilypond_header_body '}' {
413 delete THIS->lexer_p_-> scope_l_arr_.pop ();
425 /* cont */ '=' identifier_init {
428 Should find generic way of associating input with objects.
430 Input ip = THIS->pop_spot ();
432 if (! regular_identifier_b ($1))
434 ip.warning (_ ("Identifier should have alphabetic characters only"));
437 THIS->lexer_p_->set_identifier (ly_scm2string ($1), $4);
440 TODO: devise standard for protection in parser.
442 The parser stack lives on the C-stack, which means that
443 all objects can be unprotected as soon as they're here.
453 $$ = $1->self_scm ();
454 scm_gc_unprotect_object ($$);
457 $$ = $1->self_scm ();
458 scm_gc_unprotect_object ($$);
460 | translator_spec_block {
464 $$ = $1->self_scm ();
465 scm_gc_unprotect_object ($$);
468 $$ = $1->self_scm ();
469 scm_gc_unprotect_object ($$);
474 | number_expression {
485 translator_spec_block:
486 TRANSLATOR '{' translator_spec_body '}'
492 translator_spec_body:
493 TRANSLATOR_IDENTIFIER {
494 $$ = unsmob_translator_def ($1)->clone_scm ();
495 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
498 $$ = Translator_def::make_scm ();
499 Translator_def*td = unsmob_translator_def ($$);
500 td->translator_group_type_ = $2;
501 td->set_spot (THIS->here_input ());
503 | translator_spec_body STRING '=' embedded_scm {
504 unsmob_translator_def ($$)->add_property_assign ($2, $4);
506 | translator_spec_body STRING OVERRIDE embedded_scm '=' embedded_scm {
507 unsmob_translator_def ($$)
508 ->add_push_property (scm_string_to_symbol ($2), $4, $6);
510 | translator_spec_body STRING REVERT embedded_scm {
511 unsmob_translator_def ($$)->add_pop_property (
512 scm_string_to_symbol ($2), $4);
514 | translator_spec_body NAME STRING {
515 unsmob_translator_def ($$)->type_name_ = $3;
517 | translator_spec_body CONSISTS STRING {
518 unsmob_translator_def ($$)->add_element ($3);
520 | translator_spec_body ALIAS STRING {
521 Translator_def*td = unsmob_translator_def ($$);
522 td->type_aliases_ = gh_cons ($3, td->type_aliases_);
524 | translator_spec_body GROBDESCRIPTIONS embedded_scm {
525 Translator_def*td = unsmob_translator_def($$);
526 // td->add_property_assign (ly_symbol2scm ("allGrobDescriptions"), $3);
527 for (SCM p = $3; gh_pair_p (p); p = ly_cdr (p))
528 td->add_property_assign (scm_symbol_to_string (ly_caar (p)), ly_cdar (p));
530 | translator_spec_body CONSISTSEND STRING {
531 unsmob_translator_def ($$)->add_last_element ( $3);
533 | translator_spec_body ACCEPTS STRING {
534 unsmob_translator_def ($$)->set_acceptor ($3,true);
536 | translator_spec_body DENIES STRING {
537 unsmob_translator_def ($$)->set_acceptor ($3,false);
539 | translator_spec_body REMOVE STRING {
540 unsmob_translator_def ($$)->remove_element ($3);
551 /*cont*/ '{' score_body '}' {
554 if (!$$->def_p_arr_.size ())
556 Music_output_def *id =
557 unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
558 $$->add_output (id ? id->clone () : new Paper_def );
567 $$->set_spot (THIS->here_input ());
568 SCM m = $1->self_scm ();
569 scm_gc_unprotect_object (m);
573 $$ = new Score (*unsmob_score ($1));
574 $$->set_spot (THIS->here_input ());
576 | score_body lilypond_header {
577 scm_gc_unprotect_object ($2->self_scm ());
580 | score_body output_def {
593 music_output_def_body '}' {
595 THIS-> lexer_p_-> scope_l_arr_.pop ();
599 music_output_def_body:
601 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
606 p = dynamic_cast<Midi_def*> (id->clone ());
611 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
614 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
617 p = dynamic_cast<Paper_def*> (id->clone ());
620 THIS-> lexer_p_-> scope_l_arr_.push (p->scope_p_);
623 | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
624 Music_output_def *p = unsmob_music_output_def ($3);
626 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
629 | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
630 Music_output_def *p = unsmob_music_output_def ($3);
633 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
636 | music_output_def_body assignment {
639 | music_output_def_body translator_spec_block {
640 $$->assign_translator ($2);
642 | music_output_def_body STYLESHEET embedded_scm {
643 dynamic_cast<Paper_def*> ($$)-> style_sheet_ = $3;
645 | music_output_def_body tempo_request {
647 junk this ? there already is tempo stuff in
650 int m = gh_scm2int ( $2->get_mus_property ("metronome-count"));
651 Duration *d = unsmob_duration ($2->get_mus_property ("duration"));
652 dynamic_cast<Midi_def*> ($$)->set_tempo (d->length_mom (), m);
654 | music_output_def_body error {
660 TEMPO steno_duration '=' bare_unsigned {
662 $$->set_mus_property ("duration", $2);
663 $$->set_mus_property ("metronome-count", gh_int2scm ( $4));
668 The representation of a list is the
672 to have efficient append.
674 Music_list: /* empty */ {
675 $$ = gh_cons (SCM_EOL, SCM_EOL);
679 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
680 scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
681 if (gh_pair_p (ly_cdr (s)))
682 gh_set_cdr_x (ly_cdr (s), c); /* append */
684 gh_set_car_x (s, c); /* set first cons */
685 gh_set_cdr_x (s, c) ; /* remember last cell */
701 | ALTERNATIVE '{' Music_list '}' {
707 REPEAT string bare_unsigned Music Alternative_music
711 SCM alts = gh_pair_p ($5) ? gh_car ($5) : SCM_EOL;
712 if (times < scm_ilength (alts)) {
713 unsmob_music (gh_car (alts))
714 ->origin ()->warning (
715 _("More alternatives than repeats. Junking excess alternatives."));
716 alts = ly_truncate_list (times, alts);
719 Repeated_music * r = new Repeated_music (SCM_EOL);
722 r-> set_mus_property ("element", beg->self_scm ());
723 scm_gc_unprotect_object (beg->self_scm ());
725 r->set_mus_property ("repeat-count", gh_int2scm (times >? 1));
727 r-> set_mus_property ("elements",alts);
728 SCM func = scm_primitive_eval (ly_symbol2scm ("repeat-name-to-ctor"));
729 SCM result = gh_call1 (func, $2);
731 set_music_properties (r, result);
733 r->set_spot (*$4->origin ());
739 SEQUENTIAL '{' Music_list '}' {
740 $$ = new Sequential_music (SCM_EOL);
741 $$->set_mus_property ("elements", ly_car ($3));
743 | '{' Music_list '}' {
744 $$ = new Sequential_music (SCM_EOL);
745 $$->set_mus_property ("elements", ly_car ($2));
750 SIMULTANEOUS '{' Music_list '}'{
751 $$ = new Simultaneous_music (SCM_EOL);
752 $$->set_mus_property ("elements", ly_car ($3));
755 | '<' Music_list '>' {
756 $$ = new Simultaneous_music (SCM_EOL);
757 $$->set_mus_property ("elements", ly_car ($2));
762 request_chord { $$ = $1; }
763 | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm {
765 if (!gh_symbol_p ($3))
767 THIS->parser_error (_ ("Second argument must be a symbol"));
769 /*hould check # args */
770 if (!gh_procedure_p (pred))
772 THIS->parser_error (_ ("First argument must be a procedure taking 1 argument"));
775 Music *m = new Music (SCM_EOL);
776 m->set_mus_property ("predicate", pred);
777 m->set_mus_property ("grob-property", $3);
778 m->set_mus_property ("grob-value", $5);
779 m->set_mus_property ("iterator-ctor",
780 Output_property_music_iterator::constructor_cxx_function);
785 $$ = unsmob_music ($1)->clone ();
793 CONTEXT STRING Music {
794 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
795 csm->set_mus_property ("element", $3->self_scm ());
796 scm_gc_unprotect_object ($3->self_scm ());
798 csm->set_mus_property ("context-type",$2);
799 csm->set_mus_property ("context-id", ly_str02scm (""));
803 | AUTOCHANGE STRING Music {
804 Music * chm = new Music_wrapper (SCM_EOL);
805 chm->set_mus_property ("element", $3->self_scm ());
806 chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_cxx_function);
808 scm_gc_unprotect_object ($3->self_scm ());
809 chm->set_mus_property ("what", $2);
812 chm->set_spot (*$3->origin ());
817 The other version is for easier debugging of
818 Sequential_music_iterator in combination with grace notes.
821 SCM start = THIS->lexer_p_->lookup_identifier ("startGraceMusic");
822 SCM stop = THIS->lexer_p_->lookup_identifier ("stopGraceMusic");
823 Music *startm = unsmob_music (start);
824 Music *stopm = unsmob_music (stop);
828 stopm = stopm->clone ();
829 ms = gh_cons (stopm->self_scm (), ms);
830 scm_gc_unprotect_object (stopm->self_scm ());
832 ms = gh_cons ($2->self_scm (), ms);
833 scm_gc_unprotect_object ($2->self_scm());
835 startm = startm->clone ();
836 ms = gh_cons (startm->self_scm () , ms);
837 scm_gc_unprotect_object (startm->self_scm ());
840 Music* seq = new Sequential_music (SCM_EOL);
841 seq->set_mus_property ("elements", ms);
843 $$ = new Grace_music (SCM_EOL);
844 $$->set_mus_property ("element", seq->self_scm ());
845 scm_gc_unprotect_object (seq->self_scm ());
847 $$ = new Grace_music (SCM_EOL);
848 $$->set_mus_property ("element", $2->self_scm ());
849 scm_gc_unprotect_object ($2->self_scm ());
852 | CONTEXT string '=' string Music {
853 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
854 csm->set_mus_property ("element", $5->self_scm ());
855 scm_gc_unprotect_object ($5->self_scm ());
857 csm->set_mus_property ("context-type", $2);
858 csm->set_mus_property ("context-id", $4);
869 int n = gh_scm2int (ly_car ($3)); int d = gh_scm2int (ly_cdr ($3));
871 $$ = new Time_scaled_music (SCM_EOL);
872 $$->set_spot (THIS->pop_spot ());
875 $$->set_mus_property ("element", mp->self_scm ());
876 scm_gc_unprotect_object (mp->self_scm ());
877 $$->set_mus_property ("numerator", gh_int2scm (n));
878 $$->set_mus_property ("denominator", gh_int2scm (d));
879 $$->compress (Moment (Rational (n,d)));
882 | Repeated_music { $$ = $1; }
883 | Simultaneous_music { $$ = $1; }
884 | Sequential_music { $$ = $1; }
885 | TRANSPOSE pitch Music {
886 $$ = new Transposed_music (SCM_EOL);
888 Pitch pit = *unsmob_pitch ($2);
891 $$->set_mus_property ("element", p->self_scm ());
892 scm_gc_unprotect_object (p->self_scm ());
894 | TRANSPOSE steno_tonic_pitch Music {
895 $$ = new Transposed_music (SCM_EOL);
897 Pitch pit = *unsmob_pitch ($2);
900 $$->set_mus_property ("element", p->self_scm ());
901 scm_gc_unprotect_object (p->self_scm ());
904 | APPLY embedded_scm Music {
905 SCM ret = gh_call1 ($2, $3->self_scm ());
906 Music *m = unsmob_music (ret);
908 THIS->parser_error ("\\apply must return a Music");
909 m = new Music (SCM_EOL);
914 { THIS->lexer_p_->push_note_state (); }
917 THIS->lexer_p_->pop_state ();
920 { THIS->lexer_p_->push_figuredbass_state (); }
923 Music * chm = new Untransposable_music () ;
924 chm->set_mus_property ("element", $3->self_scm ());
927 THIS->lexer_p_->pop_state ();
930 { THIS->lexer_p_->push_chord_state (); }
933 Music * chm = new Un_relativable_music ;
934 chm->set_mus_property ("element", $3->self_scm ());
937 THIS->lexer_p_->pop_state ();
940 { THIS->lexer_p_->push_lyric_state (); }
944 THIS->lexer_p_->pop_state ();
946 | relative_music { $$ = $1; }
947 | re_rhythmed_music { $$ = $1; }
948 | part_combined_music { $$ = $1; }
952 RELATIVE absolute_pitch Music {
954 Pitch pit = *unsmob_pitch ($2);
955 $$ = new Relative_octave_music (SCM_EOL);
957 $$->set_mus_property ("element", p->self_scm ());
958 scm_gc_unprotect_object (p->self_scm ());
960 $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ());
966 ADDLYRICS Music Music {
967 Lyric_combine_music * l = new Lyric_combine_music (SCM_EOL);
968 l->set_mus_property ("elements", gh_list ($2->self_scm (), $3->self_scm (), SCM_UNDEFINED));
969 scm_gc_unprotect_object ($3->self_scm ());
970 scm_gc_unprotect_object ($2->self_scm ());
976 PARTCOMBINE STRING Music Music {
977 Part_combine_music * p = new Part_combine_music (SCM_EOL);
979 p->set_mus_property ("what", $2);
980 p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED));
982 scm_gc_unprotect_object ($3->self_scm ());
983 scm_gc_unprotect_object ($4->self_scm ());
990 TRANSLATOR STRING '=' STRING {
991 Music * t = new Music (SCM_EOL);
992 t->set_mus_property ("iterator-ctor",
993 Change_iterator::constructor_cxx_function);
994 t-> set_mus_property ("change-to-type", $2);
995 t-> set_mus_property ("change-to-id", $4);
998 $$->set_spot (THIS->here_input ());
1003 PROPERTY STRING '.' STRING '=' scalar {
1005 Music *t = set_property_music (scm_string_to_symbol ($4), $6);
1006 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1008 csm->set_mus_property ("element", t->self_scm ());
1009 scm_gc_unprotect_object (t->self_scm ());
1012 $$->set_spot (THIS->here_input ());
1014 csm-> set_mus_property ("context-type", $2);
1016 | PROPERTY STRING '.' STRING UNSET {
1017 Music *t = new Music (SCM_EOL);
1019 t->set_mus_property ("iterator-ctor",
1020 Property_unset_iterator::constructor_cxx_function);
1021 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
1023 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1024 csm->set_mus_property ("element", t->self_scm ());
1025 scm_gc_unprotect_object (t->self_scm ());
1028 $$->set_spot (THIS->here_input ());
1030 csm-> set_mus_property ("context-type", $2);
1032 | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm {
1033 Music *t = new Music (SCM_EOL);
1034 t->set_mus_property ("iterator-ctor",
1035 Push_property_iterator::constructor_cxx_function);
1036 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1037 t->set_mus_property ("pop-first", SCM_BOOL_T);
1038 t->set_mus_property ("grob-property", $6);
1039 t->set_mus_property ("grob-value", $8);
1040 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1041 csm->set_mus_property ("element", t->self_scm ());
1042 scm_gc_unprotect_object (t->self_scm ());
1044 $$->set_spot (THIS->here_input ());
1046 csm-> set_mus_property ("context-type", $2);
1048 | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
1049 Music *t = new Music (SCM_EOL);
1050 t->set_mus_property ("iterator-ctor",
1051 Push_property_iterator::constructor_cxx_function);
1052 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1053 t->set_mus_property ("grob-property", $6);
1054 t->set_mus_property ("grob-value", $8);
1055 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1056 csm->set_mus_property ("element", t->self_scm ());
1057 scm_gc_unprotect_object (t->self_scm ());
1060 $$->set_spot (THIS->here_input ());
1062 csm-> set_mus_property ("context-type", $2);
1064 | PROPERTY STRING '.' STRING REVERT embedded_scm {
1065 Music *t = new Music (SCM_EOL);
1066 t->set_mus_property ("iterator-ctor",
1067 Pop_property_iterator::constructor_cxx_function);
1068 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1069 t->set_mus_property ("grob-property", $6);
1071 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1072 csm->set_mus_property ("element", t->self_scm ());
1073 scm_gc_unprotect_object (t->self_scm ());
1076 $$->set_spot (THIS->here_input ());
1078 csm-> set_mus_property ("context-type", $2);
1084 | bare_int { $$ = gh_int2scm ($1); }
1085 | embedded_scm { $$ = $1; }
1092 } /*cont */ simple_element post_requests {
1093 Music_sequence *l = dynamic_cast<Music_sequence*> ($3);
1096 for (int i=0; i < $1->size (); i++) {
1097 Music * m = $1->elem (i);
1098 l->append_music (m);
1110 $$ = new Request_chord (SCM_EOL);
1111 $$->set_mus_property ("elements", gh_cons ($1->self_scm (), SCM_EOL));
1112 $$-> set_spot (THIS->here_input ());
1113 $1-> set_spot (THIS->here_input ());
1116 extern Music * get_barcheck();
1117 $$ = get_barcheck ();
1118 $$->set_spot (THIS->here_input ());
1121 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1123 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1124 csm->set_mus_property ("element", t->self_scm ());
1125 scm_gc_unprotect_object (t->self_scm ());
1128 $$->set_spot (THIS->here_input ());
1130 csm->set_mus_property ("context-type", ly_str02scm ("Score"));
1132 | PARTIAL duration_length {
1133 Moment m = - unsmob_duration ($2)->length_mom ();
1134 Music * p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1136 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1137 sp->set_mus_property ("element", p->self_scm ());
1138 scm_gc_unprotect_object (p->self_scm ());
1141 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1144 SCM func = scm_primitive_eval (ly_symbol2scm ("clef-name-to-properties"));
1145 SCM result = gh_call1 (func, $2);
1148 for (SCM s = result ; gh_pair_p (s); s = ly_cdr (s)) {
1149 Music * p = new Music (SCM_EOL);
1150 set_music_properties (p, ly_car (s));
1151 l = gh_cons (p->self_scm (), l);
1152 scm_gc_unprotect_object (p->self_scm ());
1154 Sequential_music * seq = new Sequential_music (SCM_EOL);
1155 seq->set_mus_property ("elements", l);
1157 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1158 sp->set_mus_property ("element", seq->self_scm ());
1159 scm_gc_unprotect_object (seq->self_scm ());
1162 sp-> set_mus_property ("context-type", ly_str02scm ("Staff"));
1165 Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2);
1167 int l = gh_scm2int (ly_car ($2));
1168 int o = gh_scm2int (ly_cdr ($2));
1170 Moment one_beat = Moment (1)/Moment (o);
1171 Moment len = Moment (l) * one_beat;
1174 Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ());
1175 Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ());
1177 SCM list = scm_list_n (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED);
1178 Sequential_music *seq = new Sequential_music (SCM_EOL);
1179 seq->set_mus_property ("elements", list);
1182 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1183 sp->set_mus_property ("element", seq->self_scm ());
1187 scm_gc_unprotect_object (p3->self_scm ());
1188 scm_gc_unprotect_object (p2->self_scm ());
1189 scm_gc_unprotect_object (p1->self_scm ());
1190 scm_gc_unprotect_object (seq->self_scm ());
1195 TODO: should make alias TimingContext for Score
1198 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1203 shorthand_command_req { $$ = $1; }
1204 | verbose_command_req { $$ = $1; }
1207 shorthand_command_req:
1218 Span_req*b= new Span_req;
1219 b->set_span_dir (START);
1220 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1224 THIS->last_beam_start_ = b->self_scm ();
1227 Span_req*b= new Span_req;
1228 b->set_span_dir ( STOP);
1229 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1233 $$ = new Breathing_sign_req;
1236 $$ = new Porrectus_req;
1240 verbose_command_req:
1241 COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1242 Span_req * sp_p = new Span_req;
1243 sp_p-> set_span_dir ( Direction ($2));
1244 sp_p->set_mus_property ("span-type",$3);
1245 sp_p->set_spot (THIS->here_input ());
1249 Mark_req * m = new Mark_req;
1253 Mark_req *m = new Mark_req;
1254 m->set_mus_property ("label", $2);
1259 Break_req * b = new Break_req;
1261 if (!gh_number_p (s))
1264 b->set_mus_property ("penalty", s);
1265 b->set_spot (THIS->here_input ());
1268 | SKIP duration_length {
1269 Skip_req * skip_p = new Skip_req;
1270 skip_p->set_mus_property ("duration", $2);
1278 Key_change_req *key_p= new Key_change_req;
1281 | KEY NOTENAME_PITCH SCM_IDENTIFIER {
1282 Key_change_req *key_p= new Key_change_req;
1284 key_p->set_mus_property ("pitch-alist", $3);
1285 ((Music*)key_p)->transpose (* unsmob_pitch ($2));
1292 $$ = new Link_array<Request>;
1294 | post_requests post_request {
1295 $2->set_spot (THIS->here_input ());
1307 request_that_take_dir:
1310 | script_abbreviation {
1311 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1312 Articulation_req *a = new Articulation_req;
1313 if (gh_string_p (s))
1314 a->set_mus_property ("articulation-type", s);
1315 else THIS->parser_error (_ ("Expecting string as script definition"));
1321 script_dir request_that_take_dir {
1322 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1323 gs->set_direction (Direction ($1));
1325 $2->origin ()->warning (_ ("Can't specify direction for this request"));
1331 REQUEST_IDENTIFIER {
1332 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1333 $$->set_spot (THIS->here_input ());
1335 | DYNAMICSCRIPT embedded_scm {
1337 TODO: junkme, use text-type == dynamic
1339 Text_script_req *d = new Text_script_req;
1340 SCM dyn = ly_symbol2scm ("dynamic");
1341 d->set_mus_property ("text-type" , dyn);
1342 d->set_mus_property ("text", $2);
1343 d->set_spot (THIS->here_input ());
1346 | SPANREQUEST bare_int STRING {
1347 Span_req * sp_p = new Span_req;
1348 sp_p->set_span_dir ( Direction ($2));
1349 sp_p->set_mus_property ("span-type", $3);
1350 sp_p->set_spot (THIS->here_input ());
1354 Tremolo_req* a = new Tremolo_req;
1355 a->set_spot (THIS->here_input ());
1356 a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1360 Articulation_req * a = new Articulation_req;
1361 a->set_mus_property ("articulation-type", $2);
1362 a->set_spot (THIS->here_input ());
1366 duh, junk this syntax from the parser, if possible.
1369 Arpeggio_req *a = new Arpeggio_req;
1370 a->set_spot (THIS->here_input ());
1374 Glissando_req *g = new Glissando_req;
1375 g->set_spot /* No pun intended */ (THIS->here_input ());
1402 | NOTENAME_PITCH sup_quotes {
1403 Pitch p = *unsmob_pitch ($1);
1405 $$ = p.smobbed_copy ();
1407 | NOTENAME_PITCH sub_quotes {
1408 Pitch p =* unsmob_pitch ($1);
1411 $$ = p.smobbed_copy ();
1424 | TONICNAME_PITCH sup_quotes {
1425 Pitch p = *unsmob_pitch ($1);
1427 $$ = p.smobbed_copy ();
1429 | TONICNAME_PITCH sub_quotes {
1430 Pitch p =* unsmob_pitch ($1);
1433 $$ = p.smobbed_copy ();
1448 PITCH embedded_scm {
1450 if (!unsmob_pitch ($2)) {
1451 THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1452 $$ = Pitch ().smobbed_copy ();
1458 DURATION embedded_scm {
1460 if (!unsmob_duration ($2))
1462 THIS->parser_error (_ ("Must have duration object"));
1463 $$ = Duration ().smobbed_copy ();
1470 if (!THIS->lexer_p_->lyric_state_b ())
1471 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1472 $$ = new Extender_req;
1478 if (!THIS->lexer_p_->lyric_state_b ())
1479 THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1480 $$ = new Hyphen_req;
1485 close_request_parens {
1487 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1490 close_request_parens:
1492 Span_req* s= new Span_req;
1494 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1497 Span_req* s= new Span_req;
1499 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1502 Span_req*s =new Span_req;
1504 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1507 Span_req*s =new Span_req;
1509 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1515 open_request_parens {
1517 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1521 open_request_parens:
1523 Span_req *s = new Span_req;
1524 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1529 Span_req* s= new Span_req;
1531 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1534 Span_req* s= new Span_req;
1536 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1542 Text_script_req *t = new Text_script_req;
1543 t->set_mus_property ("text", $1);
1544 t->set_spot (THIS->here_input ());
1548 Text_script_req *t = new Text_script_req;
1549 t->set_mus_property ("text", $1);
1550 t->set_spot (THIS->here_input ());
1554 String ds = to_str ($1);
1555 Text_script_req* t = new Text_script_req;
1556 SCM finger = ly_symbol2scm ("finger");
1557 t->set_mus_property ("text", ly_str02scm (ds.ch_C ()));
1558 t->set_mus_property ("text-type" , finger);
1559 t->set_spot (THIS->here_input ());
1564 script_abbreviation:
1566 $$ = gh_str02scm ("Hat");
1569 $$ = gh_str02scm ("Plus");
1572 $$ = gh_str02scm ("Dash");
1575 $$ = gh_str02scm ("Bar");
1578 $$ = gh_str02scm ("Larger");
1581 $$ = gh_str02scm ("Dot");
1588 | '-' { $$ = CENTER; }
1593 $$ = new Link_array<Request>;
1595 | pre_requests open_request {
1607 multiplied_duration {
1610 | verbose_duration {
1615 optional_notemode_duration:
1617 Duration dd = THIS->default_duration_;
1618 $$ = dd.smobbed_copy ();
1620 THIS->beam_check ($$);
1622 | multiplied_duration {
1624 THIS->default_duration_ = *unsmob_duration ($$);
1626 THIS->beam_check ($$);
1628 | verbose_duration {
1630 THIS->default_duration_ = *unsmob_duration ($$);
1635 bare_unsigned dots {
1637 if (!is_duration_b ($1))
1638 THIS->parser_error (_f ("not a duration: %d", $1));
1642 $$ = Duration (l, $2).smobbed_copy ();
1644 | DURATION_IDENTIFIER dots {
1645 Duration *d =unsmob_duration ($1);
1646 Duration k (d->duration_log (),d->dot_count () + $2);
1647 $$ = k.smobbed_copy ();
1654 multiplied_duration:
1658 | multiplied_duration '*' bare_unsigned {
1659 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1661 | multiplied_duration '*' FRACTION {
1662 Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr ($3)));
1664 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1669 FRACTION { $$ = $1; }
1670 | UNSIGNED '/' UNSIGNED {
1671 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1689 | ':' bare_unsigned {
1690 if (!is_duration_b ($2))
1691 THIS->parser_error (_f ("not a duration: %d", $2));
1711 p .notename_i_ = $1 - 1;
1714 Note_req * nr = new Note_req;
1715 $$ = nr->self_scm ();
1716 nr->set_mus_property ("pitch", p.smobbed_copy ());
1717 scm_gc_unprotect_object ($$);
1719 | bass_figure bass_mod {
1721 SCM sp = unsmob_music ($1)->get_mus_property ("pitch");
1722 unsmob_pitch (sp)->alteration_i_ += $2;
1724 unsmob_music ($1)->set_mus_property ("force-accidental", SCM_BOOL_T);
1733 | figure_list bass_figure {
1734 $$ = gh_cons ($2, $1);
1739 FIGURE_OPEN figure_list FIGURE_CLOSE {
1740 Music * m = new Request_chord (SCM_EOL);
1741 $2 = scm_reverse_x ($2, SCM_EOL);
1742 m->set_mus_property ("elements", $2);
1743 $$ = m->self_scm ();
1748 pitch exclamations questions optional_notemode_duration {
1750 Input i = THIS->pop_spot ();
1751 if (!THIS->lexer_p_->note_state_b ())
1752 THIS->parser_error (_ ("Have to be in Note mode for notes"));
1754 Note_req *n = new Note_req;
1756 n->set_mus_property ("pitch", $1);
1757 n->set_mus_property ("duration", $4);
1760 n->set_mus_property ("cautionary", SCM_BOOL_T);
1761 if ($2 % 2 || $3 % 2)
1762 n->set_mus_property ("force-accidental", SCM_BOOL_T);
1764 Simultaneous_music*v = new Request_chord (SCM_EOL);
1765 v->set_mus_property ("elements", scm_list_n (n->self_scm (), SCM_UNDEFINED));
1771 | figure_spec optional_notemode_duration {
1772 Music * m = unsmob_music ($1);
1773 Input i = THIS->pop_spot ();
1775 for (SCM s = m->get_mus_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
1777 unsmob_music (ly_car (s))->set_mus_property ("duration", $2);
1781 | RESTNAME optional_notemode_duration {
1783 Input i = THIS->pop_spot ();
1784 SCM e = SCM_UNDEFINED;
1785 if (ly_scm2string ($1) =="s") {
1787 Skip_req * skip_p = new Skip_req;
1788 skip_p->set_mus_property ("duration" ,$2);
1789 skip_p->set_spot (i);
1790 e = skip_p->self_scm ();
1793 Rest_req * rest_req_p = new Rest_req;
1794 rest_req_p->set_mus_property ("duration", $2);
1795 rest_req_p->set_spot (i);
1796 e = rest_req_p->self_scm ();
1798 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1799 velt_p-> set_mus_property ("elements", scm_list_n (e,SCM_UNDEFINED));
1800 velt_p->set_spot (i);
1804 | MULTI_MEASURE_REST optional_notemode_duration {
1805 Input i = THIS->pop_spot ();
1807 Skip_req * sk = new Skip_req;
1808 sk->set_mus_property ("duration", $2);
1809 Span_req *sp1 = new Span_req;
1810 Span_req *sp2 = new Span_req;
1811 sp1-> set_span_dir ( START);
1812 sp2-> set_span_dir ( STOP);
1813 SCM r = ly_str02scm ("rest");
1814 sp1->set_mus_property ("span-type", r);
1815 sp2->set_mus_property ("span-type", r);
1817 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1818 rqc1->set_mus_property ("elements", scm_list_n (sp1->self_scm (), SCM_UNDEFINED));
1819 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1820 rqc2->set_mus_property ("elements", scm_list_n (sk->self_scm (), SCM_UNDEFINED));;
1821 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1822 rqc3->set_mus_property ("elements", scm_list_n (sp2->self_scm (), SCM_UNDEFINED));;
1824 SCM ms = scm_list_n (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1826 $$ = new Sequential_music (SCM_EOL);
1827 $$->set_mus_property ("elements", ms);
1829 | STRING optional_notemode_duration {
1830 Input i = THIS->pop_spot ();
1832 Lyric_req* lreq_p = new Lyric_req;
1833 lreq_p->set_mus_property ("text", $1);
1834 lreq_p->set_mus_property ("duration",$2);
1835 lreq_p->set_spot (i);
1836 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1837 velt_p->set_mus_property ("elements", scm_list_n (lreq_p->self_scm (), SCM_UNDEFINED));
1842 Input i = THIS->pop_spot ();
1844 if (!THIS->lexer_p_->chord_state_b ())
1845 THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1852 steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1853 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1854 $$->set_spot (THIS->here_input ());
1861 | CHORD_COLON chord_notes {
1870 | chord_notes '.' chord_step {
1871 $$ = gh_append2 ($$, $3);
1879 | CHORD_CARET chord_notes {
1889 | '/' steno_tonic_pitch {
1898 | CHORD_BASS steno_tonic_pitch {
1905 $$ = gh_cons ($1, SCM_EOL);
1907 | CHORDMODIFIER_PITCH {
1908 $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
1910 | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1911 $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
1919 m.notename_i_ = ($1 - 1) % 7;
1920 m.octave_i_ = $1 > 7 ? 1 : 0;
1921 m.alteration_i_ = 0;
1923 $$ = m.smobbed_copy ();
1925 | bare_unsigned '+' {
1927 m.notename_i_ = ($1 - 1) % 7;
1928 m.octave_i_ = $1 > 7 ? 1 : 0;
1929 m.alteration_i_ = 1;
1932 $$ = m.smobbed_copy ();
1934 | bare_unsigned CHORD_MINUS {
1936 m.notename_i_ = ($1 - 1) % 7;
1937 m.octave_i_ = $1 > 7 ? 1 : 0;
1938 m.alteration_i_ = -1;
1940 $$ = m.smobbed_copy ();
1948 number_expression '+' number_term {
1949 $$ = scm_sum ($1, $3);
1951 | number_expression '-' number_term {
1952 $$ = scm_difference ($1, $3);
1961 | number_factor '*' number_factor {
1962 $$ = scm_product ($1, $3);
1964 | number_factor '/' number_factor {
1965 $$ = scm_divide ($1, $3);
1970 '(' number_expression ')' {
1973 | '-' number_factor { /* %prec UNARY_MINUS */
1974 $$ = scm_difference ($2, SCM_UNDEFINED);
1982 $$ = gh_int2scm ($1);
1987 | NUMBER_IDENTIFIER {
1991 $$ = gh_double2scm (gh_scm2double ($1) CM );
1994 $$ = gh_double2scm (gh_scm2double ($1) PT);
1997 $$ = gh_double2scm (gh_scm2double ($1) INCH);
2000 $$ = gh_double2scm (gh_scm2double ($1) MM);
2003 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
2019 if (scm_integer_p ($1) == SCM_BOOL_T)
2021 int k = gh_scm2int ($1);
2025 THIS->parser_error (_ ("need integer number arg"));
2039 | STRING_IDENTIFIER {
2042 | string '+' string {
2043 $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
2050 | exclamations '!' { $$ ++; }
2055 | questions '?' { $$ ++; }
2062 My_lily_parser::set_yydebug (bool b)
2069 extern My_lily_parser * current_parser;
2072 My_lily_parser::do_yyparse ()
2075 current_parser = this;;
2076 yyparse ((void*)this);
2081 Should make this optional? It will also complain when you do
2085 which is entirely legitimate.
2087 Or we can scrap it. Barchecks should detect wrong durations, and
2088 skipTypesetting speeds it up a lot.
2091 My_lily_parser::beam_check (SCM dur)
2093 Duration *d = unsmob_duration (dur);
2094 if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
2096 Music * m = unsmob_music (last_beam_start_);
2097 m->origin ()->warning (_("Suspect duration found following this beam"));
2099 last_beam_start_ = SCM_EOL;