]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.yy
release: 0.1.62
[lilypond.git] / lily / parser.yy
1 %{ // -*-Fundamental-*-
2
3 /*
4   parser.yy -- YACC -> C++ parser for mudela
5
6   source file of the GNU LilyPond music typesetter
7
8   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
9            Jan Nieuwenhuizen <jan@digicash.com>
10 */
11
12 #include <iostream.h>
13
14 #include "scalar.hh"
15 #include "translation-property.hh"
16 #include "script-def.hh"
17 #include "symtable.hh"
18 #include "lookup.hh"
19 #include "misc.hh"
20 #include "my-lily-lexer.hh"
21 #include "paper-def.hh"
22 #include "midi-def.hh"
23 #include "main.hh"
24 #include "keyword.hh"
25 #include "debug.hh"
26 #include "parseconstruct.hh"
27 #include "dimen.hh"
28 #include "identifier.hh"
29 #include "command-request.hh"
30 #include "musical-request.hh"
31 #include "my-lily-parser.hh"
32 #include "text-def.hh"
33 #include "translator-group.hh"
34 #include "score.hh"
35 #include "music-list.hh"
36 #include "header.hh"
37 #include "duration-convert.hh"
38 #include "change-translator.hh"
39 #include "file-results.hh"
40 #include "mudela-version.hh"
41
42 // mmm
43 Mudela_version oldest_version ("0.1.8");
44 Mudela_version version ("0.1.13");
45
46
47 // needed for bison.simple's malloc() and free()
48 #include <malloc.h>
49
50 int const GUESS_PLET = 5;
51 int guess_plet_a[GUESS_PLET] =
52
53   1,
54   3,
55   2,
56   3,
57   4
58 };
59
60 Paper_def* current_paper = 0;
61
62 #ifndef NDEBUG
63 #define YYDEBUG 1
64 #endif
65
66 #define YYERROR_VERBOSE 1
67
68 #define YYPARSE_PARAM my_lily_parser_l
69 #define YYLEX_PARAM my_lily_parser_l
70 #define THIS ((My_lily_parser *) my_lily_parser_l)
71
72 #define yyerror THIS->parser_error
73
74 %}
75
76
77 %union {
78     Array<Interval>* intarr;
79     Array<Melodic_req*> *melreqvec;/* should clean up naming */
80     Array<String> * strvec;
81     Array<int> *intvec;
82     Box *box;
83     Chord * chord;
84     Duration *duration;
85     Identifier *id;
86     Translator* trans;
87     Music *music;
88     Music_list *musiclist;
89     Score *score;
90     Header *header;
91     Interval *interval;
92     Lookup*lookup;
93     Melodic_req * melreq;
94     Musical_req* musreq;
95     Music_output_def * outputdef;
96     Midi_def* midi;
97     Moment *moment;
98     Note_req *notereq;
99     Paper_def *paper;
100     Real real;
101     Request * request;
102     General_script_def * script;
103     Scalar *scalar;
104     String *string;
105     Atom * symbol;
106     Symtable * symtable;
107     Symtables * symtables;
108     Text_def * textdef;
109     Tempo_req *tempo;
110     char c;
111     const char *consstr;
112     int i;
113     int pair[2];
114     int ii[10];
115 }
116 %{
117
118 int
119 yylex (YYSTYPE *s,  void * v_l)
120 {
121         My_lily_parser   *pars_l = (My_lily_parser*) v_l;
122         My_lily_lexer * lex_l = pars_l->lexer_p_;
123
124         lex_l->lexval_l = (void*) s;
125         return lex_l->yylex ();
126 }
127
128
129 %}
130
131 %pure_parser
132
133 /* tokens which are not keywords */
134
135 %token ALIAS
136 %token BAR
137 %token BEAMPLET
138 %token MAEBTELP
139 %token PENALTY
140 %token CADENZA
141 %token CLEAR
142 %token CLEF
143 %token CONTAINS
144 %token CONSISTS
145 %token ACCEPTS
146 %token CM_T
147 %token DURATION
148 %token ABSDYNAMIC
149 %token END
150 %token GROUPING
151 %token TRANSLATOR
152 %token HEADER
153 %token IN_T
154 %token LYRIC
155 %token KEY
156 %token MELODIC
157 %token MIDI
158 %token MELODIC_REQUEST
159 %token METER
160 %token MM_T
161 %token MULTI
162 %token NOTENAMES
163 %token OCTAVE
164 %token OUTPUT
165 %token PAPER
166 %token PARTIAL
167 %token PLET
168 %token TELP
169 %token PT_T
170 %token SCORE
171 %token SCRIPT
172 %token SHAPE
173 %token SKIP
174 %token SPANDYNAMIC
175 %token STAFF
176 %token START_T
177 %token SYMBOLTABLES
178 %token TABLE
179 %token TRANSPOSE
180 %token TEMPO
181 %token TYPE
182 %token TEXID
183 %token MEASURES
184 %token TEXTSTYLE
185 %token TITLE
186 %token PROPERTY
187 %token VERSION
188
189 /* escaped */
190 %token E_EXCLAMATION E_SMALLER E_BIGGER E_CHAR
191
192 %type <i>       dots
193 %token <i>      DIGIT
194 %token <melreq> NOTENAME_ID
195 %token <id>     DURATION_IDENTIFIER
196 %token <id>     IDENTIFIER
197 %token <id>     MELODIC_REQUEST_IDENTIFIER
198 %token <id>     MUSIC_IDENTIFIER
199 %token <id>     VOICE_IDENTIFIER
200 %token <id>     POST_REQUEST_IDENTIFIER
201 %token <id>     SCRIPT_IDENTIFIER
202 %token <id>     COMMAND_IDENTIFIER
203 %token <id>     REAL_IDENTIFIER
204 %token <id>     TRANS_IDENTIFIER
205 %token <id>     INT_IDENTIFIER
206 %token <id>     SCORE_IDENTIFIER
207 %token <id>     MIDI_IDENTIFIER
208 %token <id>     PAPER_IDENTIFIER
209 %token <id>     REQUEST_IDENTIFIER
210 %token <real>   REAL
211 %token <string> DURATION RESTNAME
212 %token <string> STRING
213 %token <i>      UNSIGNED
214 %token <i>      POST_QUOTES
215 %token <i>      PRE_QUOTES
216
217 %type <outputdef> output_def
218 %type <header>  mudela_header mudela_header_body
219 %type <box>     box
220 %type <i>       open_request_parens close_request_parens
221 %type <i>       open_abbrev_parens
222 %type <i>       open_plet_parens close_plet_parens
223 %type <i>       post_quotes pre_quotes
224 %type <music>   simple_element music_elt full_element lyrics_elt command_elt
225 %type <i>       abbrev_type
226 %type <i>       int unsigned
227 %type <i>       script_dir
228 %type <id>      identifier_init
229 %type <duration> explicit_steno_duration notemode_duration
230 %type <duration> entered_notemode_duration explicit_duration
231 %type <interval>        dinterval
232 %type <intvec>  intastint_list
233 %type <lookup>  symtables symtables_body
234 %type <melreq>  melodic_request steno_melodic_req
235 %type <notereq> steno_note_req
236 %type <melreqvec>       pitch_list
237 %type <midi>    midi_block midi_body
238 %type <moment>  duration_length
239
240 %type <scalar>  scalar
241 %type <music>   Music transposed_music
242 %type <music>   property_def translator_change
243 %type <musiclist> Voice Voice_body
244 %type <chord>   Chord Chord_body
245 %type <paper>   paper_block paper_body
246 %type <real>    dim real real_expression
247 %type <real>    real_add_expression real_mult_expression real_primary
248 %type <real>    unit
249 %type <request> abbrev_command_req
250 %type <request> post_request structured_post_request
251 %type <pair>    plet_fraction
252 %type <request> command_req verbose_command_req
253 %type <request> script_req  dynamic_req
254 %type <score>   score_block score_body
255 %type <intarr>  shape_array
256 %type <script>  script_definition script_body mudela_script gen_script_def
257 %type <textdef> text_def finger
258 %type <string>  script_abbreviation
259 %type <symbol>  symboldef
260 %type <symtable>        symtable symtable_body
261 %type <trans>   translator_spec translator_spec_body
262 %type <tempo>   tempo_request
263 %type <string>  concat_strings
264
265 %expect 1
266
267
268 %%
269
270 mudela: /* empty */
271         | mudela mudela_header {
272                 delete THIS->default_header_p_ ;
273                 THIS->default_header_p_ = $2;
274         }
275         | mudela score_block {
276                 score_global_array.push ($2);
277         }
278         | mudela add_declaration { }
279         | mudela error
280         | mudela check_version { }
281         | mudela add_notenames { }
282         ;
283
284 check_version:
285         VERSION STRING ';'              {
286                 Mudela_version ver (*$2);
287                 if (!((ver >= oldest_version) && (ver <= version))) {
288                         if (THIS->ignore_version_b_) {
289                                 THIS->here_input ().error ("Incorrect mudela version");
290                         } else {
291                                 THIS->fatal_error_i_ = 1;
292                                 THIS->parser_error ("Incorrect mudela version");
293                         }
294                 }
295         }
296         ;
297
298 add_notenames:
299         NOTENAMES '{' notenames_body '}'
300         ;
301 notenames_body:
302         /**/    {
303         }
304         | notenames_body CLEAR  {
305                 THIS->clear_notenames ();
306         }
307         | notenames_body STRING '=' melodic_request {
308                 THIS->add_notename (*$2, $4);
309                 delete $2;
310         }
311         ;
312
313 mudela_header_body:
314                 {
315                 $$ = new Header;
316         }
317         | mudela_header_body STRING '=' concat_strings ';' {
318                 (*$$)[*$2] = *$4;
319                 delete $2;
320                 delete $4;
321         }
322         ;
323
324 mudela_header:
325         HEADER '{' mudela_header_body '}'       {
326                 $$ = $3;
327         }
328         ;
329
330
331 concat_strings:
332                 {
333                 $$ = new String;
334         }
335         | concat_strings STRING {
336                 *$$ += *$2;
337         }
338
339
340 /*
341         DECLARATIONS
342 */
343
344 add_declaration:
345         STRING {
346                 THIS->remember_spot ();
347         }
348         /* cont */ '=' identifier_init {
349             THIS->lexer_p_->set_identifier (*$1, $4);
350             $4->init_b_ = THIS->init_parse_b_;
351             $4->set_spot (THIS->pop_spot ());
352         }
353         ;
354
355 identifier_init:
356         score_block {
357                 $$ = new Score_id ($1, SCORE_IDENTIFIER);
358
359         }
360         | paper_block {
361                 $$ = new Paper_def_id ($1, PAPER_IDENTIFIER);
362
363         }
364         | midi_block {
365                 $$ = new Midi_def_id ($1, MIDI_IDENTIFIER);
366
367         }
368         | script_definition {
369                 $$ = new Script_id ($1, SCRIPT_IDENTIFIER);
370
371         }
372         | Music  {
373                 $$ = new Music_id ($1, MUSIC_IDENTIFIER);
374
375         }
376         | symtables {
377                 $$ = new Lookup_id ($1, IDENTIFIER);
378
379         }
380         | real {
381                 $$ = new Real_id (new Real ($1), REAL_IDENTIFIER);
382         }
383         | int   {
384                 $$ = new Int_id (new int ($1), INT_IDENTIFIER);
385         }
386         | post_request {
387                 $$ = new Request_id ($1, POST_REQUEST_IDENTIFIER);
388         }
389         | melodic_request {
390                 $$ = new Request_id ($1, MELODIC_REQUEST_IDENTIFIER);
391
392         }
393         | translator_spec {
394                 $$ = new Translator_id ($1, TRANS_IDENTIFIER);
395         }
396         | explicit_duration {
397                 $$ = new Duration_id ($1, DURATION_IDENTIFIER);
398         }
399         ;
400
401 translator_spec:
402         TRANSLATOR '{' translator_spec_body '}'
403                 { $$ = $3; }
404         ;
405
406 translator_spec_body:
407         TRANS_IDENTIFIER        {
408                 $$ = $1->translator ();
409                 $$-> set_spot (THIS->here_input ());
410         }
411         | TYPE STRING ';'       {
412                 $$ = get_translator_l (*$2)->clone ();
413                 $$->set_spot (THIS->here_input ());
414                 delete $2;
415         }
416         | translator_spec_body STRING '=' scalar ';'    {
417                 $$-> set_property (*$2, *$4);
418                 delete $2;
419                 delete $4;
420         }
421         | translator_spec_body CONSISTS STRING ';'      {
422                 $$->group_l ()->consists_str_arr_.push (*$3);
423                 delete $3;
424         }
425         | translator_spec_body ACCEPTS STRING ';' {
426                 $$->group_l ()->accepts_str_arr_.push (*$3);
427                 delete $3;
428         }
429         ;
430
431 /*
432         SCORE
433 */
434 score_block:
435         SCORE { THIS->remember_spot ();
436                 THIS->error_level_i_ =0;
437         }
438         /*cont*/ '{' score_body '}'     {
439                 $$ = $4;
440                 $$->set_spot (THIS->pop_spot ());
441                 if (!$$->def_p_arr_.size ())
442                         $$->add (THIS->default_paper ());
443
444                 /* handle error levels. */
445                 $$->errorlevel_i_ = THIS->error_level_i_;
446                 THIS->error_level_i_ = 0;
447                 if (!$$->header_p_ && THIS->default_header_p_)
448                         $$->header_p_ = new Header (*THIS->default_header_p_);
449         }
450         ;
451
452 score_body:             {
453                 $$ = new Score;
454         }
455         | SCORE_IDENTIFIER {
456                 $$ = $1->score ();
457         }
458         | score_body mudela_header      {
459                 $$->header_p_ = $2;
460         }
461         | score_body Music      {
462                 if ($$->music_p_)
463                         $2->warning ("More than one music block");      
464                 $$->music_p_ = $2;
465         }
466         | score_body output_def {
467                 $$->add ($2);
468         }
469         | score_body error {
470
471         }
472         ;
473
474 output_def:
475         paper_block {
476                 $$ = $1;
477         }
478         |  midi_block           {
479                 $$= $1;
480         }
481         ;
482
483 intastint_list:
484         /* */   { $$ =new Array<int>; }
485         | intastint_list int '*' int    {
486                 $$->push ($2); $$->push ($4);
487         }
488         ;
489
490
491 /*
492         PAPER
493 */
494 paper_block:
495         PAPER
496         '{' paper_body '}'      { $$ = $3; }
497         ;
498
499 optional_semicolon:
500         /* empty */
501         | ';'
502         ;
503
504 paper_body:
505         /* empty */                     {
506                 $$ = THIS->default_paper ();
507         }
508         | PAPER_IDENTIFIER optional_semicolon   {
509                 $$ = $1->paperdef ();
510         }
511         | paper_body OUTPUT STRING ';'  { 
512                 $$->outfile_str_ = *$3;
513                 delete $3;
514         }
515         | paper_body symtables          { $$->set ($2); }
516         | paper_body STRING '=' real_expression ';'             {
517                 $$->set_var (*$2, $4);
518 // ugh, huh?
519                 current_paper = $$;
520         }
521         | paper_body STRING '=' translator_spec {
522                 $$-> assign_translator (*$2, $4);
523                 delete $2;
524         }
525         | paper_body SHAPE '=' shape_array ';' {
526                 $$->shape_int_a_ = *$4;
527                 delete $4;
528         }
529         | paper_body error {
530
531         }
532         ;
533
534 real_primary:
535         real
536         | dim
537         | STRING {
538 // ugh, huh?
539 //              $$ = THIS->default_paper ()->get_var (*$1);
540                 $$ = current_paper->get_var (*$1);
541         }
542         | '(' real_expression ')' {
543                 $$ = $2;
544         }
545         ;
546
547 real_expression:
548         real_add_expression
549         ;
550
551 real_add_expression:
552         real_mult_expression
553         | real_add_expression '+' real_mult_expression {
554                 $$ = $1 + $3;
555         }
556         | real_add_expression '-' real_mult_expression {
557                 $$ = $1 - $3;
558         }
559         ;
560
561 real_mult_expression:
562         real_primary
563         | real_mult_expression '*' real_primary {
564                 $$ = $1 * $3;
565         }
566         | real_mult_expression '/' real_primary {
567                 $$ = $1 / $3;
568         }
569         ;
570
571 shape_array:
572         /* empty */ {
573                 $$ = new Array<Interval>;
574         }
575         | shape_array dim dim {
576                 $$->push(Interval($2, $2 + $3));
577         };
578
579 /*
580         MIDI
581 */
582 midi_block:
583         MIDI
584
585         '{' midi_body '}'       { $$ = $3; }
586         ;
587
588 midi_body: /* empty */          {
589                 $$ = THIS->default_midi ();
590         }
591         | midi_body STRING '=' translator_spec  {
592                 $$-> assign_translator (*$2, $4);
593                 delete $2;
594         }
595         | midi_body OUTPUT STRING ';'   {
596                 $$->outfile_str_ = *$3;
597                 delete $3;
598         }
599         | midi_body tempo_request ';' {
600                 $$->set_tempo ($2->dur_.length (), $2->metronome_i_);
601                 delete $2;
602         }
603         | midi_body error {
604
605         }
606         ;
607
608 tempo_request:
609         TEMPO entered_notemode_duration '=' unsigned    {
610                 $$ = new Tempo_req;
611                 $$->dur_ = *$2;
612                 delete $2;
613                 $$-> metronome_i_ = $4;
614         }
615         ;
616
617 /*
618         MUSIC
619 */
620
621 Voice:
622         '{' Voice_body '}'      {
623                 $$ = $2;
624         }
625         ;
626
627 Voice_body:
628         /**/            {
629                 $$ = new Voice;
630                 $$->set_spot (THIS->here_input ());
631         }
632         | Voice_body Music              {
633                 $$->add ($2);
634         }
635         ;
636
637 Music:
638         full_element            { $$ = $1; }
639         | TYPE STRING Music     {
640                 $$ = $3;
641                 $$->translator_type_str_ = *$2;
642                 delete $2;
643         }
644         | TYPE STRING '=' STRING Music {
645                 $$ = $5;
646                 $$->translator_type_str_ = *$2;
647                 $$->translator_id_str_ = *$4;
648                 delete $2;
649                 delete $4;
650         }
651         | Voice         { $$ = $1; }
652         | Chord                 { $$ = $1; }
653         | transposed_music      { $$ = $1; }
654         | MUSIC_IDENTIFIER      { $$ = $1->music (); }
655         | MUSIC_IDENTIFIER ';'  { $$ = $1->music (); }
656         | MELODIC
657                 { THIS->lexer_p_->push_note_state (); }
658         Music
659                 { $$=$3; THIS->lexer_p_->pop_state (); }
660
661         | LYRIC
662                 { THIS->lexer_p_->push_lyric_state (); }
663         Music
664                 { $$ = $3; THIS->lexer_p_->pop_state (); }
665         | property_def
666         | translator_change
667         ;
668
669 translator_change:
670         TRANSLATOR STRING '=' STRING  {
671                 Change_translator * t = new Change_translator;
672                 t-> change_to_type_str_ = *$2;
673                 t-> change_to_id_str_ = *$4;
674
675                 $$ = t;
676                 $$->set_spot (THIS->here_input ());
677                 delete $2;
678                 delete $4;
679         }
680         ;
681
682 property_def:
683         PROPERTY STRING '.' STRING '=' scalar   {
684                 Translation_property *t = new Translation_property;
685                 t-> translator_type_str_ = *$2;
686                 t-> var_str_ = *$4;
687                 t-> value_ = *$6;
688                 $$ = t;
689                 $$->set_spot (THIS->here_input ());
690                 delete $2;
691                 delete $4;
692                 delete $6;
693         }
694         ;
695
696 scalar:
697         STRING          { $$ = new Scalar (*$1); delete $1; }
698         | int           { $$ = new Scalar ($1); }
699         ;
700
701
702 Chord:
703         '<' Chord_body '>'      { $$  = $2; }
704         | MULTI unsigned Chord {
705                 $$ = $3;
706                 $$->multi_level_i_=$2;
707         }
708         ;
709
710 Chord_body:
711         /**/    {
712                 $$ = new Chord;
713                 $$-> multi_level_i_ = 1;
714                 $$->set_spot (THIS->here_input ());
715         }
716         | Chord_body Music {
717                 $$->add ($2);
718         }
719         ;
720
721 transposed_music:
722         TRANSPOSE steno_melodic_req Music {
723                 $$ = $3;
724                 $$ -> transpose ($2);
725
726                 delete $2;
727         }
728         ;
729
730
731 /*
732         VOICE ELEMENTS
733 */
734 full_element:
735         pre_requests simple_element post_requests       {
736                 THIS->add_requests ((Chord*)$2);//ugh
737                 $$ = $2;
738         }
739         | command_elt
740         | voice_command ';'     { $$ = 0; }
741         ;
742
743 simple_element:
744         music_elt
745         | lyrics_elt
746         ;
747
748 command_elt:
749         command_req {
750                 $$ = new Request_chord;
751                 $$-> set_spot (THIS->here_input ());
752                 $1-> set_spot (THIS->here_input ());
753                 ((Chord*)$$) ->add ($1);//ugh
754
755         }
756         ;
757
758 command_req:
759         abbrev_command_req
760         | verbose_command_req ';'       { $$ = $1; }
761         ;
762
763 abbrev_command_req:
764         '|'                             {
765                 $$ = new Barcheck_req;
766         }
767         | COMMAND_IDENTIFIER    {
768                 $$ = $1->request ();
769         }
770         ;
771
772 verbose_command_req:
773         BAR STRING                      {
774                 $$ = new Bar_req (*$2);
775                 delete $2;
776         }
777         | PENALTY '=' int       {
778                 Break_req * b = new Break_req;
779                 b->penalty_i_ = $3;
780                 b-> set_spot (THIS->here_input ());
781                 $$ = b;
782         }
783         | METER unsigned '/' unsigned   {
784                 Meter_change_req *m = new Meter_change_req;
785                 m->set ($2,$4);
786                 $$ = m;
787         }
788         | SKIP duration_length {
789                 Skip_req * skip_p = new Skip_req;
790                 skip_p->duration_.set_plet ($2->num (),
791                         $2->den ());
792
793                 delete $2;
794                 $$ = skip_p;
795         }
796         | tempo_request {
797                 $$ = $1;
798         }
799         | CADENZA unsigned      {
800                 $$ = new Cadenza_req ($2);
801         }
802         | PARTIAL duration_length       {
803                 $$ = new Partial_measure_req (*$2);
804                 delete $2;
805         }
806         | CLEF STRING {
807                 $$ = new Clef_change_req (*$2);
808                 delete $2;
809         }
810         | KEY pitch_list        {
811                 Key_change_req *key_p= new Key_change_req;
812                 key_p->melodic_p_arr_ = *$2;
813                 $$ = key_p;
814                 delete $2;
815         }
816         | GROUPING intastint_list {
817                 $$ = get_grouping_req (*$2); delete $2;
818         }
819         ;
820
821 post_requests:
822         {
823                 /* something silly happened.  Junk this stuff*/
824                 if (!THIS->post_reqs.empty ())
825                 {
826                         warning ("Junking post-requests");
827                         THIS->post_reqs.clear ();
828                 }
829         }
830         | post_requests structured_post_request {
831                 $2->set_spot (THIS->here_input ());
832                 THIS->post_reqs.push ($2);
833         }
834         | post_requests close_request_parens    {
835                 Array<Request*>& r = *THIS->get_parens_request ($2);
836                 for (int i = 0; i < r.size (); i++ )
837                         r[i]->set_spot (THIS->here_input ());
838                 THIS->post_reqs.concat (r);
839                 delete &r;
840         }
841         ;
842
843 structured_post_request:
844         script_req
845         | post_request
846         ;
847
848 post_request:
849         POST_REQUEST_IDENTIFIER {
850                 $$ = (Request*)$1->request ();
851         }
852         | dynamic_req {
853                 $$ = $1;
854         }
855         | abbrev_type   {
856                 Abbreviation_req* a = new Abbreviation_req;
857                 a->type_i_ = $1;
858                 $$ = a;
859         }
860         ;
861
862 pre_quotes:
863         PRE_QUOTES {
864 //              int i = $1;
865                 $$ = $1;
866         }
867         | pre_quotes PRE_QUOTES {
868 //              int i = $1 + $2;
869                 $$ =  $1 + $2;
870         }
871         ;
872
873 post_quotes:
874         POST_QUOTES {
875 //              int i = $1;
876                 $$ = $1;
877         }
878         | post_quotes POST_QUOTES {
879 //              int i = $1 + $2;
880                 $$ = $1 + $2;
881         }
882         ;
883
884 /*
885         URG!!
886
887         Whitespace mustn't be stripped.  So what?
888         Python is cool, and there even the amount *and* type of whitespace
889         is significant.  So this is not uncool per se, maybe context-free
890         just sucks for humans.
891         jcn
892 */
893 steno_melodic_req:
894         NOTENAME_ID     {
895                 Melodic_req* m =  $1->clone ()->musical ()->melodic ();
896                 $$ = THIS->get_melodic_req (m, 0 + THIS->default_octave_i_);
897         }
898         | NOTENAME_ID post_quotes       {
899                 Melodic_req* m =  $1->clone ()->musical ()->melodic ();
900                 $$ = THIS->get_melodic_req (m, $2 + THIS->default_octave_i_);
901         }
902         | pre_quotes NOTENAME_ID         {
903                 Melodic_req* m =  $2->clone ()->musical ()->melodic ();
904                 $$ = THIS->get_melodic_req (m, -$1 + THIS->default_octave_i_);
905         }
906         ;
907
908 steno_note_req:
909         steno_melodic_req       {
910                 $$ = new Note_req;
911                 *(Melodic_req *) $$ = *$1;
912                 delete $1;
913         }
914         | steno_note_req   '!'          {
915                 $$->forceacc_b_ = ! $$->forceacc_b_;
916         }
917         /* have to duration here. */
918         ;
919
920 melodic_request:
921         MELODIC_REQUEST '{' int int int '}'     {/* ugh */
922                 $$ = new Melodic_req;
923                 $$->octave_i_ = $3;
924                 $$->notename_i_ = $4;
925                 $$->accidental_i_ = $5;
926         }
927         ;
928
929 explicit_duration:
930         DURATION '{' int unsigned '}'   {
931                 $$ = new Duration;
932                 $$-> durlog_i_ = $3;
933                 $$-> dots_i_ = $4;
934         }
935         ;
936
937 dynamic_req:
938         ABSDYNAMIC '{' unsigned '}'     {
939                 Absolute_dynamic_req *ad_p = new Absolute_dynamic_req;
940                 ad_p ->loudness_ = (Dynamic_req::Loudness)$3;
941                 $$ =ad_p;
942         }
943         | SPANDYNAMIC '{' int int '}' {
944                 Span_dynamic_req * sp_p = new Span_dynamic_req;
945                 sp_p->spantype = (Span_req::Spantype)$4;
946                 sp_p-> dynamic_dir_  = (Direction)$3;
947                 $$ = sp_p;
948         }
949         ;
950
951 plet_fraction:
952         unsigned '/' unsigned {
953                 $$[0] = $1;
954                 $$[1] = $3;
955         }
956         |
957         '/' unsigned {
958                 int num = $2 >? 1;
959                 $$[0] = guess_plet_a[(num <? GUESS_PLET) - 1];
960                 $$[1] = num;
961         }
962         ;
963
964 close_plet_parens:
965         ']' plet_fraction {
966                 $$ = MAEBTELP;
967                 THIS->plet_.type_i_ = $2[1];
968                 THIS->plet_.iso_i_ = $2[0];
969                 THIS->default_duration_.plet_.type_i_ = $2[1];
970                 THIS->default_duration_.plet_.iso_i_ = $2[0];
971         }
972         | TELP {
973                 $$ = TELP;
974                 THIS->plet_.type_i_ = 1;
975                 THIS->plet_.iso_i_ = 1;
976                 THIS->default_duration_.plet_.iso_i_ = 1;
977                 THIS->default_duration_.plet_.type_i_ = 1;
978         }
979         | TELP plet_fraction {
980                 $$ = TELP;
981                 THIS->plet_.type_i_ = $2[1];
982                 THIS->plet_.iso_i_ = $2[0];
983                 THIS->default_duration_.plet_.type_i_ = $2[1];
984                 THIS->default_duration_.plet_.iso_i_ = $2[0];
985         }
986         ;
987
988 close_request_parens:
989         '~'     {
990                 $$ = '~';
991         }
992         | '('   {
993                 $$='(';
994         }
995         | ']'   {
996                 $$ = ']';
997         }
998         | E_SMALLER {
999                 $$ = '<';
1000         }
1001         | E_BIGGER {
1002                 $$ = '>';
1003         }
1004         | close_plet_parens
1005         ;
1006
1007 open_abbrev_parens:
1008         '[' ':' unsigned {
1009                 $$ = '[';
1010                 if (!Duration::duration_type_b ($3))
1011                         THIS->parser_error (String ("Not a duration: ") + $3);
1012                 else if ($3 < 8)
1013                         THIS->parser_error ("Can't abbreviate");
1014                 else
1015                         THIS->set_abbrev_beam ($3);
1016         }
1017         ;
1018
1019 open_plet_parens:
1020         '[' plet_fraction {
1021                 $$ = BEAMPLET;
1022                 THIS->plet_.type_i_ = $2[1];
1023                 THIS->plet_.iso_i_ = $2[0];
1024                 THIS->default_duration_.plet_.type_i_ = $2[1];
1025                 THIS->default_duration_.plet_.iso_i_ = $2[0];
1026         }
1027         | PLET plet_fraction {
1028                 $$ = PLET;
1029                 THIS->plet_.type_i_ = $2[1];
1030                 THIS->plet_.iso_i_ = $2[0];
1031                 THIS->default_duration_.plet_.type_i_ = $2[1];
1032                 THIS->default_duration_.plet_.iso_i_ = $2[0];
1033         }
1034         ;
1035
1036 open_request_parens:
1037         E_EXCLAMATION   {
1038                 $$ = '!';
1039         }
1040         | ')'   {
1041                 $$=')';
1042         }
1043         | '['   {
1044                 $$='[';
1045         }
1046         | open_abbrev_parens
1047         | open_plet_parens
1048         ;
1049
1050
1051
1052 script_definition:
1053         SCRIPT '{' script_body '}'      { $$ = $3; }
1054         ;
1055
1056 script_body:
1057         STRING int int int int int              {
1058                 Script_def *s = new Script_def;
1059                 s->set_from_input (*$1,$2, $3,$4,$5, $6);
1060                 $$  = s;
1061                 delete $1;
1062         }
1063         ;
1064
1065 script_req:
1066         script_dir gen_script_def       {
1067                 Musical_script_req *m = new Musical_script_req;
1068                 $$ = m;
1069                 m->scriptdef_p_ = $2;
1070                 m->set_spot (THIS->here_input ());
1071                 if (!m->dir_)
1072                   m->dir_  = (Direction)$1;
1073         }
1074         ;
1075
1076 gen_script_def:
1077         text_def        { 
1078                 $$ = $1;
1079                 ((Text_def*) $$)->align_i_ = CENTER; /* UGH */
1080         }
1081         | mudela_script { 
1082                 $$ = $1;
1083                 $$-> set_spot (THIS->here_input ());
1084         }
1085         | finger {
1086                 $$ = $1;
1087                 ((Text_def*)$$)->align_i_ = CENTER;
1088         }
1089         ;
1090
1091 text_def:
1092         STRING {
1093                 Text_def *t  = new Text_def;
1094                 $$ = t;
1095                 t->text_str_ = *$1;
1096                 delete $1;
1097                 t->style_str_ = THIS->textstyle_str_;
1098                 $$->set_spot (THIS->here_input ());
1099         }
1100         ;
1101
1102 finger:
1103          DIGIT {
1104                 Text_def* t  = new Text_def;
1105                 $$ = t;
1106                 t->text_str_ = String ($1);
1107                 t->style_str_ = "finger";
1108                 $$->set_spot (THIS->here_input ());
1109         }
1110         ;
1111
1112 script_abbreviation:
1113         '^'             { $$ = get_scriptdef ('^'); }
1114         | '+'           { $$ = get_scriptdef ('+'); }
1115         | '-'           { $$ = get_scriptdef ('-'); }
1116         | '|'           { $$ = get_scriptdef ('|'); }
1117         | 'o'           { $$ = get_scriptdef ('o'); }
1118         | '>'           { $$ = get_scriptdef ('>'); }
1119         | '.'           {
1120                 $$ = get_scriptdef ('.');
1121         }
1122         ;
1123
1124 mudela_script:
1125         SCRIPT_IDENTIFIER               { $$ = $1->script (); }
1126         | script_definition             { $$ = $1; }
1127         | script_abbreviation           {
1128                 $$ = THIS->lexer_p_->lookup_identifier (*$1)->script ();
1129                 delete $1;
1130         }
1131         ;
1132
1133 script_dir:
1134         '_'     { $$ = -1; }
1135         | '^'   { $$ = 1; }
1136         | '-'   { $$ = 0; }
1137         ;
1138
1139 pre_requests:
1140         {
1141         }
1142         | pre_requests open_request_parens {
1143                 Array<Request*>& r = *THIS->get_parens_request ($2);
1144                 for (int i = 0; i < r.size (); i++ )
1145                         r[i]->set_spot (THIS->here_input ());
1146                 THIS->pre_reqs.concat (r);
1147                 delete &r;
1148         }
1149         ;
1150
1151 voice_command:
1152         DURATION STRING {
1153                 THIS->set_duration_mode (*$2);
1154                 delete $2;
1155         }
1156         | DURATION entered_notemode_duration {
1157                 THIS->set_default_duration ($2);
1158                 delete $2;
1159         }
1160         | OCTAVE {
1161                 /*
1162                         This is weird, but default_octave_i_
1163                         is used in steno_note_req too
1164
1165                         c' -> default_octave_i_ == 1
1166                 */
1167                 /* why can't we have \oct 0 iso \oct{c'}*/
1168                 THIS->default_octave_i_ = 1; }
1169 /* cont */
1170         steno_melodic_req {
1171                 THIS->default_octave_i_ = $3->octave_i_;
1172                 delete $3;
1173         }
1174         | OCTAVE STRING {
1175                 THIS->set_octave_mode (*$2);
1176                 delete $2;
1177         }
1178         | TEXTSTYLE STRING      {
1179                 THIS->textstyle_str_ = *$2;
1180                 delete $2;
1181         }
1182         ;
1183
1184 duration_length:
1185         {
1186                 $$ = new Moment (0,1);
1187         }
1188         | duration_length explicit_steno_duration               {
1189                 *$$ += $2->length ();
1190         }
1191         ;
1192
1193 dots:
1194         '.'             { $$ = 1; }
1195         | dots '.'      { $$ ++; }
1196         ;
1197
1198 entered_notemode_duration:
1199         /* */           {
1200                 $$ = new Duration (THIS->default_duration_);
1201                 // get sticky plet part too
1202                 $$->set_plet (THIS->plet_.iso_i_, THIS->plet_.type_i_);
1203         }
1204         | dots          {
1205                 $$ = new Duration (THIS->default_duration_);
1206                 // get sticky plet part too
1207                 $$->set_plet (THIS->plet_.iso_i_, THIS->plet_.type_i_);
1208                 $$->dots_i_  = $1;
1209         }
1210         | explicit_steno_duration       {
1211                 THIS->set_last_duration ($1);
1212                 $$ = $1;
1213         }
1214         ;
1215
1216 notemode_duration:
1217         entered_notemode_duration {
1218                 $$ = $1;
1219         }
1220         ;
1221
1222 explicit_steno_duration:
1223         unsigned                {
1224                 $$ = new Duration;
1225                 if (!Duration::duration_type_b ($1))
1226                         THIS->parser_error ("Not a duration:" + String ($1));
1227                 else {
1228                         $$->durlog_i_ = Duration_convert::i2_type ($1);
1229                         $$->set_plet (THIS->plet_.iso_i_, THIS->plet_.type_i_);
1230                      }
1231         }
1232         | DURATION_IDENTIFIER   {
1233                 $$ = $1->duration ();
1234         }
1235         | explicit_steno_duration '.'   {
1236                 $$->dots_i_ ++;
1237         }
1238         | explicit_steno_duration '*' unsigned  {
1239                 $$->plet_.iso_i_ = $3;  /* ugh.  should do *= */
1240         }
1241         | explicit_steno_duration '/' unsigned {
1242                 $$->plet_.type_i_ = $3; /* ugh. should do *= iso = */
1243         }
1244         ;
1245
1246
1247 abbrev_type: 
1248         ':'     {
1249                 $$ =0;
1250         }
1251         | ':' unsigned {
1252                 if (!Duration::duration_type_b ($2))
1253                         THIS->parser_error ("Not a duration:" + String ($2));
1254                 else if ($2 < 8)
1255                         THIS->parser_error ("Can't abbreviate");
1256                 $$ = $2;
1257         }
1258
1259         ;
1260
1261 music_elt:
1262         steno_note_req notemode_duration  {
1263                 if (!THIS->lexer_p_->note_state_b ())
1264                         THIS->parser_error ("have to be in Note mode for notes");
1265                 $1->set_duration (*$2);
1266                 int durlog_i = $2->durlog_i_;
1267                 $$ = THIS->get_note_element ($1, $2);
1268         }
1269         | RESTNAME notemode_duration            {
1270                 $$ = THIS->get_rest_element (*$1, $2);
1271                 delete $1;  // delete notename
1272         }
1273         | MEASURES notemode_duration    {
1274                 Multi_measure_rest_req* m = new Multi_measure_rest_req;
1275                 m->duration_ = *$2;
1276                 delete $2;
1277
1278                 Chord*velt_p = new Request_chord;
1279                 velt_p->set_spot (THIS->here_input ());
1280                 velt_p->add (m);
1281                 $$ = velt_p;
1282
1283         }
1284         ;
1285
1286 lyrics_elt:
1287         text_def notemode_duration                      {
1288         /* this sux! text-def should be feature of lyric-engraver. */
1289                 if (!THIS->lexer_p_->lyric_state_b ())
1290                         THIS->parser_error ("Have to be in Lyric mode for lyrics");
1291                 $$ = THIS->get_word_element ($1, $2);
1292
1293         };
1294
1295 /*
1296         UTILITIES
1297  */
1298 pitch_list:                     {
1299                 $$ = new Array<Melodic_req*>;
1300         }
1301         | pitch_list NOTENAME_ID        {
1302                 $$->push ($2->clone ()->musical ()->melodic ());
1303         }
1304         ;
1305
1306 unsigned:
1307         UNSIGNED        {
1308                 $$ = $1;
1309         }
1310         | DIGIT {
1311                 $$ = $1;
1312         };
1313
1314 int:
1315         unsigned {
1316                 $$ = $1;
1317         }
1318         | '-' unsigned {
1319                 $$ = -$2;
1320         }
1321         | INT_IDENTIFIER        {
1322                 int *i_p = $1->intid ();
1323                 $$ = *i_p;
1324                 delete i_p;
1325         }
1326         ;
1327
1328 real:
1329         REAL            {
1330                 $$ = $1;
1331         }
1332         | REAL_IDENTIFIER               {
1333                 Real *r_p = $1->real ();
1334                 $$ = * r_p;
1335                 delete r_p;
1336         }
1337         ;
1338
1339
1340
1341 dim:
1342         real unit       { $$ = $1*$2; }
1343         ;
1344
1345
1346 unit:   CM_T            { $$ = 1 CM; }
1347         |IN_T           { $$ = 1 INCH; }
1348         |MM_T           { $$ = 1 MM; }
1349         |PT_T           { $$ = 1 PT; }
1350         ;
1351
1352 /*
1353         symbol tables
1354 */
1355 symtables:
1356         SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
1357         ;
1358
1359 symtables_body:
1360                         {
1361                 $$ = new Lookup;
1362         }
1363         | IDENTIFIER            {
1364                 $$ = $1->lookup ();
1365         }
1366         | symtables_body TEXID STRING           {
1367                 $$->texsetting = *$3;
1368                 delete $3;
1369         }
1370         | symtables_body STRING '=' symtable            {
1371                 $$->add (*$2, $4);
1372                 delete $2;
1373         }
1374         ;
1375
1376 symtable:
1377         TABLE '{' symtable_body '}' { $$ = $3; }
1378         ;
1379
1380 symtable_body:
1381                                 { $$ = new Symtable; }
1382         | symtable_body STRING  symboldef {
1383                 $$->add (*$2, *$3);
1384                 delete $2;
1385                 delete $3;
1386         }
1387         ;
1388
1389 symboldef:
1390         STRING  box             {
1391                 $$ = new Atom (*$1, *$2);
1392                 delete $1;
1393                 delete $2;
1394         }
1395         | STRING {
1396                 Box b (Interval (0,0), Interval (0,0));
1397                 $$ = new Atom (*$1, b);
1398                 delete $1;
1399         }
1400         ;
1401
1402 box:
1403         dinterval dinterval     {
1404                 $$ = new Box (*$1, *$2);
1405                 delete $1;
1406                 delete $2;
1407         }
1408         ;
1409
1410 dinterval: dim  dim             {
1411                 $$ = new Interval ($1, $2);
1412         }
1413         ;
1414
1415 %%
1416
1417 void
1418 My_lily_parser::set_yydebug (bool b)
1419 {
1420 #ifdef YYDEBUG
1421         yydebug = b;
1422 #endif
1423 }
1424 void
1425 My_lily_parser::do_yyparse ()
1426 {
1427         yyparse ((void*)this);
1428 }
1429
1430 Paper_def*
1431 My_lily_parser::default_paper ()
1432 {
1433         Identifier *id = lexer_p_->lookup_identifier ("default_paper");
1434         return id ? id->paperdef () : new Paper_def ;
1435 }
1436
1437 Midi_def*
1438 My_lily_parser::default_midi ()
1439 {
1440         Identifier *id = lexer_p_->lookup_identifier ("default_midi");
1441         return id ? id->mididef () : new Midi_def ;
1442 }
1443