]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.yy
release: 1.3.150
[lilypond.git] / lily / parser.yy
1 %{ // -*-Fundamental-*-
2
3 /*
4   parser.yy -- Bison/C++ parser for lilypond
5
6   source file of the GNU LilyPond music typesetter
7
8   (c)  1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9            Jan Nieuwenhuizen <janneke@gnu.org>
10 */
11 #include <ctype.h>
12 #include <iostream.h>
13
14 #include "translator-def.hh"
15 #include "lily-guile.hh"
16 #include "change-iterator.hh"
17 #include "misc.hh"
18 #include "my-lily-lexer.hh"
19 #include "paper-def.hh"
20 #include "midi-def.hh"
21 #include "main.hh"
22 #include "file-path.hh"
23 #include "debug.hh"
24 #include "dimensions.hh"
25 #include "command-request.hh"
26 #include "musical-request.hh"
27 #include "my-lily-parser.hh"
28 #include "context-specced-music.hh"
29 #include "score.hh"
30 #include "music-list.hh"
31 #include "output-property-music-iterator.hh"
32 #include "property-iterator.hh"
33 #include "file-results.hh"
34 #include "input.hh"
35 #include "scope.hh"
36 #include "relative-music.hh"
37 #include "lyric-combine-music.hh"
38 #include "transposed-music.hh"
39 #include "time-scaled-music.hh"
40 #include "repeated-music.hh"
41
42 #include "lilypond-input-version.hh"
43 #include "grace-music.hh"
44 #include "part-combine-music.hh"
45 #include "scm-hash.hh"
46 #include "auto-change-iterator.hh"
47 #include "un-relativable-music.hh"
48 #include "chord.hh"
49
50 bool
51 regular_identifier_b (SCM id)
52 {
53   String str = ly_scm2string (id);
54   char const *s = str.ch_C() ;
55
56   bool v = true;
57   while (*s && v)
58    {
59         v = v && isalpha (*s);
60         s++;
61    }
62   return v;
63 }
64
65
66 Music* 
67 set_property_music (SCM sym, SCM value)
68 {
69         Music * p = new Music (SCM_EOL);
70         p->set_mus_property ("symbol", sym);
71         p->set_mus_property ("iterator-ctor",
72         Property_iterator::constructor_cxx_function);
73
74         p->set_mus_property ("value", value);
75         return p;
76 }
77
78 bool
79 is_duration_b (int t)
80 {
81   return t && t == 1 << intlog2 (t);
82 }
83
84 void
85 set_music_properties (Music *p, SCM a)
86 {
87   for (SCM k = a; gh_pair_p (k); k = gh_cdr (k))
88         {
89         p->set_mus_property (gh_caar (k), gh_cdar (k));
90         }
91 }
92
93
94
95
96
97
98
99 // needed for bison.simple's malloc () and free ()
100 #include <malloc.h>
101
102 #ifndef NDEBUG
103 #define YYDEBUG 1
104 #endif
105
106 #define YYERROR_VERBOSE 1
107
108 #define YYPARSE_PARAM my_lily_parser_l
109 #define YYLEX_PARAM my_lily_parser_l
110 #define THIS\
111         ((My_lily_parser *) my_lily_parser_l)
112
113 #define yyerror THIS->parser_error
114 #define ARRAY_SIZE(a,s)   if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
115
116 %}
117
118
119 %union {
120
121     Link_array<Request> *reqvec;
122
123     String *string; // needed by the lexer as temporary scratch area.
124     Music *music;
125     Score *score;
126     Scope *scope;
127     Scheme_hash_table *scmhash;
128     Music_output_def * outputdef;
129
130     Request * request;
131
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. */
135
136     SCM scm;
137
138     Tempo_req *tempo;
139     int i;
140 }
141 %{
142
143 int
144 yylex (YYSTYPE *s,  void * v_l)
145 {
146         My_lily_parser   *pars_l = (My_lily_parser*) v_l;
147         My_lily_lexer * lex_l = pars_l->lexer_p_;
148
149         lex_l->lexval_l = (void*) s;
150         return lex_l->yylex ();
151 }
152
153
154 %}
155
156 %pure_parser
157
158 /* tokens which are not keywords */
159 %token AUTOCHANGE
160 %token ALIAS
161 %token APPLY
162 %token ARPEGGIO
163 %token DYNAMICSCRIPT
164 %token ACCEPTS
165 %token ALTERNATIVE
166 %token BAR
167 %token BREATHE
168 %token CHORDMODIFIERS
169 %token CHORDS
170 %token CHAR_T
171 %token CLEF
172 %token CM_T
173 %token CONSISTS
174 %token DURATION
175 %token SEQUENTIAL
176 %token ELEMENTDESCRIPTIONS
177 %token SIMULTANEOUS
178 %token CONSISTSEND
179 %token DENIES
180 %token DURATION
181 %token EXTENDER
182 %token FONT
183 %token GLISSANDO
184 %token GRACE
185 %token HEADER
186 %token HYPHEN
187 %token IN_T
188 %token INVALID
189 %token KEY
190 %token LYRICS
191 %token MARK
192 %token MULTI_MEASURE_REST
193 %token MIDI
194 %token MM_T
195 %token PITCH
196 %token DEFAULT
197 %token NAME
198 %token PITCHNAMES
199 %token NOTES
200 %token PAPER
201 %token PARTIAL
202 %token PENALTY
203 %token PROPERTY
204 %token OVERRIDE SET REVERT 
205 %token PT_T
206 %token RELATIVE
207 %token REMOVE
208 %token REPEAT
209 %token ADDLYRICS
210 %token PARTCOMBINE
211 %token SCM_T
212 %token SCORE
213 %token SCRIPT
214 %token SKIP
215 %token SPANREQUEST
216 %token STYLESHEET
217 %token COMMANDSPANREQUEST
218 %token TEMPO
219 %token OUTPUTPROPERTY
220 %token TIME_T
221 %token TIMES
222 %token TRANSLATOR
223 %token TRANSPOSE
224 %token TYPE
225 %token UNSET
226 %token CONTEXT
227
228 /* escaped */
229 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
230 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET 
231
232 %type <i>       exclamations questions dots
233 %token <i>      DIGIT
234 %token <scm>    NOTENAME_PITCH
235 %token <scm>    TONICNAME_PITCH
236 %token <scm>    CHORDMODIFIER_PITCH
237 %token <scm>    DURATION_IDENTIFIER
238 %token <scm>    FRACTION
239 %token <id>     IDENTIFIER
240
241
242 %token <scm>    SCORE_IDENTIFIER
243 %token <scm>    MUSIC_OUTPUT_DEF_IDENTIFIER
244
245 %token <scm>    NUMBER_IDENTIFIER
246 %token <scm>    REQUEST_IDENTIFIER
247 %token <scm>    MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
248 %token <scm>    STRING_IDENTIFIER SCM_IDENTIFIER 
249 %token <scm>    RESTNAME
250 %token <scm>    STRING   
251 %token <scm>    SCM_T
252 %token <i>      UNSIGNED
253 %token <scm>   REAL
254
255 %type <outputdef> output_def
256 %type <scmhash>         lilypond_header lilypond_header_body
257 %type <request> open_request_parens close_request_parens open_request close_request
258 %type <request> request_with_dir request_that_take_dir verbose_request
259 %type <i>       sub_quotes sup_quotes
260 %type <music>   simple_element  request_chord command_element Simple_music  Composite_music 
261 %type <music>   Alternative_music Repeated_music
262 %type <i>       tremolo_type
263 %type <i>       bare_int  bare_unsigned
264 %type <i>       script_dir
265
266 %type <scm>     identifier_init 
267
268 %type <scm> steno_duration optional_notemode_duration multiplied_duration
269 %type <scm>  explicit_duration
270         
271 %type <reqvec>  pre_requests post_requests
272 %type <request> gen_text_def
273 %type <scm>   steno_pitch pitch absolute_pitch
274 %type <scm>   explicit_pitch steno_tonic_pitch
275
276 %type <scm>     chord_additions chord_subtractions chord_notes chord_step
277 %type <music>   chord
278 %type <scm>     chord_note chord_inversion chord_bass
279 %type <scm>     duration_length fraction
280
281 %type <scm>  embedded_scm scalar
282 %type <music>   Music Sequential_music Simultaneous_music Music_sequence
283 %type <music>   relative_music re_rhythmed_music part_combined_music
284 %type <music>   property_def translator_change
285 %type <scm> Music_list
286 %type <outputdef>  music_output_def_body
287 %type <request> shorthand_command_req
288 %type <request> post_request 
289 %type <music> command_req verbose_command_req
290 %type <request> extender_req
291 %type <request> hyphen_req
292 %type <scm>     string bare_number number_expression number_term number_factor 
293
294 %type <score>   score_block score_body
295
296 %type <scm>     translator_spec_block translator_spec_body
297 %type <tempo>   tempo_request
298 %type <scm> notenames_body notenames_block chordmodifiers_block
299 %type <scm>     script_abbreviation
300
301
302
303 %left '-' '+'
304
305 /* We don't assign precedence to / and *, because we might need varied
306 prec levels in different prods */
307
308 %left UNARY_MINUS
309
310 %%
311
312 lilypond:       /* empty */
313         | lilypond toplevel_expression {}
314         | lilypond assignment  { }
315         | lilypond error {
316                 THIS->error_level_i_  = 1;
317         }
318         | lilypond INVALID      {
319                 THIS->error_level_i_  = 1;
320         }
321         ;
322
323 toplevel_expression:
324         notenames_block                 {
325                 THIS->lexer_p_->pitchname_tab_ =  $1;
326         }
327         | chordmodifiers_block                  {
328                 THIS->lexer_p_->chordmodifier_tab_  = $1;
329         }
330         | lilypond_header {
331                 if (global_header_p)
332                         scm_unprotect_object (global_header_p->self_scm ());
333                 global_header_p = $1;
334         }
335         | score_block {
336                 score_global_array.push ($1);
337         }
338         | output_def {
339                 if (dynamic_cast<Paper_def*> ($1))
340                         THIS->lexer_p_->set_identifier ("$defaultpaper", $1->self_scm ());
341                 else if (dynamic_cast<Midi_def*> ($1))
342                         THIS->lexer_p_->set_identifier ("$defaultmidi", $1->self_scm ());
343         }
344         | embedded_scm {
345                 // junk value
346         }       
347         ;
348
349 embedded_scm:
350         SCM_T
351         | SCM_IDENTIFIER 
352         ;
353
354
355 chordmodifiers_block:
356         CHORDMODIFIERS notenames_body   {  $$ = $2; }
357         ;
358
359 notenames_block:
360         PITCHNAMES notenames_body   {  $$ = $2; }
361         ;
362
363 notenames_body:
364         embedded_scm    {
365           int i = scm_ilength ($1);
366
367           SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
368           for (SCM s = $1; gh_pair_p (s); s = gh_cdr (s)) {
369                 SCM pt = gh_cdar (s);
370                 if (!unsmob_pitch (pt))
371                         THIS->parser_error ("Need pitch object.");
372                 else
373                         scm_hashq_set_x (tab, gh_caar (s), pt);
374           }
375
376           $$ = tab;
377         }
378         ;
379
380 lilypond_header_body:
381         {
382                 $$ = new Scheme_hash_table;
383                 
384                 Scope *sc = new Scope ($$);
385                 THIS->lexer_p_-> scope_l_arr_.push (sc);
386         }
387         | lilypond_header_body assignment  { 
388
389         }
390         ;
391
392 lilypond_header:
393         HEADER '{' lilypond_header_body '}'     {
394                 $$ = $3;
395                 delete THIS->lexer_p_-> scope_l_arr_.pop ();
396         }
397         ;
398
399
400 /*
401         DECLARATIONS
402 */
403 assignment:
404         STRING {
405                 THIS->remember_spot ();
406         }
407         /* cont */ '=' identifier_init  {
408
409         /*
410                 Should find generic way of associating input with objects.
411         */
412                 Input ip = THIS->pop_spot ();
413
414                 if (! regular_identifier_b ($1))
415                 {
416                         ip.warning (_ ("Identifier should have  alphabetic characters only"));
417                 }
418
419                 THIS->lexer_p_->set_identifier (ly_scm2string ($1), $4);
420
421 /*
422  TODO: devise standard for protection in parser.
423
424   The parser stack lives on the C-stack, which means that
425 all objects can be unprotected as soon as they're here.
426
427 */
428         }
429         ;
430
431
432
433 identifier_init:
434         score_block {
435                 $$ = $1->self_scm ();
436                 scm_unprotect_object ($$);
437         }
438         | output_def {
439                 $$ = $1->self_scm ();
440                 scm_unprotect_object ($$);
441         }
442         | translator_spec_block {
443                 $$ = $1;
444         }
445         | Music  {
446                 $$ = $1->self_scm ();
447                 scm_unprotect_object ($$);
448         }
449         | post_request {
450                 $$ = $1->self_scm ();
451                 scm_unprotect_object ($$);
452         }
453         | explicit_duration {
454                 $$ = $1;
455         }
456         | number_expression {
457                 $$ = $1;
458         }
459         | string {
460                 $$ = $1;
461         }
462         | embedded_scm  {
463                 $$ = $1;
464         }
465         ;
466
467 translator_spec_block:
468         TRANSLATOR '{' translator_spec_body '}'
469                 {
470                 $$ = $3;
471         }
472         ;
473
474 translator_spec_body:
475         TRANSLATOR_IDENTIFIER   {
476                 $$ = unsmob_translator_def ($1)->clone_scm ();
477                 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
478         }
479         | TYPE STRING   {
480                 $$ = Translator_def::make_scm ();
481                 Translator_def*td =  unsmob_translator_def ($$);
482                 td->translator_group_type_ = $2;
483                 td->set_spot (THIS->here_input ());
484         }
485         | translator_spec_body STRING '=' embedded_scm                  {
486                 unsmob_translator_def ($$)->add_property_assign ($2, $4);
487         }
488         | translator_spec_body STRING OVERRIDE embedded_scm '=' embedded_scm {
489                 unsmob_translator_def ($$)
490                         ->add_push_property (scm_string_to_symbol ($2), $4, $6);
491         }
492         | translator_spec_body STRING REVERT embedded_scm  {
493           unsmob_translator_def ($$)->add_pop_property (
494                 scm_string_to_symbol ($2), $4);
495         }
496         | translator_spec_body NAME STRING  {
497                 unsmob_translator_def ($$)->type_name_ = $3;
498         }
499         | translator_spec_body CONSISTS STRING  {
500                 unsmob_translator_def ($$)->add_element ($3);
501         }
502         | translator_spec_body ALIAS STRING  {
503                 Translator_def*td = unsmob_translator_def ($$);
504                 td->type_aliases_ = gh_cons ($3, td->type_aliases_);
505         }
506         | translator_spec_body ELEMENTDESCRIPTIONS embedded_scm {
507                 for (SCM p = $3; gh_pair_p (p); p = gh_cdr (p))
508                         unsmob_translator_def ($$)
509                         ->add_property_assign (scm_symbol_to_string (gh_caar (p)), gh_cdar (p));
510
511         }
512         | translator_spec_body CONSISTSEND STRING  {
513                 unsmob_translator_def ($$)->add_last_element ( $3);
514         }
515         | translator_spec_body ACCEPTS STRING  {
516                 unsmob_translator_def ($$)->set_acceptor ($3,true);
517         }
518         | translator_spec_body DENIES STRING  {
519                 unsmob_translator_def ($$)->set_acceptor ($3,false);
520         }
521         | translator_spec_body REMOVE STRING  {
522                 unsmob_translator_def ($$)->remove_element ($3);
523         }
524         ;
525
526 /*
527         SCORE
528 */
529 score_block:
530         SCORE { 
531                 THIS->remember_spot ();
532         }
533         /*cont*/ '{' score_body '}'     {
534                 THIS->pop_spot ();
535                 $$ = $4;
536                 if (!$$->def_p_arr_.size ())
537                 {
538                   Music_output_def *id =
539                         unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
540                   $$->add_output (id ? id->clone () :  new Paper_def );
541                 }
542         }
543         ;
544
545 score_body:
546         Music   {
547                 $$ = new Score;
548         
549                 $$->set_spot (THIS->here_input ());
550                 SCM m = $1->self_scm ();
551                 scm_unprotect_object (m);
552                 $$->music_ = m;
553         }
554         | SCORE_IDENTIFIER {
555                 $$ = new Score (*unsmob_score ($1));
556                 $$->set_spot (THIS->here_input ());
557         }
558         | score_body lilypond_header    {
559                 scm_unprotect_object ($2->self_scm ()); 
560                 $$->header_p_ = $2;
561         }
562         | score_body output_def {
563                 $$->add_output ($2);
564         }
565         | score_body error {
566
567         }
568         ;
569
570
571 /*
572         MIDI
573 */
574 output_def:
575         music_output_def_body '}' {
576                 $$ = $1;
577                 THIS-> lexer_p_-> scope_l_arr_.pop ();
578         }
579         ;
580
581 music_output_def_body:
582         MIDI '{'    {
583            Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
584
585                 
586          Midi_def* p =0;
587         if (id)
588                 p = dynamic_cast<Midi_def*> (id->clone ());
589         else
590                 p = new Midi_def;
591
592          $$ = p;
593          THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
594         }
595         | PAPER '{'     {
596                 Music_output_def *id = unsmob_music_output_def (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
597                   Paper_def *p = 0;
598                 if (id)
599                         p = dynamic_cast<Paper_def*> (id->clone ());
600                 else
601                         p = new Paper_def;
602                 THIS-> lexer_p_-> scope_l_arr_.push (p->scope_p_);
603                 $$ = p;
604         }
605         | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER         {
606                 Music_output_def *p = unsmob_music_output_def ($3);
607                 p = p->clone ();
608                 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
609                 $$ = p;
610         }
611         | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER  {
612                 Music_output_def *p = unsmob_music_output_def ($3);
613                 p = p->clone ();
614
615                 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
616                 $$ = p;
617         }
618         | music_output_def_body assignment  {
619
620         }
621         | music_output_def_body translator_spec_block   {
622                 $$->assign_translator ($2);
623         }
624         | music_output_def_body STYLESHEET embedded_scm {
625                 dynamic_cast<Paper_def*> ($$)-> style_sheet_ = $3;
626         }
627         | music_output_def_body tempo_request  {
628                 /*
629                         junk this ? there already is tempo stuff in
630                         music.
631                 */
632                 int m = gh_scm2int ( $2->get_mus_property ("metronome-count"));
633                 Duration *d = unsmob_duration ($2->get_mus_property ("duration"));
634                 dynamic_cast<Midi_def*> ($$)->set_tempo (d->length_mom (), m);
635         }
636         | music_output_def_body error {
637
638         }
639         ;
640
641 tempo_request:
642         TEMPO steno_duration '=' bare_unsigned  {
643                 $$ = new Tempo_req;
644                 $$->set_mus_property ("duration", $2);
645                 $$->set_mus_property ("metronome-count", gh_int2scm ( $4));
646         }
647         ;
648
649 Music_list: /* empty */ {
650                 $$ = gh_cons (SCM_EOL, SCM_EOL);
651         }
652         | Music_list Music {
653                 SCM s = $$;
654                 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
655                 scm_unprotect_object ($2->self_scm ()); /* UGH */
656                 if (gh_pair_p (gh_cdr (s)))
657                         gh_set_cdr_x (gh_cdr (s), c); /* append */
658                 else
659                         gh_set_car_x (s, c); /* set first cons */
660                 gh_set_cdr_x (s, c) ;  /* remember last cell */ 
661         }
662         | Music_list error {
663         }
664         ;
665
666
667 Music:
668         Simple_music
669         | Composite_music
670         ;
671
672 Alternative_music:
673         /* empty */ {
674                 $$ = 0;
675         }
676         | ALTERNATIVE Music_sequence {
677                 $$ = $2;
678                 $2->set_spot (THIS->here_input ());
679         }
680         ;
681
682
683
684
685 Repeated_music:
686         REPEAT string bare_unsigned Music Alternative_music
687         {
688                 Music_sequence* alts = dynamic_cast <Music_sequence*> ($5);
689                 if (alts && $3 < alts->length_i ())
690                         $5->origin ()->warning (_ ("More alternatives than repeats.  Junking excess alternatives."));
691                 Music *beg = $4;
692                 int times = $3;
693
694                 Repeated_music * r = new Repeated_music (SCM_EOL);
695
696                 if (beg)
697                         {
698                         r-> set_mus_property ("body", beg->self_scm ());
699                         scm_unprotect_object (beg->self_scm ());
700                         }
701                 r->set_mus_property ("repeat-count", gh_int2scm (times >? 1));
702
703                 if (alts)
704                         {
705                         alts->truncate (times);
706                         r-> set_mus_property ("alternatives", alts->self_scm ());
707                         scm_unprotect_object (alts->self_scm ());  
708                         }
709                 SCM func = scm_eval2 (ly_symbol2scm ("repeat-name-to-ctor"), SCM_EOL);
710                 SCM result = gh_call1 (func, $2);
711
712                 set_music_properties (r, result);
713
714                 r->set_spot (*$4->origin ());
715                 $$ = r;
716         }
717         ;
718
719 Music_sequence: '{' Music_list '}'      {
720                 $$ = new Music_sequence (SCM_EOL);
721                 $$->set_mus_property ("elements", gh_car ($2));
722         }
723         ;
724
725 Sequential_music:
726         SEQUENTIAL '{' Music_list '}'           {
727                 $$ = new Sequential_music (SCM_EOL);
728                 $$->set_mus_property ("elements", gh_car ($3));
729         }
730         | '{' Music_list '}'            {
731                 $$ = new Sequential_music (SCM_EOL);
732                 $$->set_mus_property ("elements", gh_car ($2));
733         }
734         ;
735
736 Simultaneous_music:
737         SIMULTANEOUS '{' Music_list '}'{
738                 $$ = new Simultaneous_music (SCM_EOL);
739                 $$->set_mus_property ("elements", gh_car ($3));
740
741         }
742         | '<' Music_list '>'    {
743                 $$ = new Simultaneous_music (SCM_EOL);
744                 $$->set_mus_property ("elements", gh_car ($2));
745         }
746         ;
747
748 Simple_music:
749         request_chord           { $$ = $1; }
750         | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm     {
751                 SCM pred = $2;
752                 if (!gh_symbol_p ($3))
753                 {
754                         THIS->parser_error (_ ("Second argument must be a symbol")); 
755                 }
756                 /*hould check # args */
757                 if (!gh_procedure_p (pred))
758                 {
759                         THIS->parser_error (_ ("First argument must be a procedure taking 1 argument"));
760                 }
761
762                 Music *m = new Music (SCM_EOL);
763                 m->set_mus_property ("predicate", pred);
764                 m->set_mus_property ("grob-property", $3);
765                 m->set_mus_property ("grob-value",  $5);
766                 m->set_mus_property ("iterator-ctor",
767                 Output_property_music_iterator::constructor_cxx_function);
768
769                 $$ = m;
770         }
771         | MUSIC_IDENTIFIER {
772                 $$ = unsmob_music ($1)->clone ();
773         }
774         | property_def
775         | translator_change
776         ;
777
778
779 Composite_music:
780         CONTEXT STRING Music    {
781                 Context_specced_music *csm =  new Context_specced_music (SCM_EOL);
782                 csm->set_mus_property ("element", $3->self_scm ());
783                 scm_unprotect_object ($3->self_scm ());
784
785                 csm->set_mus_property ("context-type",$2);
786                 csm->set_mus_property ("context-id", ly_str02scm (""));
787
788                 $$ = csm;
789         }
790         | AUTOCHANGE STRING Music       {
791                 Music * chm = new Music_wrapper (SCM_EOL);
792                 chm->set_mus_property ("element", $3->self_scm ());
793                 chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_cxx_function);
794
795                 scm_unprotect_object ($3->self_scm ());
796                 chm->set_mus_property ("what", $2); 
797
798                 $$ = chm;
799                 chm->set_spot (*$3->origin ());
800         }
801         | GRACE Music {
802                 $$ = new Grace_music (SCM_EOL);
803                 $$->set_mus_property ("element", $2->self_scm ());
804                 scm_unprotect_object ($2->self_scm ());
805
806         }
807         | CONTEXT string '=' string Music {
808                 Context_specced_music *csm =  new Context_specced_music (SCM_EOL);
809                 csm->set_mus_property ("element", $5->self_scm ());
810                 scm_unprotect_object ($5->self_scm ());
811
812                 csm->set_mus_property ("context-type", $2);
813                 csm->set_mus_property ("context-id", $4);
814
815                 $$ = csm;
816         }
817         | TIMES {
818                 THIS->remember_spot ();
819         }
820         /* CONTINUED */ 
821                 fraction Music  
822
823         {
824                 int n = gh_scm2int (gh_car ($3)); int d = gh_scm2int (gh_cdr ($3));
825                 Music *mp = $4;
826                 $$ = new Time_scaled_music (SCM_EOL);
827                 $$->set_spot (THIS->pop_spot ());
828
829
830                 $$->set_mus_property ("element", mp->self_scm ());
831                 scm_unprotect_object (mp->self_scm ());
832                 $$->set_mus_property ("numerator", gh_int2scm (n));
833                 $$->set_mus_property ("denominator", gh_int2scm (d));
834                 $$->compress (Moment (n,d));
835
836         }
837         | Repeated_music                { $$ = $1; }
838         | Simultaneous_music            { $$ = $1; }
839         | Sequential_music              { $$ = $1; }
840         | TRANSPOSE pitch Music {
841                 $$ = new Transposed_music (SCM_EOL);
842                 Music *p = $3;
843                 Pitch pit = *unsmob_pitch ($2);
844
845                 p->transpose (pit);
846                 $$->set_mus_property ("element", p->self_scm ());
847                 scm_unprotect_object (p->self_scm ());
848         }
849         | TRANSPOSE steno_tonic_pitch Music {
850                 $$ = new Transposed_music (SCM_EOL);
851                 Music *p = $3;
852                 Pitch pit = *unsmob_pitch ($2);
853
854                 p->transpose (pit);
855                 $$->set_mus_property ("element", p->self_scm ());
856                 scm_unprotect_object (p->self_scm ());
857         
858         }
859         | APPLY embedded_scm Music  {
860                 SCM ret = gh_call1 ($2, $3->self_scm ());
861                 Music *m = unsmob_music (ret);
862                 if (!m) {
863                         THIS->parser_error ("\\apply must return a Music");
864                         m = new Music (SCM_EOL);
865                         }
866                 $$ = m;
867         }
868         | NOTES
869                 { THIS->lexer_p_->push_note_state (); }
870         Music
871                 { $$ = $3;
872                   THIS->lexer_p_->pop_state ();
873                 }
874         | CHORDS
875                 { THIS->lexer_p_->push_chord_state (); }
876         Music
877                 {
878                   Music * chm = new Un_relativable_music ;
879                   chm->set_mus_property ("element", $3->self_scm ());
880                   $$ = chm;
881
882                   THIS->lexer_p_->pop_state ();
883         }
884         | LYRICS
885                 { THIS->lexer_p_->push_lyric_state (); }
886         Music
887                 {
888                   $$ = $3;
889                   THIS->lexer_p_->pop_state ();
890         }
891         | relative_music        { $$ = $1; }
892         | re_rhythmed_music     { $$ = $1; } 
893         | part_combined_music   { $$ = $1; } 
894         ;
895
896 relative_music:
897         RELATIVE absolute_pitch Music {
898                 Music * p = $3;
899                 Pitch pit = *unsmob_pitch ($2);
900                 $$ = new Relative_octave_music (SCM_EOL);
901
902                 $$->set_mus_property ("element", p->self_scm ());
903                 scm_unprotect_object (p->self_scm ());
904
905                 $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ());
906
907         }
908         ;
909
910 re_rhythmed_music:
911         ADDLYRICS Music Music {
912           Lyric_combine_music * l = new Lyric_combine_music (SCM_EOL);
913           l->set_mus_property ("music", $2->self_scm ());
914           l->set_mus_property ("lyrics", $3->self_scm ());
915           scm_unprotect_object ($3->self_scm ());
916           scm_unprotect_object ($2->self_scm ());
917           $$ = l;
918         }
919         ;
920
921 part_combined_music:
922         PARTCOMBINE STRING Music Music {
923                 Part_combine_music * p = new Part_combine_music (SCM_EOL);
924
925                 p->set_mus_property ("what", $2);
926                 p->set_mus_property ("one", $3->self_scm ());
927                 p->set_mus_property ("two", $4->self_scm ());  
928
929                 scm_unprotect_object ($3->self_scm ());
930                 scm_unprotect_object ($4->self_scm ());  
931
932
933                 $$ = p;
934         }
935         ;
936
937 translator_change:
938         TRANSLATOR STRING '=' STRING  {
939                 Music * t = new Music (SCM_EOL);
940                 t->set_mus_property ("iterator-ctor",
941                         Change_iterator::constructor_cxx_function);
942                 t-> set_mus_property ("change-to-type", $2);
943                 t-> set_mus_property ("change-to-id", $4);
944
945                 $$ = t;
946                 $$->set_spot (THIS->here_input ());
947         }
948         ;
949
950 property_def:
951         PROPERTY STRING '.' STRING '='  scalar {
952                 
953                 Music *t = set_property_music (scm_string_to_symbol ($4), $6);
954                 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
955
956                 csm->set_mus_property ("element", t->self_scm ());
957                 scm_unprotect_object (t->self_scm ());
958
959                 $$ = csm;
960                 $$->set_spot (THIS->here_input ());
961
962                 csm-> set_mus_property ("context-type", $2);
963         }
964         | PROPERTY STRING '.' STRING UNSET {
965                 Music *t = new Music (SCM_EOL);
966
967                 t->set_mus_property ("iterator-ctor",
968                         Property_unset_iterator::constructor_cxx_function);
969                 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
970
971                 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
972                 csm->set_mus_property ("element", t->self_scm ());
973                 scm_unprotect_object (t->self_scm ());
974
975                 $$ = csm;
976                 $$->set_spot (THIS->here_input ());
977
978                 csm-> set_mus_property ("context-type", $2);
979         }
980         | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm {
981                 Music *t = new Music (SCM_EOL);
982                 t->set_mus_property ("iterator-ctor",
983                         Push_property_iterator::constructor_cxx_function);
984                 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
985                 t->set_mus_property ("pop-first", SCM_BOOL_T);
986                 t->set_mus_property ("grob-property", $6);
987                 t->set_mus_property ("grob-value", $8);
988                 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
989                 csm->set_mus_property ("element", t->self_scm ());
990                 scm_unprotect_object (t->self_scm ());
991                 $$ = csm;
992                 $$->set_spot (THIS->here_input ());
993
994                 csm-> set_mus_property ("context-type", $2);
995         }
996         | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm {
997                 Music *t = new Music (SCM_EOL);
998                 t->set_mus_property ("iterator-ctor",
999                         Push_property_iterator::constructor_cxx_function);
1000                 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1001                 t->set_mus_property ("grob-property", $6);
1002                 t->set_mus_property ("grob-value", $8);
1003                 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1004                 csm->set_mus_property ("element", t->self_scm ());
1005                 scm_unprotect_object (t->self_scm ());
1006
1007                 $$ = csm;
1008                 $$->set_spot (THIS->here_input ());
1009
1010                 csm-> set_mus_property ("context-type", $2);
1011         }
1012         | PROPERTY STRING '.' STRING REVERT embedded_scm {
1013                 Music *t = new Music (SCM_EOL);
1014                 t->set_mus_property ("iterator-ctor",
1015                         Pop_property_iterator::constructor_cxx_function);
1016                 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
1017                 t->set_mus_property ("grob-property", $6);
1018
1019                 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1020                 csm->set_mus_property ("element", t->self_scm ());
1021                 scm_unprotect_object (t->self_scm ());
1022
1023                 $$ = csm;
1024                 $$->set_spot (THIS->here_input ());
1025
1026                 csm-> set_mus_property ("context-type", $2);
1027         }
1028         ;
1029
1030 scalar:
1031         string          { $$ = $1; }
1032         | bare_int      { $$ = gh_int2scm ($1); }
1033         | embedded_scm  { $$ = $1; }
1034         ;
1035
1036
1037 request_chord:
1038         pre_requests simple_element post_requests       {
1039                 Music_sequence *l = dynamic_cast<Music_sequence*> ($2);
1040                 if (l) {
1041                         for (int i=0; i < $1->size (); i++)
1042                                 l->append_music ($1->elem (i));
1043                         for (int i=0; i < $3->size (); i++)
1044                                 l->append_music ($3->elem (i));
1045                         }
1046                 else
1047                         programming_error ("Need Sequence to add music to");
1048                 $$ = $2;
1049                 
1050         }
1051         | command_element
1052         ;
1053
1054 command_element:
1055         command_req {
1056                 $$ = new Request_chord (SCM_EOL);
1057                 $$->set_mus_property ("elements", gh_cons ($1->self_scm (), SCM_EOL));
1058                 $$-> set_spot (THIS->here_input ());
1059                 $1-> set_spot (THIS->here_input ());
1060         }
1061         | BAR STRING                    {
1062                 Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
1063
1064                 Context_specced_music *csm = new Context_specced_music (SCM_EOL);
1065                 csm->set_mus_property ("element", t->self_scm ());
1066                 scm_unprotect_object (t->self_scm ());
1067
1068                 $$ = csm;
1069                 $$->set_spot (THIS->here_input ());
1070
1071                 csm->set_mus_property ("context-type", ly_str02scm ("Score"));
1072         }
1073         | PARTIAL duration_length       {
1074                 Moment m = - unsmob_duration ($2)->length_mom ();
1075                 Music * p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ());
1076
1077                 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1078                 sp->set_mus_property ("element", p->self_scm ());
1079                 scm_unprotect_object (p->self_scm ());
1080
1081                 $$ =sp ;
1082                 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1083         }
1084         | CLEF STRING  {
1085                 SCM func = scm_eval2 (ly_symbol2scm ("clef-name-to-properties"), SCM_EOL);
1086                 SCM result = gh_call1 (func, $2);
1087
1088                 SCM l = SCM_EOL;
1089                 for (SCM s = result ; gh_pair_p (s); s = gh_cdr (s)) {
1090                         Music * p = new Music (SCM_EOL);
1091                         set_music_properties (p, gh_car (s));
1092                         l = gh_cons (p->self_scm (), l);
1093                         scm_unprotect_object (p->self_scm ());
1094                 }
1095                 Sequential_music * seq = new Sequential_music (SCM_EOL);
1096                 seq->set_mus_property ("elements", l);
1097
1098                 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1099                 sp->set_mus_property ("element", seq->self_scm ());
1100                 scm_unprotect_object (seq->self_scm ());
1101
1102                 $$ =sp ;
1103                 sp-> set_mus_property ("context-type", ly_str02scm ("Staff"));
1104         }
1105         | TIME_T fraction  {
1106                 Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2);
1107
1108   int l = gh_scm2int (gh_car ($2));
1109   int o = gh_scm2int (gh_cdr ($2));
1110   
1111   Moment one_beat = Moment (1)/Moment (o);
1112   Moment len = Moment (l) * one_beat;
1113
1114
1115                 Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ());
1116                 Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ());
1117
1118                 SCM list = gh_list (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED);
1119                 Sequential_music *seq = new Sequential_music (SCM_EOL);
1120                 seq->set_mus_property ("elements", list);
1121                 
1122
1123                 Context_specced_music * sp = new Context_specced_music (SCM_EOL);
1124                 sp->set_mus_property ("element", seq->self_scm ());
1125
1126                 
1127
1128                 scm_unprotect_object (p3->self_scm ());
1129                 scm_unprotect_object (p2->self_scm ());
1130                 scm_unprotect_object (p1->self_scm ());
1131                 scm_unprotect_object (seq->self_scm ());
1132
1133                 $$ = sp;
1134
1135 /*
1136  TODO: should make alias TimingContext for Score
1137 */
1138
1139                 sp-> set_mus_property ("context-type", ly_str02scm ( "Score"));
1140         }
1141         ;
1142
1143 command_req:
1144         shorthand_command_req   { $$ = $1; }
1145         | verbose_command_req   { $$ = $1; }
1146         ;
1147
1148 shorthand_command_req:
1149         extender_req {
1150                 $$ = $1;
1151         }
1152         | hyphen_req {
1153                 $$ = $1;
1154         }
1155         | '|'                           {
1156                 $$ = new Barcheck_req;
1157         }
1158         | '~'   {
1159                 $$ = new Tie_req;
1160         }
1161         | '['           {
1162                 Span_req*b= new Span_req;
1163                 b->set_span_dir (START);
1164                 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1165                 $$ =b;
1166         }
1167         | ']'           {
1168                 Span_req*b= new Span_req;
1169                 b->set_span_dir ( STOP);
1170                 b->set_mus_property ("span-type", ly_str02scm ("beam"));
1171                 $$ = b;
1172         }
1173         | BREATHE {
1174                 $$ = new Breathing_sign_req;
1175         }
1176         ;
1177
1178
1179 verbose_command_req:
1180         COMMANDSPANREQUEST bare_int STRING { /*TODO: junkme */
1181                 Span_req * sp_p = new Span_req;
1182                 sp_p-> set_span_dir ( Direction ($2));
1183                 sp_p->set_mus_property ("span-type",$3);
1184                 sp_p->set_spot (THIS->here_input ());
1185                 $$ = sp_p;
1186         }
1187         | MARK DEFAULT  {
1188                 Mark_req * m = new Mark_req;
1189                 $$ = m;
1190         }
1191         | MARK scalar {
1192                 Mark_req *m = new Mark_req;
1193                 m->set_mus_property ("label", $2);
1194                 $$ = m;
1195
1196         }
1197         | PENALTY SCM_T         {
1198
1199                 
1200                 Break_req * b = new Break_req;
1201                 SCM s = $2;
1202                 if (!gh_number_p (s))
1203                         s  =gh_int2scm (0);
1204
1205                 b->set_mus_property ("penalty", s);
1206                 b->set_spot (THIS->here_input ());
1207                 $$ = b;
1208         }
1209         | SKIP duration_length {
1210                 Skip_req * skip_p = new Skip_req;
1211                 skip_p->set_mus_property ("duration", $2);
1212
1213                 $$ = skip_p;
1214         }
1215         | tempo_request {
1216                 $$ = $1;
1217         }
1218         | KEY DEFAULT {
1219                 Key_change_req *key_p= new Key_change_req;
1220                 $$ = key_p;
1221         }
1222         | KEY NOTENAME_PITCH SCM_IDENTIFIER     {
1223                 Key_change_req *key_p= new Key_change_req;
1224                 
1225                 key_p->set_mus_property ("pitch-alist", $3);
1226  ((Music* )key_p)->transpose (* unsmob_pitch ($2));
1227                 $$ = key_p; 
1228         }
1229         ;
1230
1231 post_requests:
1232         {
1233                 $$ = new Link_array<Request>;
1234         }
1235         | post_requests post_request {
1236                 $2->set_spot (THIS->here_input ());
1237                 $$->push ($2);
1238         }
1239         ;
1240
1241 post_request:
1242         verbose_request
1243         | request_with_dir
1244         | close_request
1245         ;
1246
1247
1248 request_that_take_dir:
1249         gen_text_def
1250         | verbose_request
1251         | script_abbreviation {
1252                 SCM s = THIS->lexer_p_->lookup_identifier ("dash" + ly_scm2string ($1));
1253                 Articulation_req *a = new Articulation_req;
1254                 if (gh_string_p (s))
1255                         a->set_mus_property ("articulation-type", s);
1256                 else THIS->parser_error (_ ("Expecting string as script definition"));
1257                 $$ = a;
1258         }
1259         ;
1260
1261 request_with_dir:
1262         script_dir request_that_take_dir        {
1263                 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1264                         gs->set_direction (Direction ($1));
1265                 else if ($1)
1266                         $2->origin ()->warning (_ ("Can't specify direction for this request"));
1267                 $$ = $2;
1268         }
1269         ;
1270         
1271 verbose_request:
1272         REQUEST_IDENTIFIER      {
1273                 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1274                 $$->set_spot (THIS->here_input ());
1275         }
1276         | DYNAMICSCRIPT embedded_scm {
1277                 /*
1278                         TODO: junkme, use text-type == dynamic
1279                 */
1280                 Text_script_req *d = new Text_script_req;
1281                 d->set_mus_property ("text-type" , ly_symbol2scm ("dynamic"));
1282                 d->set_mus_property ("text", $2);
1283                 d->set_spot (THIS->here_input ());
1284                 $$ = d;
1285         }
1286         | SPANREQUEST bare_int STRING {
1287                 Span_req * sp_p = new Span_req;
1288                 sp_p->set_span_dir ( Direction ($2));
1289                 sp_p->set_mus_property ("span-type", $3);
1290                 sp_p->set_spot (THIS->here_input ());
1291                 $$ = sp_p;
1292         }
1293         | tremolo_type  {
1294                Tremolo_req* a = new Tremolo_req;
1295                a->set_spot (THIS->here_input ());
1296                a->set_mus_property ("tremolo-type", gh_int2scm ($1));
1297                $$ = a;
1298         }
1299         | SCRIPT STRING         { 
1300                 Articulation_req * a = new Articulation_req;
1301                 a->set_mus_property ("articulation-type", $2);
1302                 a->set_spot (THIS->here_input ());
1303                 $$ = a;
1304         }
1305         /*
1306 duh, junk this syntax from the parser, if possible. 
1307         */
1308         | ARPEGGIO {
1309                 Arpeggio_req *a = new Arpeggio_req;
1310                 a->set_spot (THIS->here_input ());
1311                 $$ = a;
1312         }
1313         | GLISSANDO {
1314                 Glissando_req *g = new Glissando_req;
1315                 g->set_spot /* No pun intended */ (THIS->here_input ());
1316                 $$ = g;
1317         }       
1318         ;
1319
1320 sup_quotes:
1321         '\'' {
1322                 $$ = 1;
1323         }
1324         | sup_quotes '\'' {
1325                 $$ ++;
1326         }
1327         ;
1328
1329 sub_quotes:
1330         ',' {
1331                 $$ = 1;
1332         }
1333         | sub_quotes ',' {
1334                 $$ ++ ;
1335         }
1336         ;
1337
1338 steno_pitch:
1339         NOTENAME_PITCH  {
1340                 $$ = $1;
1341         }
1342         | NOTENAME_PITCH sup_quotes     {
1343                 Pitch p = *unsmob_pitch ($1);
1344                 p.octave_i_ +=  $2;
1345                 $$ = p.smobbed_copy ();
1346         }
1347         | NOTENAME_PITCH sub_quotes      {
1348                 Pitch p =* unsmob_pitch ($1);
1349
1350                 p.octave_i_ +=  -$2;
1351                 $$ = p.smobbed_copy ();
1352
1353         }
1354         ;
1355
1356 /*
1357 ugh. duplication
1358 */
1359
1360 steno_tonic_pitch:
1361         TONICNAME_PITCH {
1362                 $$ = $1;
1363         }
1364         | TONICNAME_PITCH sup_quotes    {
1365                 Pitch p = *unsmob_pitch ($1);
1366                 p.octave_i_ +=  $2;
1367                 $$ = p.smobbed_copy ();
1368         }
1369         | TONICNAME_PITCH sub_quotes     {
1370                 Pitch p =* unsmob_pitch ($1);
1371
1372                 p.octave_i_ +=  -$2;
1373                 $$ = p.smobbed_copy ();
1374
1375         }
1376         ;
1377
1378 pitch:
1379         steno_pitch {
1380                 $$ = $1;
1381         }
1382         | explicit_pitch {
1383                 $$ = $1;
1384         }
1385         ;
1386
1387 explicit_pitch:
1388         PITCH embedded_scm {
1389                 $$ = $2;
1390                 if (!unsmob_pitch ($2)) {
1391                         THIS->parser_error (_f ("Expecting musical-pitch value", 3));
1392                          $$ = Pitch ().smobbed_copy ();
1393                 }
1394         }
1395         ;
1396
1397 explicit_duration:
1398         DURATION embedded_scm   {
1399                 $$ = $2;
1400                 if (!unsmob_duration ($2))
1401                 {
1402                         THIS->parser_error (_ ("Must have duration object"));
1403                         $$ = Duration ().smobbed_copy ();
1404                 }
1405         }
1406         ;
1407
1408 extender_req:
1409         EXTENDER {
1410                 if (!THIS->lexer_p_->lyric_state_b ())
1411                         THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1412                 $$ = new Extender_req;
1413         }
1414         ;
1415
1416 hyphen_req:
1417         HYPHEN {
1418                 if (!THIS->lexer_p_->lyric_state_b ())
1419                         THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1420                 $$ = new Hyphen_req;
1421         }
1422         ;
1423
1424 close_request:
1425         close_request_parens {
1426                 $$ = $1;
1427                 dynamic_cast<Span_req*> ($$)->set_span_dir ( START);
1428         }
1429         
1430 close_request_parens:
1431         '('     {
1432                 Span_req* s= new Span_req;
1433                 $$ = s;
1434                 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1435         }
1436         | E_OPEN        {
1437                 Span_req* s= new Span_req;
1438                 $$ = s;
1439                 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1440         }
1441         | E_SMALLER {
1442                 Span_req*s =new Span_req;
1443                 $$ = s;
1444                 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1445         }
1446         | E_BIGGER {
1447                 Span_req*s =new Span_req;
1448                 $$ = s;
1449                 s->set_mus_property ("span-type", ly_str02scm ("decrescendo"));
1450         }
1451         ;
1452
1453
1454 open_request:
1455         open_request_parens {
1456                 $$ = $1;
1457                 dynamic_cast<Span_req*> ($$)->set_span_dir (STOP);
1458         }
1459         ;
1460
1461 open_request_parens:
1462         E_EXCLAMATION   {
1463                 Span_req *s =  new Span_req;
1464                 s->set_mus_property ("span-type", ly_str02scm ( "crescendo"));
1465
1466                 $$ = s;
1467         }
1468         | ')'   {
1469                 Span_req* s= new Span_req;
1470                 $$ = s;
1471                 s->set_mus_property ("span-type", ly_str02scm ( "slur"));
1472         }
1473         | E_CLOSE       {
1474                 Span_req* s= new Span_req;
1475                 $$ = s;
1476                 s->set_mus_property ("span-type", ly_str02scm ( "phrasing-slur"));
1477         }
1478         ;
1479
1480 gen_text_def:
1481         embedded_scm {
1482                 Text_script_req *t = new Text_script_req;
1483                 t->set_mus_property ("text", $1);
1484                 t->set_spot (THIS->here_input ());
1485                 $$ = t;
1486         }
1487         | string {
1488                 Text_script_req *t = new Text_script_req;
1489                 t->set_mus_property ("text", $1);
1490                 t->set_spot (THIS->here_input ());
1491                 $$ = t;
1492         }
1493         | DIGIT {
1494                 String ds = to_str ($1);
1495                 Text_script_req* t = new Text_script_req;
1496
1497                 t->set_mus_property ("text",  ly_str02scm (ds.ch_C ()));
1498                 t->set_mus_property ("text-type" , ly_symbol2scm ("finger"));
1499                 t->set_spot (THIS->here_input ());
1500                 $$ = t;
1501         }
1502         ;
1503
1504 script_abbreviation:
1505         '^'             {
1506                 $$ = gh_str02scm ("Hat");
1507         }
1508         | '+'           {
1509                 $$ = gh_str02scm ("Plus");
1510         }
1511         | '-'           {
1512                 $$ = gh_str02scm ("Dash");
1513         }
1514         | '|'           {
1515                 $$ = gh_str02scm ("Bar");
1516         }
1517         | '>'           {
1518                 $$ = gh_str02scm ("Larger");
1519         }
1520         | '.'           {
1521                 $$ = gh_str02scm ("Dot");
1522         }
1523         ;
1524
1525
1526 script_dir:
1527         '_'     { $$ = DOWN; }
1528         | '^'   { $$ = UP; }
1529         | '-'   { $$ = CENTER; }
1530         ;
1531
1532 pre_requests:
1533         {
1534                 $$ = new Link_array<Request>;
1535         }
1536         | pre_requests open_request {
1537                 $$->push ($2);
1538         }
1539         ;
1540
1541 absolute_pitch:
1542         steno_pitch     {
1543                 $$ = $1;
1544         }
1545         ;
1546
1547 duration_length:
1548         multiplied_duration {
1549                 $$ = $1;
1550         }
1551         | explicit_duration {
1552                 $$ = $1;
1553         }       
1554         ;
1555
1556 optional_notemode_duration:
1557         {
1558                 $$ = THIS->default_duration_.smobbed_copy ();
1559         }
1560         | multiplied_duration   {
1561                 $$ = $1;
1562         }
1563         | explicit_duration {
1564                 $$ = $1;
1565         }       
1566         ;
1567
1568 steno_duration:
1569         bare_unsigned dots              {
1570                 int l = 0;
1571                 if (!is_duration_b ($1))
1572                         THIS->parser_error (_f ("not a duration: %d", $1));
1573                 else
1574                         l =  intlog2 ($1);
1575
1576                 $$ = Duration (l, $2).smobbed_copy ();
1577
1578                 THIS->set_last_duration (unsmob_duration ($$));
1579         }
1580         | DURATION_IDENTIFIER dots      {
1581                 Duration *d =unsmob_duration ($1);
1582                 Duration k (d->duration_log (),d->dot_count () + $2);
1583                 $$ = k.smobbed_copy ();
1584
1585                 THIS->set_last_duration (unsmob_duration ($$));
1586         }
1587         ;
1588
1589
1590
1591
1592 multiplied_duration:
1593         steno_duration {
1594                 $$ = $1;
1595         }
1596         | steno_duration '*' bare_unsigned {
1597                 $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
1598         }
1599         | steno_duration '*' FRACTION {
1600                 Moment m (gh_scm2int (gh_car ($3)), gh_scm2int (gh_cdr ($3)));
1601
1602                 $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
1603         }
1604         ;
1605
1606 fraction:
1607         FRACTION { $$ = $1; }
1608         | UNSIGNED '/' UNSIGNED {
1609                 $$ = gh_cons (gh_int2scm ($1), gh_int2scm ($3));
1610         }
1611         ;
1612
1613 dots:
1614         /* empty */     {
1615                 $$ = 0;
1616         }
1617         | dots '.' {
1618                 $$ ++;
1619         }
1620         ;
1621
1622
1623 tremolo_type: 
1624         ':'     {
1625                 $$ =0;
1626         }
1627         | ':' bare_unsigned {
1628                 if (!is_duration_b ($2))
1629                         THIS->parser_error (_f ("not a duration: %d", $2));
1630                 $$ = $2;
1631         }
1632         ;
1633
1634
1635 simple_element:
1636         pitch exclamations questions optional_notemode_duration {
1637                 if (!THIS->lexer_p_->note_state_b ())
1638                         THIS->parser_error (_ ("Have to be in Note mode for notes"));
1639
1640                 Note_req *n = new Note_req;
1641                 
1642                 n->set_mus_property ("pitch", $1);
1643                 n->set_mus_property ("duration", $4);
1644
1645                 if ($3 % 2)
1646                         n->set_mus_property ("cautionary", SCM_BOOL_T);
1647                 if ($2 % 2 || $3 % 2)
1648                         n->set_mus_property ("force-accidental", SCM_BOOL_T);
1649
1650                 Simultaneous_music*v = new Request_chord (SCM_EOL);
1651                 v->set_mus_property ("elements", gh_list (n->self_scm (), SCM_UNDEFINED));
1652                 
1653 /*
1654 FIXME: location is one off, since ptich & duration don't contain origin refs. 
1655 */
1656                 v->set_spot (THIS->here_input ());
1657                 n->set_spot (THIS->here_input ());
1658
1659                 $$ = v;
1660         }
1661         | RESTNAME optional_notemode_duration           {
1662
1663                 SCM e = SCM_UNDEFINED;
1664                   if (ly_scm2string ($1) =="s")
1665                     { /* Space */
1666                       Skip_req * skip_p = new Skip_req;
1667                       skip_p->set_mus_property ("duration" ,$2);
1668
1669                       skip_p->set_spot (THIS->here_input ());
1670                         e = skip_p->self_scm ();
1671                     }
1672                   else
1673                     {
1674                       Rest_req * rest_req_p = new Rest_req;
1675                       rest_req_p->set_mus_property ("duration", $2);
1676                       rest_req_p->set_spot (THIS->here_input ());
1677                         e = rest_req_p->self_scm ();
1678                     }
1679                   Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1680                 velt_p-> set_mus_property ("elements", gh_list (e,SCM_UNDEFINED));
1681                   velt_p->set_spot (THIS->here_input ());
1682
1683
1684                   $$ = velt_p;
1685         }
1686         | MULTI_MEASURE_REST optional_notemode_duration         {
1687                 Skip_req * sk = new Skip_req;
1688                 sk->set_mus_property ("duration", $2);
1689                 Span_req *sp1 = new Span_req;
1690                 Span_req *sp2 = new Span_req;
1691                 sp1-> set_span_dir ( START);
1692                 sp2-> set_span_dir ( STOP);
1693                 SCM r = ly_str02scm ("rest");
1694                 sp1->set_mus_property ("span-type", r);
1695                 sp2->set_mus_property ("span-type", r);
1696
1697                 Request_chord * rqc1 = new Request_chord (SCM_EOL);
1698                 rqc1->set_mus_property ("elements", gh_list (sp1->self_scm (), SCM_UNDEFINED));
1699                 Request_chord * rqc2 = new Request_chord (SCM_EOL);
1700                 rqc2->set_mus_property ("elements", gh_list (sk->self_scm (), SCM_UNDEFINED));;
1701                 Request_chord * rqc3 = new Request_chord (SCM_EOL);
1702                 rqc3->set_mus_property ("elements", gh_list (sp2->self_scm (), SCM_UNDEFINED));;
1703
1704                 SCM ms = gh_list (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1705
1706                 $$ = new Sequential_music (SCM_EOL);
1707                 $$->set_mus_property ("elements", ms);
1708         }
1709         | STRING optional_notemode_duration     {
1710
1711                 Lyric_req* lreq_p = new Lyric_req;
1712                 lreq_p->set_mus_property ("text", $1);
1713                 lreq_p->set_mus_property ("duration",$2);
1714                 lreq_p->set_spot (THIS->here_input ());
1715                 Simultaneous_music* velt_p = new Request_chord (SCM_EOL);
1716                 velt_p->set_mus_property ("elements", gh_list (lreq_p->self_scm (), SCM_UNDEFINED));
1717
1718
1719                 $$= velt_p;
1720
1721         }
1722         | chord {
1723                 if (!THIS->lexer_p_->chord_state_b ())
1724                         THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1725                 $$ = $1;
1726         }
1727         ;
1728
1729
1730 chord:
1731         steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1732                 $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
1733                 $$->set_spot (THIS->here_input ());
1734         };
1735
1736 chord_additions: 
1737         {
1738                 $$ = SCM_EOL;
1739         } 
1740         | CHORD_COLON chord_notes {
1741                 $$ = $2;
1742         }
1743         ;
1744
1745 chord_notes:
1746         chord_step {
1747                 $$ = $1
1748         }
1749         | chord_notes '.' chord_step {
1750                 $$ = gh_append2 ($$, $3);
1751         }
1752         ;
1753
1754 chord_subtractions: 
1755         {
1756                 $$ = SCM_EOL;
1757         } 
1758         | CHORD_CARET chord_notes {
1759                 $$ = $2;
1760         }
1761         ;
1762
1763
1764 chord_inversion:
1765         {
1766                 $$ = SCM_EOL;
1767         }
1768         | '/' steno_tonic_pitch {
1769                 $$ = $2;
1770         }
1771         ;
1772
1773 chord_bass:
1774         {
1775                 $$ = SCM_EOL;
1776         }
1777         | CHORD_BASS steno_tonic_pitch {
1778                 $$ = $2;
1779         }
1780         ;
1781
1782 chord_step:
1783         chord_note {
1784                 $$ = gh_cons ($1, SCM_EOL);
1785         }
1786         | CHORDMODIFIER_PITCH {
1787                 $$ = gh_cons ($1, SCM_EOL);
1788         }
1789         | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1790                 $$ = gh_list ($1, $2, SCM_UNDEFINED);
1791         }
1792         ;
1793
1794 chord_note:
1795         bare_unsigned {
1796                  Pitch m;
1797                 m.notename_i_ = ($1 - 1) % 7;
1798                 m.octave_i_ = $1 > 7 ? 1 : 0;
1799                 m.alteration_i_ = 0;
1800
1801                 $$ = m.smobbed_copy ();
1802         } 
1803         | bare_unsigned '+' {
1804                 Pitch m;
1805                 m.notename_i_ = ($1 - 1) % 7;
1806                 m.octave_i_ = $1 > 7 ? 1 : 0;
1807                 m.alteration_i_ = 1;
1808
1809
1810                 $$ = m.smobbed_copy ();
1811         }
1812         | bare_unsigned CHORD_MINUS {
1813                 Pitch m;
1814                 m.notename_i_ = ($1 - 1) % 7;
1815                 m.octave_i_ = $1 > 7 ? 1 : 0;
1816                 m.alteration_i_ = -1;
1817
1818                 $$ = m.smobbed_copy ();
1819         }
1820         ;
1821
1822 /*
1823         UTILITIES
1824  */
1825 number_expression:
1826         number_expression '+' number_term {
1827                 $$ = scm_sum ($1, $3);
1828         }
1829         | number_expression '-' number_term {
1830                 $$ = scm_difference ($1, $3);
1831         }
1832         | number_term 
1833         ;
1834
1835 number_term:
1836         number_factor {
1837                 $$ = $1;
1838         }
1839         | number_factor '*' number_factor {
1840                 $$ = scm_product ($1, $3);
1841         }
1842         | number_factor '/' number_factor {
1843                 $$ = scm_divide ($1, $3);
1844         }
1845         ;
1846
1847 number_factor:
1848         '(' number_expression ')'       {
1849                 $$ = $2;
1850         }
1851         | '-'  number_factor { /* %prec UNARY_MINUS */
1852                 $$ = scm_difference ($2, SCM_UNDEFINED);
1853         }
1854         | bare_number
1855         ;
1856
1857
1858 bare_number:
1859         UNSIGNED        {
1860                 $$ = gh_int2scm ($1);
1861         }
1862         | REAL          {
1863                 $$ = $1;
1864         }
1865         | NUMBER_IDENTIFIER             {
1866                 $$ = $1;
1867         }
1868         | REAL CM_T     {
1869                 $$ = gh_double2scm (gh_scm2double ($1) CM );
1870         }
1871         | REAL PT_T     {
1872                 $$ = gh_double2scm (gh_scm2double ($1) PT);
1873         }
1874         | REAL IN_T     {
1875                 $$ = gh_double2scm (gh_scm2double ($1) INCH);
1876         }
1877         | REAL MM_T     {
1878                 $$ = gh_double2scm (gh_scm2double ($1) MM);
1879         }
1880         | REAL CHAR_T   {
1881                 $$ = gh_double2scm (gh_scm2double ($1) CHAR);
1882         }
1883         ;
1884
1885
1886 bare_unsigned:
1887         UNSIGNED {
1888                         $$ = $1;
1889         }
1890         | DIGIT {
1891                 $$ = $1;
1892         }
1893         ;
1894
1895 bare_int:
1896         bare_number {
1897                 if (scm_integer_p ($1) == SCM_BOOL_T)
1898                 {
1899                         int k = gh_scm2int ($1);
1900                         $$ = k;
1901                 } else
1902                 {
1903                         THIS->parser_error (_ ("need integer number arg"));
1904                         $$ = 0;
1905                 }
1906         }
1907         | '-' bare_int {
1908                 $$ = -$2;
1909         }
1910         ;
1911
1912
1913 string:
1914         STRING          {
1915                 $$ = $1;
1916         }
1917         | STRING_IDENTIFIER     {
1918                 $$ = $1;
1919         }
1920         | string '+' string {
1921                 $$ = scm_string_append (scm_listify ($1, $3, SCM_UNDEFINED));
1922         }
1923         ;
1924
1925
1926 exclamations:
1927                 { $$ = 0; }
1928         | exclamations '!'      { $$ ++; }
1929         ;
1930
1931 questions:
1932                 { $$ = 0; }
1933         | questions '?' { $$ ++; }
1934         ;
1935
1936
1937 %%
1938
1939 void
1940 My_lily_parser::set_yydebug (bool b)
1941 {
1942 #ifdef YYDEBUG
1943         yydebug = b;
1944 #endif
1945 }
1946
1947 extern My_lily_parser * current_parser;
1948
1949 void
1950 My_lily_parser::do_yyparse ()
1951 {
1952
1953         current_parser = this;;
1954         yyparse ((void*)this);
1955 }
1956
1957