]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.yy
patch::: 1.3.59.uu2.jcn1
[lilypond.git] / lily / parser.yy
1 %{ // -*-Fundamental-*-
2
3 /*
4   parser.yy -- Bison/C++ parser for mudela
5
6   source file of the GNU LilyPond music typesetter
7
8   (c)  1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9            Jan Nieuwenhuizen <janneke@gnu.org>
10 */
11
12 #include <iostream.h>
13 #include "lily-guile.hh"
14 #include "translation-property.hh"
15 #include "lookup.hh"
16 #include "misc.hh"
17 #include "my-lily-lexer.hh"
18 #include "paper-def.hh"
19 #include "midi-def.hh"
20 #include "main.hh"
21 #include "file-path.hh"
22 #include "debug.hh"
23 #include "dimensions.hh"
24 #include "identifier.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 "translator-group.hh"
30 #include "score.hh"
31 #include "music-list.hh"
32 #include "change-translator.hh"
33 #include "file-results.hh"
34 #include "scope.hh"
35 #include "relative-music.hh"
36 #include "lyric-combine-music.hh"
37 #include "transposed-music.hh"
38 #include "time-scaled-music.hh"
39 #include "repeated-music.hh"
40 #include "mudela-version.hh"
41 #include "grace-music.hh"
42 #include "auto-change-music.hh"
43 #include "output-property.hh"
44
45 bool
46 is_duration_b (int t)
47 {
48   return t && t == 1 << intlog2(t);
49 }
50
51
52 // mmm JUNKME ?
53 Mudela_version oldest_version ("1.3.42");
54
55 void
56 print_mudela_versions (ostream &os)
57 {
58   os << _f ("Oldest supported input version: %s", oldest_version.str ()) 
59     << endl;
60 }
61
62
63 // needed for bison.simple's malloc() and free()
64 #include <malloc.h>
65
66 #ifndef NDEBUG
67 #define YYDEBUG 1
68 #endif
69
70 #define YYERROR_VERBOSE 1
71
72 #define YYPARSE_PARAM my_lily_parser_l
73 #define YYLEX_PARAM my_lily_parser_l
74 #define THIS ((My_lily_parser *) my_lily_parser_l)
75
76 #define yyerror THIS->parser_error
77 #define ARRAY_SIZE(a,s)   if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
78
79 %}
80
81
82 %union {
83     Array<Musical_pitch> *pitch_arr;
84     Link_array<Request> *reqvec;
85     Array<int> *intvec;
86     Duration *duration;
87     Identifier *id;
88     String * string;
89     Music *music;
90     Music_list *music_list;
91     Score *score;
92     Scope *scope;
93     Interval *interval;
94     Musical_req* musreq;
95     Music_output_def * outputdef;
96     Musical_pitch * pitch;
97     Midi_def* midi;
98     Moment *moment;
99     Paper_def *paper;
100     Real real;
101     Request * request;
102
103     /* We use SCMs to do strings, because it saves us the trouble of
104 deleting them.  Let's hope that a stack overflow doesnt trigger a move
105 of the parse stack onto the heap. */
106     SCM scm;
107
108     Tempo_req *tempo;
109     Translator_group* trans;
110     int i;
111 }
112 %{
113
114 int
115 yylex (YYSTYPE *s,  void * v_l)
116 {
117         My_lily_parser   *pars_l = (My_lily_parser*) v_l;
118         My_lily_lexer * lex_l = pars_l->lexer_p_;
119
120         lex_l->lexval_l = (void*) s;
121         return lex_l->yylex ();
122 }
123
124
125 %}
126
127 %pure_parser
128
129 /* tokens which are not keywords */
130 %token AUTOCHANGE
131 %token TEXTSCRIPT
132 %token ACCEPTS
133 %token ALTERNATIVE
134 %token BAR
135 %token BREATHE
136 %token CHORDMODIFIERS
137 %token CHORDS
138 %token CHAR_T
139 %token CLEF
140 %token CM_T
141 %token CONSISTS
142 %token SEQUENTIAL
143 %token SIMULTANEOUS
144 %token CONSISTSEND
145 %token DURATION
146 %token EXTENDER
147 %token FONT
148 %token GRACE
149 %token HEADER
150 %token HYPHEN
151 %token IN_T
152 %token INVALID
153 %token KEY
154 %token LYRICS
155 %token MARK
156 %token MEASURES
157 %token MIDI
158 %token MM_T
159 %token MUSICAL_PITCH
160 %token NAME
161 %token NOTENAMES
162 %token NOTES
163 %token PAPER
164 %token PARTIAL
165 %token PENALTY
166 %token PROPERTY
167 %token PT_T
168 %token RELATIVE
169 %token REMOVE
170 %token REPEAT
171 %token ADDLYRICS
172 %token SCM_T
173 %token SCORE
174 %token SCRIPT
175 %token SKIP
176 %token SPANREQUEST
177 %token COMMANDSPANREQUEST
178 %token TEMPO
179 %token OUTPUTPROPERTY
180 %token TIME_T
181 %token TIMES
182 %token TRANSLATOR
183 %token TRANSPOSE
184 %token TYPE
185 %token CONTEXT
186
187 /* escaped */
188 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER 
189 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET 
190
191 %type <i>       exclamations questions
192 %token <i>      DIGIT
193 %token <pitch>  NOTENAME_PITCH
194 %token <pitch>  TONICNAME_PITCH
195 %token <pitch>  CHORDMODIFIER_PITCH
196 %token <id>     DURATION_IDENTIFIER
197 %token <id>     IDENTIFIER
198 %token <id>     MUSIC_IDENTIFIER
199 %token <id>     REQUEST_IDENTIFIER
200 %token <id>     REAL_IDENTIFIER
201 %token <id>     STRING_IDENTIFIER
202 %token <id>     TRANS_IDENTIFIER
203 %token <id>     INT_IDENTIFIER
204 %token <id>     SCORE_IDENTIFIER
205 %token <id>     MIDI_IDENTIFIER
206 %token <id>     PAPER_IDENTIFIER
207 %token <real>   REAL
208 %token <scm>    DURATION RESTNAME
209 %token <scm>    STRING
210 %token <scm>    SCM_T
211 %token <i>      UNSIGNED
212
213
214 %type <outputdef> output_def
215 %type <scope>   mudela_header mudela_header_body
216 %type <request> open_request_parens close_request_parens open_request close_request
217 %type <request> request_with_dir request_that_take_dir verbose_request
218 %type <i>       sub_quotes sup_quotes
219 %type <music>   simple_element  request_chord command_element Simple_music  Composite_music 
220 %type <music>   Alternative_music Repeated_music
221 %type <i>       tremolo_type
222 %type <i>       int unsigned
223 %type <i>       script_dir
224
225 %type <id>      identifier_init  
226 %type <duration> steno_duration optional_notemode_duration
227 %type <duration> entered_notemode_duration explicit_duration
228 %type <intvec>   int_list
229 %type <reqvec>  pre_requests post_requests
230 %type <request> gen_text_def
231 %type <pitch>   steno_musical_pitch musical_pitch absolute_musical_pitch
232 %type <pitch>   steno_tonic_pitch
233
234 %type <pitch_arr>       chord_additions chord_subtractions chord_notes chord_step
235 %type <music>   chord
236 %type <pitch>   chord_note chord_inversion chord_bass
237 %type <midi>    midi_block midi_body
238 %type <duration>        duration_length
239
240 %type <scm>  embedded_scm scalar
241 %type <music>   Music Sequential_music Simultaneous_music Music_sequence
242 %type <music>   relative_music re_rhythmed_music
243 %type <music>   property_def translator_change
244 %type <music_list> Music_list
245 %type <paper>   paper_block paper_def_body
246 %type <real>    real real_with_dimension
247 %type <request> shorthand_command_req
248 %type <request> post_request 
249 %type <request> command_req verbose_command_req
250 %type <request> extender_req
251 %type <request> hyphen_req
252 %type <scm>     string
253 %type <score>   score_block score_body
254
255 %type <trans>   translator_spec_block translator_spec_body
256 %type <tempo>   tempo_request
257 %type <scm> notenames_body notenames_block chordmodifiers_block
258 %type <scm>     script_abbreviation
259
260
261
262 %left '-' '+'
263 %left '*' '/'
264 %left UNARY_MINUS
265
266 %%
267
268 mudela: /* empty */
269         | mudela toplevel_expression {}
270         | mudela assignment  { }
271         | mudela error
272         | mudela INVALID        {
273                 THIS->error_level_i_  =1;
274         }
275         ;
276
277 toplevel_expression:
278         notenames_block                 {
279                 THIS->lexer_p_->pitchname_tab_ =  $1;
280         }
281         | chordmodifiers_block                  {
282                 THIS->lexer_p_->chordmodifier_tab_  = $1;
283         }
284         | mudela_header {
285                 delete header_global_p;
286                 header_global_p = $1;
287         }
288         | score_block {
289                 score_global_array.push ($1);
290         }
291         | paper_block {
292                 Identifier * id = new
293                         Paper_def_identifier ($1, PAPER_IDENTIFIER);
294                 THIS->lexer_p_->set_identifier ("$defaultpaper", id)
295         }
296         | midi_block {
297                 Identifier * id = new
298                         Midi_def_identifier ($1, MIDI_IDENTIFIER);
299                 THIS->lexer_p_->set_identifier ("$defaultmidi", id)
300         }
301         | embedded_scm {
302                 // junk value
303         }       
304         ;
305
306 embedded_scm:
307         SCM_T
308         ;
309
310
311 chordmodifiers_block:
312         CHORDMODIFIERS notenames_body   {  $$ = $2; }
313         ;
314
315
316 notenames_block:
317         NOTENAMES notenames_body   {  $$ = $2; }
318         ;
319
320
321
322 notenames_body:
323         embedded_scm    {
324           int i = scm_ilength ($1);
325
326           SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
327           for (SCM s = $1; s != SCM_EOL; s = gh_cdr (s)) {
328                 SCM pt = gh_cdar (s);
329                 if (scm_ilength (pt) != 3)
330                         THIS->parser_error ("Need three args");
331                 scm_hashq_set_x (tab, gh_caar(s), pt);
332           }
333
334           $$ = tab;
335         }
336         ;
337
338 mudela_header_body:
339         {
340                 $$ = new Scope;
341                 THIS->lexer_p_-> scope_l_arr_.push ($$);
342         }
343         | mudela_header_body assignment semicolon { 
344
345         }
346         ;
347
348 mudela_header:
349         HEADER '{' mudela_header_body '}'       {
350                 $$ = $3;
351                 THIS->lexer_p_-> scope_l_arr_.pop ();           
352         }
353         ;
354
355
356 /*
357         DECLARATIONS
358 */
359 assignment:
360         STRING {
361                 THIS->remember_spot ();
362         }
363         /* cont */ '=' identifier_init  {
364             THIS->lexer_p_->set_identifier (ly_scm2string ($1), $4);
365
366             $4->set_spot (THIS->pop_spot ());
367         }
368         ;
369
370
371
372 identifier_init:
373         score_block {
374                 $$ = new Score_identifier ($1, SCORE_IDENTIFIER);
375
376         }
377         | paper_block {
378                 $$ = new Paper_def_identifier ($1, PAPER_IDENTIFIER);
379         }
380         | midi_block {
381                 $$ = new Midi_def_identifier ($1, MIDI_IDENTIFIER);
382
383         }
384         | translator_spec_block {
385                 $$ = new Translator_group_identifier ($1, TRANS_IDENTIFIER);
386         }
387         | Music  {
388                 $$ = new Music_identifier ($1, MUSIC_IDENTIFIER);
389         }
390
391         | post_request {
392                 $$ = new Request_identifier ($1, REQUEST_IDENTIFIER);
393         }
394         | explicit_duration {
395                 $$ = new Duration_identifier ($1, DURATION_IDENTIFIER);
396         }
397         | real {
398                 $$ = new Real_identifier (new Real ($1), REAL_IDENTIFIER);
399         }
400         | string {
401                 $$ = new String_identifier (new String (ly_scm2string ($1)), STRING_IDENTIFIER);
402         }
403         | int   {
404                 $$ = new int_identifier (new int ($1), INT_IDENTIFIER);
405         }
406         ;
407
408 translator_spec_block:
409         TRANSLATOR '{' translator_spec_body '}'
410                 {
411                 $$ = $3;
412         }
413         ;
414
415 translator_spec_body:
416         TRANS_IDENTIFIER        {
417                 $$ = $1->access_content_Translator_group (true);
418                 $$-> set_spot (THIS->here_input ());
419         }
420         | TYPE STRING semicolon {
421                 Translator* t = get_translator_l (ly_scm2string ($2));
422                 Translator_group * tg = dynamic_cast<Translator_group*> (t);
423
424                 if (!tg)
425                         THIS->parser_error (_("Need a translator group for a context"));
426                 
427                 tg = dynamic_cast<Translator_group*> (t->clone ());
428                 tg->set_spot (THIS->here_input ());
429                 $$ = tg;
430         }
431         | translator_spec_body STRING '=' embedded_scm                  {
432                 Translator_group* tg = dynamic_cast<Translator_group*> ($$);
433                 tg->set_property (ly_scm2string ($2), $4);
434         }
435         | translator_spec_body STRING '=' identifier_init semicolon     { 
436                 Identifier* id = $4;
437                 String_identifier *s = dynamic_cast<String_identifier*> (id);
438                 Real_identifier *r= dynamic_cast<Real_identifier*>(id);
439                 int_identifier *i = dynamic_cast<int_identifier*> (id);
440         
441                 SCM v;
442                 if (s) v = ly_str02scm (s->access_content_String (false)->ch_C());
443                 if (i) v = gh_int2scm (*i->access_content_int (false));
444                 if (r) v = gh_double2scm (*r->access_content_Real (false));
445                 if (!s && !i && !r)
446                         THIS->parser_error (_("Wrong type for property value"));
447
448                 delete $4;
449                 /* ugh*/
450                 Translator_group* tg = dynamic_cast<Translator_group*> ($$);
451                 
452                 tg->set_property (ly_scm2string ($2), v);
453         }
454         | translator_spec_body NAME STRING semicolon {
455                 $$->type_str_ = ly_scm2string ($3);
456         }
457         | translator_spec_body CONSISTS STRING semicolon {
458                 dynamic_cast<Translator_group*> ($$)-> set_element (ly_scm2string ($3), true);
459         }
460         | translator_spec_body CONSISTSEND STRING semicolon {
461                 dynamic_cast<Translator_group*> ($$)-> set_element (ly_scm2string ($3), true);
462         }
463         | translator_spec_body ACCEPTS STRING semicolon {
464                 dynamic_cast<Translator_group*> ($$)-> set_acceptor (ly_scm2string ($3), true);
465         }
466         | translator_spec_body REMOVE STRING semicolon {
467                 dynamic_cast<Translator_group*> ($$)-> set_element (ly_scm2string ($3), false);
468         }
469         ;
470
471 /*
472         SCORE
473 */
474 score_block:
475         SCORE { 
476         }
477         /*cont*/ '{' score_body '}'     {
478                 $$ = $4;
479                 if (!$$->def_p_arr_.size ())
480                 {
481                   Identifier *id =
482                         THIS->lexer_p_->lookup_identifier ("$defaultpaper");
483                   $$->add_output (id ? id->access_content_Paper_def (true) : new Paper_def );
484                 }
485         }
486         ;
487
488 score_body:
489         Music   {
490                 $$ = new Score;
491                 $$->set_spot (THIS->here_input ());
492                 $$->music_p_ = $1;
493         }
494         | SCORE_IDENTIFIER {
495                 $$ = $1->access_content_Score (true);
496         }
497         | score_body mudela_header      {
498                 $$->header_p_ = $2;
499         }
500         | score_body output_def {
501                 $$->add_output ($2);
502         }
503         | score_body error {
504
505         }
506         ;
507
508 output_def:
509         paper_block {
510                 $$ = $1;
511         }
512         |  midi_block           {
513                 $$= $1;
514         }
515         ;
516
517
518 /*
519         PAPER
520 */
521 paper_block:
522         PAPER '{' paper_def_body '}'    { 
523                 $$ = $3;
524                 THIS-> lexer_p_->scope_l_arr_.pop ();
525         }
526         ;
527
528
529 paper_def_body:
530         /* empty */                     {
531                   Identifier *id = THIS->lexer_p_->lookup_identifier ("$defaultpaper");
532                   Paper_def *p = id ? id->access_content_Paper_def (true) : new Paper_def;
533                 THIS-> lexer_p_-> scope_l_arr_.push (p->scope_p_);
534                 $$ = p;
535         }
536         | PAPER_IDENTIFIER      {
537                 Paper_def *p = $1->access_content_Paper_def (true);
538                 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
539                 $$ = p;
540         }
541         | paper_def_body int '=' FONT STRING            { // ugh, what a syntax
542                 Lookup * l = new Lookup;
543                 l->font_name_ = ly_scm2string ($5);
544                 $$->set_lookup ($2, l);
545         }
546         | paper_def_body assignment semicolon {
547                 
548         }
549         | paper_def_body translator_spec_block {
550                 $$->assign_translator ($2);
551         }
552         | paper_def_body error {
553
554         }
555         ;
556
557
558
559 real_with_dimension:
560         REAL CM_T       {
561                 $$ = $1 CM;
562         }
563         | REAL PT_T     {
564                 $$ = $1 PT;
565         }
566         | REAL IN_T     {
567                 $$ = $1 INCH;
568         }
569         | REAL MM_T     {
570                 $$ = $1 MM;
571         }
572         | REAL CHAR_T   {
573                 $$ = $1 CHAR;
574         }
575         ;
576
577 real:
578         REAL            {
579                 $$ = $1;
580         }
581         | real_with_dimension
582         | REAL_IDENTIFIER               {
583                 $$= *$1->access_content_Real (false);
584         }
585         | '-'  real %prec UNARY_MINUS {
586                 $$ = -$2;
587         }
588         | real '*' real {
589                 $$ = $1 * $3;
590         }
591         | real '/' real {
592                 $$ = $1 / $3;
593         }
594         | real '+' real {
595                 $$ = $1  + $3;
596         }
597         | real '-' real {
598                 $$ = $1 - $3;
599         }
600         | '(' real ')'  {
601                 $$ = $2;
602         }
603         ;
604                 
605 /*
606         MIDI
607 */
608 midi_block:
609         MIDI
610         '{' midi_body '}'       {
611                 $$ = $3;
612                 THIS-> lexer_p_-> scope_l_arr_.pop();
613         }
614         ;
615
616 midi_body: /* empty */          {
617          Identifier *id = THIS->lexer_p_->lookup_identifier ("$defaultmidi");
618          Midi_def* p = id
619                 ? id->access_content_Midi_def (true) : new Midi_def ;
620
621          $$ = p;
622          THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
623         }
624         | MIDI_IDENTIFIER       {
625                 Midi_def * p =$1-> access_content_Midi_def (true);
626                 $$ = p;
627                 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
628         }
629         | midi_body assignment semicolon {
630
631         }
632         | midi_body translator_spec_block       {
633                 $$-> assign_translator ($2);
634         }
635         | midi_body tempo_request semicolon {
636                 /*
637                         junk this ? there already is tempo stuff in
638                         music.
639                 */
640                 $$->set_tempo ($2->dur_.length_mom (), $2->metronome_i_);
641                 delete $2;
642         }
643         | midi_body error {
644
645         }
646         ;
647
648 tempo_request:
649         TEMPO steno_duration '=' unsigned       {
650                 $$ = new Tempo_req;
651                 $$->dur_ = *$2;
652                 delete $2;
653                 $$-> metronome_i_ = $4;
654         }
655         ;
656
657 Music_list: /* empty */ {
658                 $$ = new Music_list;
659                 $$->set_spot (THIS->here_input ());
660         }
661         | Music_list Music {
662                 $$->add_music ($2);
663         }
664         | Music_list error {
665         }
666         ;
667
668
669 Music:
670         Simple_music
671         | Composite_music
672         ;
673
674 Alternative_music:
675         /* empty */ {
676                 $$ = 0;
677         }
678         | ALTERNATIVE Music_sequence {
679                 $$ = $2;
680                 $2->set_spot (THIS->here_input ());
681         }
682         ;
683
684
685
686
687 Repeated_music:
688         REPEAT STRING unsigned Music Alternative_music
689         {
690                 Music_sequence* m = dynamic_cast <Music_sequence*> ($5);
691                 if (m && $3 < m->length_i ())
692                         $5->warning (_ ("More alternatives than repeats.  Junking excess alternatives."));
693
694                 Repeated_music * r = new Repeated_music ($4, $3 >? 1, m);
695                 $$ = r;
696                 r->type_ = ly_scm2string ($2);
697                 r->fold_b_ = (r->type_ == "fold");
698                 r->volta_fold_b_ =  (r->type_ == "volta");
699                 r->set_spot ($4->spot  ());
700         }
701         ;
702
703 Music_sequence: '{' Music_list '}'      {
704                 $$ = new Music_sequence ($2);
705                 $$->set_spot ($2->spot ());
706         }
707         ;
708
709 Sequential_music:
710         SEQUENTIAL '{' Music_list '}'           {
711                 $$ = new Sequential_music ($3);
712                 $$->set_spot ($3->spot ());
713         }
714         | '{' Music_list '}'            {
715                 $$ = new Sequential_music ($2);
716                 $$->set_spot ($2->spot ());
717         }
718         ;
719
720 Simultaneous_music:
721         SIMULTANEOUS '{' Music_list '}'{
722                 $$ = new Simultaneous_music ($3);
723                 $$->set_spot ($3->spot ());
724         }
725         | '<' Music_list '>'    {
726                 $$ = new Simultaneous_music ($2);
727                 $$->set_spot ($2->spot ());
728         }
729         ;
730
731 Simple_music:
732         request_chord           { $$ = $1; }
733         | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm     {
734                 SCM pred = $2;
735                 if (!gh_symbol_p ($3))
736                 {
737                         THIS->parser_error (_("Second argument must be a symbol")); 
738                 }
739                 /*hould check # args */
740                 if (!gh_procedure_p (pred))
741                 {
742                         THIS->parser_error (_("First argument must be a procedure taking 1 argument"));
743                 }
744         
745                 $$ = new Output_property (pred,$3, $5);
746         }
747         | MUSIC_IDENTIFIER { $$ = $1->access_content_Music (true); }
748         | property_def
749         | translator_change
750         | Simple_music '*' unsigned '/' unsigned        {
751                 $$ = $1;
752                 $$->compress (Moment($3, $5 ));
753         }
754         | Simple_music '*' unsigned              {
755                 $$ = $1;
756                 $$->compress (Moment ($3, 1));
757         }
758         ;
759
760
761 Composite_music:
762         CONTEXT STRING Music    {
763                 Context_specced_music *csm =  new Context_specced_music ($3);
764
765                 csm->translator_type_str_ = ly_scm2string ($2);
766                 csm->translator_id_str_ = "";
767
768
769                 $$ = csm;
770         }
771         | AUTOCHANGE STRING Music       {
772                 Auto_change_music * chm = new Auto_change_music (ly_scm2string ($2), $3);
773
774                 $$ = chm;
775                 chm->set_spot ($3->spot ());
776         }
777         | GRACE Music {
778                 $$ = new Grace_music ($2);
779         }
780         | CONTEXT STRING '=' STRING Music {
781                 Context_specced_music *csm =  new Context_specced_music ($5);
782
783                 csm->translator_type_str_ = ly_scm2string ($2);
784                 csm->translator_id_str_ = ly_scm2string ($4);
785
786                 $$ = csm;
787         }
788         | TIMES {
789                 THIS->remember_spot ();
790         }
791         /* CONTINUED */ 
792                 unsigned '/' unsigned Music     
793
794         {
795                 $$ = new Time_scaled_music ($3, $5, $6);
796                 $$->set_spot (THIS->pop_spot ());
797         }
798         | Repeated_music                { $$ = $1; }
799         | Simultaneous_music            { $$ = $1; }
800         | Sequential_music              { $$ = $1; }
801         | TRANSPOSE musical_pitch Music {
802                 $$ = new Transposed_music ($3, *$2);
803                 delete $2;
804         }
805         | TRANSPOSE steno_tonic_pitch Music {
806                 $$ = new Transposed_music ($3, *$2);
807                 delete $2;
808         }
809         | NOTES
810                 { THIS->lexer_p_->push_note_state (); }
811         Music
812                 { $$ = $3;
813                   THIS->lexer_p_->pop_state ();
814                 }
815         | CHORDS
816                 { THIS->lexer_p_->push_chord_state (); }
817         Music
818                 {
819                   $$ = $3;
820                   THIS->lexer_p_->pop_state ();
821         }
822         | LYRICS
823                 { THIS->lexer_p_->push_lyric_state (); }
824         Music
825                 {
826                   $$ = $3;
827                   THIS->lexer_p_->pop_state ();
828         }
829         | relative_music        { $$ = $1; }
830         | re_rhythmed_music     { $$ = $1; } 
831         ;
832
833 relative_music:
834         RELATIVE absolute_musical_pitch Music {
835                 $$ = new Relative_octave_music ($3, *$2);
836                 delete $2;
837         }
838         ;
839
840 re_rhythmed_music:
841         ADDLYRICS Music Music {
842                 Lyric_combine_music * l = new Lyric_combine_music ($2, $3);
843                 $$ = l;
844         }
845         ;
846
847 translator_change:
848         TRANSLATOR STRING '=' STRING  {
849                 Change_translator * t = new Change_translator;
850                 t-> change_to_type_str_ = ly_scm2string ($2);
851                 t-> change_to_id_str_ = ly_scm2string ($4);
852
853                 $$ = t;
854                 $$->set_spot (THIS->here_input ());
855         }
856         ;
857
858 property_def:
859         PROPERTY STRING '.' STRING '='  scalar {
860                 Translation_property *t = new Translation_property;
861
862                 t->var_str_ = ly_scm2string ($4);
863                 t->value_ = $6;
864
865                 Context_specced_music *csm = new Context_specced_music (t);
866                 $$ = csm;
867                 $$->set_spot (THIS->here_input ());
868
869                 csm-> translator_type_str_ = ly_scm2string ($2);
870         }
871         ;
872
873 scalar:
874         string          { $$ = $1; }
875         | int           { $$ = gh_int2scm ($1); }
876         | embedded_scm  { $$ = $1; }
877         ;
878
879
880 request_chord:
881         pre_requests simple_element post_requests       {
882                 Music_sequence *l = dynamic_cast<Music_sequence*>($2);
883                 if (l) {
884                         for (int i=0; i < $1->size(); i++)
885                                 l->add_music ($1->elem(i));
886                         for (int i=0; i < $3->size(); i++)
887                                 l->add_music ($3->elem(i));
888                         }
889                 else
890                         programming_error ("Need Sequence to add music to");
891                 $$ = $2;
892                 
893         }
894         | command_element
895         ;
896
897 command_element:
898         command_req {
899                 $$ = new Request_chord;
900                 $$-> set_spot (THIS->here_input ());
901                 $1-> set_spot (THIS->here_input ());
902                 ((Simultaneous_music*)$$) ->add_music ($1);//ugh
903         }
904         | PARTIAL duration_length ';'   {
905                 Translation_property * p = new Translation_property;
906                 p->var_str_ = "measurePosition";
907                 p->value_ =  (new Moment (-$2->length_mom ()))->smobify_self ();
908                 delete $2;
909                 Context_specced_music * sp = new Context_specced_music (p);
910                 $$ =sp ;
911                 sp-> translator_type_str_ = "Score";
912         }
913         ;
914
915 command_req:
916         shorthand_command_req
917         | verbose_command_req semicolon { $$ = $1; }
918         ;
919
920 shorthand_command_req:
921         extender_req {
922                 $$ = $1;
923         }
924         | hyphen_req {
925                 $$ = $1;
926         }
927         | '|'                           {
928                 $$ = new Barcheck_req;
929         }
930         | '~'   {
931                 $$ = new Tie_req;
932         }
933         | '['           {
934                 Span_req*b= new Span_req;
935                 b->span_dir_ = START;
936                 b->span_type_str_ = "beam";
937                 $$ =b;
938         }
939         | ']'           {
940              Span_req*b= new Span_req;
941              b->span_dir_ = STOP;
942              b->span_type_str_ = "beam";
943              $$ = b;
944         }
945         | BREATHE {
946                 $$ = new Breathing_sign_req;
947         }
948         ;
949
950
951 verbose_command_req:
952         
953         BAR STRING                      {
954                 $$ = new Bar_req (ly_scm2string ($2));
955         }
956         | COMMANDSPANREQUEST int STRING {
957                 Span_req * sp_p = new Span_req;
958                 sp_p-> span_dir_  = Direction($2);
959                 sp_p->span_type_str_ = ly_scm2string ($3);
960                 sp_p->set_spot (THIS->here_input ());
961                 $$ = sp_p;
962         }
963         | MARK  {
964                 Mark_req * m = new Mark_req;
965                 $$ = m;
966         }
967         | MARK STRING {
968                 Mark_req *m = new Mark_req;
969                 m->mark_label_ = $2;
970                 $$ = m;
971
972         }
973         | MARK unsigned {
974                 Mark_req *m = new Mark_req;
975                 m->mark_label_ =  gh_int2scm ($2);
976                 $$ = m;
977         }
978
979         | TIME_T unsigned '/' unsigned  {
980                 Time_signature_change_req *m = new Time_signature_change_req;
981                 m->beats_i_ = $2;
982                 m->one_beat_i_=$4;
983                 $$ = m;
984         }
985         | PENALTY int   {
986                 Break_req * b = new Break_req;
987                 b->penalty_f_ = $2 / 100.0;
988                 b->set_spot (THIS->here_input ());
989                 $$ = b;
990         }
991         | SKIP duration_length {
992                 Skip_req * skip_p = new Skip_req;
993                 skip_p->duration_ = *$2;
994                 delete $2;
995                 $$ = skip_p;
996         }
997         | tempo_request {
998                 $$ = $1;
999         }
1000         | CLEF STRING {
1001                 $$ = new Clef_change_req (ly_scm2string ($2));
1002
1003         }
1004         | KEY {
1005                 Key_change_req *key_p= new Key_change_req;
1006                 key_p->key_ = 0;
1007                 $$ = key_p;
1008         }
1009 /*
1010 TODO: Support for minor/major keys; make `major-scale' settable.
1011 */
1012         | KEY NOTENAME_PITCH    {
1013                 Key_change_req *key_p= new Key_change_req;
1014                 key_p->key_ = new Newkey_def;
1015                 
1016                 key_p->key_->pitch_alist_ = scm_eval (ly_symbol2scm ("major-scale"));
1017                 key_p->key_->transpose (* $2);
1018                 $$ = key_p; 
1019         }
1020         ;
1021
1022 post_requests:
1023         {
1024                 $$ = new Link_array<Request>;
1025         }
1026         | post_requests post_request {
1027                 $2->set_spot (THIS->here_input ());
1028                 $$->push ($2);
1029         }
1030         ;
1031
1032 post_request:
1033         verbose_request
1034         | request_with_dir
1035         | close_request
1036         ;
1037
1038
1039 request_that_take_dir:
1040         gen_text_def
1041         | verbose_request
1042         | script_abbreviation {
1043                 Identifier*i = THIS->lexer_p_->lookup_identifier ("dash-" + ly_scm2string ($1));
1044                 Articulation_req *a = new Articulation_req;
1045                 a->articulation_str_ = *i->access_content_String (false);
1046                 $$ = a;
1047         }
1048         ;
1049
1050 request_with_dir:
1051         script_dir request_that_take_dir        {
1052                 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1053                         gs->dir_ = Direction ($1);
1054                 else if ($1)
1055                         $2->warning (_ ("Can't specify direction for this request"));
1056                 $$ = $2;
1057         }
1058         ;
1059         
1060 verbose_request:
1061         REQUEST_IDENTIFIER      {
1062                 $$ = (Request*)$1->access_content_Request (true);
1063                 $$->set_spot (THIS->here_input ());
1064         }
1065         | TEXTSCRIPT STRING STRING      {
1066                 Text_script_req *ts_p = new Text_script_req;
1067                 ts_p-> text_str_ = ly_scm2string ($2);
1068                 ts_p-> style_str_ = ly_scm2string ($3);
1069                 ts_p->set_spot (THIS->here_input ());
1070
1071                 $$ = ts_p;
1072         }
1073         | SPANREQUEST int STRING {
1074                 Span_req * sp_p = new Span_req;
1075                 sp_p-> span_dir_  = Direction($2);
1076                 sp_p->span_type_str_ = ly_scm2string ($3);
1077                 sp_p->set_spot (THIS->here_input ());
1078                 $$ = sp_p;
1079         }
1080         | tremolo_type  {
1081                 Tremolo_req* a = new Tremolo_req;
1082                 a->set_spot (THIS->here_input ());
1083                 a->type_i_ = $1;
1084                 $$ = a;
1085         }
1086         | SCRIPT STRING         { 
1087                 Articulation_req * a = new Articulation_req;
1088                 a->articulation_str_ = ly_scm2string ($2);
1089                 a->set_spot (THIS->here_input ());
1090                 $$ = a;
1091         }
1092         ;
1093
1094 sup_quotes:
1095         '\'' {
1096                 $$ = 1;
1097         }
1098         | sup_quotes '\'' {
1099                 $$ ++;
1100         }
1101         ;
1102
1103 sub_quotes:
1104         ',' {
1105                 $$ = 1;
1106         }
1107         | sub_quotes ',' {
1108                 $$ ++ ;
1109         }
1110         ;
1111
1112 steno_musical_pitch:
1113         NOTENAME_PITCH  {
1114                 $$ = $1;
1115         }
1116         | NOTENAME_PITCH sup_quotes     {
1117                 $$ = $1;
1118                 $$->octave_i_ +=  $2;
1119         }
1120         | NOTENAME_PITCH sub_quotes      {
1121                 $$ = $1;
1122                 $$->octave_i_ += - $2;
1123         }
1124         ;
1125
1126 steno_tonic_pitch:
1127         TONICNAME_PITCH {
1128                 $$ = $1;
1129         }
1130         | TONICNAME_PITCH sup_quotes    {
1131                 $$ = $1;
1132                 $$->octave_i_ +=  $2;
1133         }
1134         | TONICNAME_PITCH sub_quotes     {
1135                 $$ = $1;
1136                 $$->octave_i_ += - $2;
1137         }
1138         ;
1139
1140 musical_pitch:
1141         steno_musical_pitch {
1142                 $$ = $1;
1143         }
1144         | MUSICAL_PITCH embedded_scm {
1145                 int sz = scm_ilength ($2);
1146                 if (sz != 3) {
1147                         THIS->parser_error (_f ("Expecting %d arguments", 3));
1148                         $2 = gh_list (gh_int2scm (0), gh_int2scm (0), gh_int2scm (0), SCM_UNDEFINED);
1149                 }
1150                 $$ = new Musical_pitch ($2);
1151         }
1152         ;
1153
1154 explicit_duration:
1155         DURATION '{' int_list '}'       {
1156                 $$ = new Duration;
1157                 Array<int> &a = *$3;
1158                 ARRAY_SIZE(a,2);
1159                         
1160                 $$-> durlog_i_ = a[0];
1161                 $$-> dots_i_ = a[1];
1162
1163                 delete &a;              
1164         }
1165         ;
1166
1167 extender_req:
1168         EXTENDER {
1169                 if (!THIS->lexer_p_->lyric_state_b ())
1170                         THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1171                 $$ = new Extender_req;
1172         }
1173         ;
1174
1175 hyphen_req:
1176         HYPHEN {
1177                 if (!THIS->lexer_p_->lyric_state_b ())
1178                         THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1179                 $$ = new Hyphen_req;
1180         }
1181         ;
1182
1183 close_request:
1184         close_request_parens {
1185                 $$ = $1;
1186                 dynamic_cast<Span_req*> ($$)->span_dir_ = START;
1187         }
1188         
1189 close_request_parens:
1190         '('     {
1191                 Span_req* s= new Span_req;
1192                 $$ = s;
1193                 s->span_type_str_ = "slur";
1194         }
1195         | E_SMALLER {
1196                 Span_req*s =new Span_req;
1197                 $$ = s;
1198                 s->span_type_str_ = "crescendo";
1199         }
1200         | E_BIGGER {
1201                 Span_req*s =new Span_req;
1202                 $$ = s;
1203                 s->span_type_str_ = "decrescendo";
1204         }
1205         ;
1206
1207
1208 open_request:
1209         open_request_parens {
1210                 $$ = $1;
1211                 dynamic_cast<Span_req*> ($$)->span_dir_ = STOP;
1212         }
1213         ;
1214
1215 open_request_parens:
1216         E_EXCLAMATION   {
1217                 Span_req *s =  new Span_req;
1218                 s->span_type_str_ = "crescendo";
1219                 $$ = s;
1220         }
1221         | ')'   {
1222                 Span_req* s= new Span_req;
1223                 $$ = s;
1224                 s->span_type_str_ = "slur";
1225         }
1226         ;
1227
1228 gen_text_def:
1229         string {
1230                 Text_script_req *t  = new Text_script_req;
1231                 $$ = t;
1232                 t->text_str_ = ly_scm2string ($1);
1233
1234                 $$->set_spot (THIS->here_input ());
1235         }
1236         | DIGIT {
1237                 Text_script_req* t  = new Text_script_req;
1238                 $$ = t;
1239                 t->text_str_ = to_str ($1);
1240                 t->style_str_ = "finger";
1241                 $$->set_spot (THIS->here_input ());
1242         }
1243         ;
1244
1245 script_abbreviation:
1246         '^'             {
1247                 $$ = gh_str02scm  ("hat");
1248         }
1249         | '+'           {
1250                 $$ = gh_str02scm("plus");
1251         }
1252         | '-'           {
1253                 $$ = gh_str02scm ("dash");
1254         }
1255         | '|'           {
1256                 $$ = gh_str02scm ("bar");
1257         }
1258         | '>'           {
1259                 $$ = gh_str02scm ("larger");
1260         }
1261         | '.'           {
1262                 $$ = gh_str02scm ("dot");
1263         }
1264         ;
1265
1266
1267 script_dir:
1268         '_'     { $$ = DOWN; }
1269         | '^'   { $$ = UP; }
1270         | '-'   { $$ = CENTER; }
1271         ;
1272
1273 pre_requests:
1274         {
1275                 $$ = new Link_array<Request>;
1276         }
1277         | pre_requests open_request {
1278                 $$->push ($2);
1279         }
1280         ;
1281
1282 absolute_musical_pitch:
1283         steno_musical_pitch     {
1284                 $$ = $1;
1285         }
1286         ;
1287
1288 duration_length:
1289         steno_duration {
1290                 $$ = $1;
1291         }
1292         | duration_length '*' unsigned {
1293                 $$->tuplet_iso_i_ *= $3;
1294         }
1295         | duration_length '/' unsigned {
1296                 $$->tuplet_type_i_ *= $3;
1297         }
1298         ;
1299
1300 entered_notemode_duration:
1301         steno_duration  {
1302                 THIS->set_last_duration ($1);
1303         }
1304         ;
1305
1306 optional_notemode_duration:
1307         {
1308                 $$ = new Duration (THIS->default_duration_);
1309         }
1310         | entered_notemode_duration {
1311                 $$ = $1;
1312         }
1313         ;
1314
1315 steno_duration:
1316         unsigned                {
1317                 $$ = new Duration;
1318                 if (!is_duration_b ($1))
1319                         THIS->parser_error (_f ("not a duration: %d", $1));
1320                 else {
1321                         $$->durlog_i_ = intlog2 ($1);
1322                      }
1323         }
1324         | DURATION_IDENTIFIER   {
1325                 $$ = $1->access_content_Duration (true);
1326         }
1327         | steno_duration '.'    {
1328                 $$->dots_i_ ++;
1329         }
1330         ;
1331
1332
1333 tremolo_type: 
1334         ':'     {
1335                 $$ =0;
1336         }
1337         | ':' unsigned {
1338                 if (!is_duration_b ($2))
1339                         THIS->parser_error (_f ("not a duration: %d", $2));
1340                 $$ = $2;
1341         }
1342         ;
1343
1344
1345 simple_element:
1346         musical_pitch exclamations questions optional_notemode_duration {
1347                 if (!THIS->lexer_p_->note_state_b ())
1348                         THIS->parser_error (_ ("Have to be in Note mode for notes"));
1349
1350
1351                 Note_req *n = new Note_req;
1352                 
1353                 n->pitch_ = *$1;
1354                 n->duration_ = *$4;
1355
1356                 n->cautionary_b_ = $3 % 2;
1357                 n->forceacc_b_ = $2 % 2 || n->cautionary_b_;
1358
1359                 Simultaneous_music*v = new Request_chord;
1360                 v->set_spot ($1->spot ());
1361                 n->set_spot ($1->spot ());
1362
1363                 v->add_music (n);
1364
1365                 $$ = v;
1366
1367                 delete $1;
1368                 delete $4;
1369
1370         }
1371         | RESTNAME optional_notemode_duration           {
1372                   Simultaneous_music* velt_p = new Request_chord;
1373                   velt_p->set_spot (THIS->here_input());
1374
1375                   if (ly_scm2string ($1) =="s")
1376                     { /* Space */
1377                       Skip_req * skip_p = new Skip_req;
1378                       skip_p->duration_ = *$2;
1379
1380                       skip_p->set_spot (THIS->here_input());
1381                       velt_p->add_music (skip_p);
1382                     }
1383                   else
1384                     {
1385                       Rest_req * rest_req_p = new Rest_req;
1386                       rest_req_p->duration_ = *$2;
1387                       rest_req_p->set_spot (THIS->here_input());
1388
1389                       velt_p->add_music (rest_req_p);
1390                     }
1391
1392                   delete $2;
1393                   $$ = velt_p;
1394         }
1395         | MEASURES optional_notemode_duration   {
1396                 Skip_req * sk = new Skip_req;
1397                 sk->duration_ = *$2;
1398                 Music_list * ms = new Music_list;
1399                 Request_chord * rqc1 = new Request_chord;
1400                 Request_chord * rqc2 = new Request_chord;
1401                 Request_chord * rqc3 = new Request_chord;
1402
1403                 Span_req *sp1 = new Span_req;
1404                 Span_req *sp2 = new Span_req;
1405                 sp1-> span_dir_ = START;
1406                 sp2-> span_dir_ = STOP;
1407                 sp1->span_type_str_ = sp2->span_type_str_ = "rest";
1408                 rqc1->add_music (sp1);
1409                 rqc2->add_music (sk);
1410                 rqc3->add_music (sp2);
1411                 
1412                 ms->add_music (rqc1);
1413                 ms->add_music (rqc2);
1414                 ms->add_music (rqc3);
1415
1416                 $$ = new Sequential_music (ms);
1417         }
1418         | STRING optional_notemode_duration     {
1419                 if (!THIS->lexer_p_->lyric_state_b ())
1420                         THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1421                   Simultaneous_music* velt_p = new Request_chord;
1422
1423                   Lyric_req* lreq_p = new Lyric_req;
1424                   lreq_p ->text_str_ = ly_scm2string ($1);
1425                   lreq_p->duration_ = *$2;
1426                   lreq_p->set_spot (THIS->here_input());
1427
1428                   velt_p->add_music (lreq_p);
1429
1430                   delete  $2;
1431                 $$= velt_p;
1432
1433         }
1434         | chord {
1435                 if (!THIS->lexer_p_->chord_state_b ())
1436                         THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1437                 $$ = $1;
1438         }
1439         ;
1440
1441 chord:
1442         steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1443                 $$ = THIS->get_chord (*$1, $3, $4, $5, $6, *$2);
1444         };
1445
1446 chord_additions: 
1447         {
1448                 $$ = new Array<Musical_pitch>;
1449         } 
1450         | CHORD_COLON chord_notes {
1451                 $$ = $2;
1452         }
1453         ;
1454
1455 chord_notes:
1456         chord_step {
1457                 $$ = $1
1458         }
1459         | chord_notes '.' chord_step {
1460                 $$ = $1;
1461                 $$->concat (*$3);
1462         }
1463         ;
1464
1465 chord_subtractions: 
1466         {
1467                 $$ = new Array<Musical_pitch>;
1468         } 
1469         | CHORD_CARET chord_notes {
1470                 $$ = $2;
1471         }
1472         ;
1473
1474
1475 chord_inversion:
1476         {
1477                 $$ = 0;
1478         }
1479         | '/' steno_tonic_pitch {
1480                 $$ = $2;
1481                 $$->set_spot (THIS->here_input ());
1482         }
1483         ;
1484
1485 chord_bass:
1486         {
1487                 $$ = 0;
1488         }
1489         | CHORD_BASS steno_tonic_pitch {
1490                 $$ = $2;
1491                 $$->set_spot (THIS->here_input ());
1492         }
1493         ;
1494
1495 chord_step:
1496         chord_note {
1497                 $$ = new Array<Musical_pitch>;
1498                 $$->push (*$1);
1499         }
1500         | CHORDMODIFIER_PITCH {
1501                 $$ = new Array<Musical_pitch>;
1502                 $$->push (*$1);
1503         }
1504         | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1505                 $$ = new Array<Musical_pitch>;
1506                 $$->push (*$1);
1507                 $$->push (*$2);
1508         }
1509         ;
1510
1511 chord_note:
1512         unsigned {
1513                 $$ = new Musical_pitch;
1514                 $$->notename_i_ = ($1 - 1) % 7;
1515                 $$->octave_i_ = $1 > 7 ? 1 : 0;
1516                 $$->accidental_i_ = 0;
1517         } 
1518         | unsigned '+' {
1519                 $$ = new Musical_pitch;
1520                 $$->notename_i_ = ($1 - 1) % 7;
1521                 $$->octave_i_ = $1 > 7 ? 1 : 0;
1522                 $$->accidental_i_ = 1;
1523         }
1524         | unsigned CHORD_MINUS {
1525                 $$ = new Musical_pitch;
1526                 $$->notename_i_ = ($1 - 1) % 7;
1527                 $$->octave_i_ = $1 > 7 ? 1 : 0;
1528                 $$->accidental_i_ = -1;
1529         }
1530         ;
1531
1532 /*
1533         UTILITIES
1534  */
1535
1536 /*
1537   FIXME: use scm.
1538 */
1539 /*
1540 pitch_list:                     {
1541                 $$ = new Array<Musical_pitch>;
1542         }
1543         | pitch_list musical_pitch      {
1544                 $$->push (*$2);
1545                 delete $2;
1546         }
1547         ;
1548 */
1549
1550 int_list:
1551         /**/                    {
1552                 $$ = new Array<int>
1553         }
1554         | int_list int          {
1555                 $$->push ($2);          
1556         }
1557         ;
1558
1559 unsigned:
1560         UNSIGNED        {
1561                 $$ = $1;
1562         }
1563         | DIGIT         {
1564                 $$ = $1;
1565         }
1566         ;
1567
1568 int:
1569         unsigned {
1570                 $$ = $1;
1571         }
1572         | '-' unsigned {
1573                 $$ = -$2;
1574         }
1575         | INT_IDENTIFIER        {
1576                 $$ = *$1->access_content_int (false);
1577         }
1578         ;
1579
1580
1581 string:
1582         STRING          {
1583                 $$ = $1;
1584         }
1585         | STRING_IDENTIFIER     {
1586                 $$ = ly_str02scm ($1->access_content_String (true)->ch_C ());
1587         }
1588         | string '+' string {
1589                 $$ = scm_string_append (scm_listify ($1, $3, SCM_UNDEFINED));
1590         }
1591         ;
1592
1593
1594 exclamations:
1595                 { $$ = 0; }
1596         | exclamations '!'      { $$ ++; }
1597         ;
1598
1599 questions:
1600                 { $$ = 0; }
1601         | questions '?' { $$ ++; }
1602         ;
1603
1604
1605 semicolon:
1606         ';'
1607         ;
1608 %%
1609
1610 void
1611 My_lily_parser::set_yydebug (bool b)
1612 {
1613 #ifdef YYDEBUG
1614         yydebug = b;
1615 #endif
1616 }
1617 void
1618 My_lily_parser::do_yyparse ()
1619 {
1620         yyparse ((void*)this);
1621 }
1622
1623