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