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