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