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