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