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