]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.y
release: 0.0.72pre
[lilypond.git] / lily / parser.y
1 %{ // -*-Fundamental-*-
2 #include <iostream.h>
3
4 #define MUDELA_VERSION "0.0.61"
5
6 #include "script-def.hh"
7 #include "symtable.hh"
8 #include "lookup.hh"
9 #include "misc.hh"
10 #include "my-lily-lexer.hh"
11 #include "paper-def.hh"
12 #include "midi-def.hh"
13 #include "main.hh"
14 #include "keyword.hh"
15 #include "debug.hh"
16 #include "parseconstruct.hh"
17 #include "dimen.hh"
18 #include "identifier.hh"
19 #include "command-request.hh"
20 #include "musical-request.hh"
21 #include "my-lily-parser.hh"
22 #include "text-def.hh"
23 #include "input-engraver.hh"
24 #include "score.hh"
25 #include "music-list.hh"
26
27 #ifndef NDEBUG
28 #define YYDEBUG 1
29 #endif
30
31 #define YYERROR_VERBOSE 1
32
33 #define YYPARSE_PARAM my_lily_parser_l
34 #define YYLEX_PARAM my_lily_parser_l
35 #define THIS ((My_lily_parser *) my_lily_parser_l)
36
37 #define yyerror THIS->parser_error
38
39 %}
40
41
42 %union {
43     Array<Melodic_req*> *melreqvec;/* should clean up naming */
44     Array<String> * strvec;
45     Array<int> *intvec;
46     Box *box;
47     Chord * chord;
48     Duration *duration;
49     Identifier *id;    
50     Input_engraver * iregs;
51     Music *music;
52     Music_list *musiclist;
53     Score *score;
54     Interval *interval;
55     Lookup*lookup;
56     Melodic_req * melreq;
57     Midi_def* midi;
58     Moment *moment;
59     Note_req *notereq;
60     Paper_def *paper;
61     Real real;
62     Request * request;
63     General_script_def * script;
64     String *string;
65     Symbol * symbol;
66     Symtable * symtable;
67     Symtables * symtables;
68     Text_def * textdef;
69     char c;
70     const char *consstr;
71     int i;
72     int ii[10];
73 }
74 %{
75
76 int 
77 yylex(YYSTYPE *s,  void * v_l)
78 {
79         My_lily_parser   *pars_l = (My_lily_parser*) v_l;
80         My_lily_lexer * lex_l = pars_l->lexer_p_;
81         
82         lex_l->lexval_l = (void*) s;
83         return lex_l->yylex();
84 }
85
86
87 %}
88
89 %pure_parser
90
91 /* tokens which are not keywords */
92 %token CONCAT
93
94 %token ALIAS
95 %token BAR
96 %token CADENZA
97 %token CLEAR
98 %token CLEF
99 %token CONTAINS
100 %token CONSISTS
101 %token ACCEPTS
102 %token CM_T
103 %token DURATIONCOMMAND
104 %token ABSDYNAMIC
105 %token END
106 %token GEOMETRIC
107 %token GROUPING
108 %token GROUP
109 %token REQUESTENGRAVER
110 %token HSHIFT
111 %token IN_T
112 %token ID
113 %token INIT_END
114 %token LYRIC
115 %token KEY
116 %token MELODIC
117 %token MELODIC_REQUEST
118 %token METER
119 %token MIDI
120 %token MM_T
121 %token MULTI
122 %token NOTE
123 %token NOTENAMES
124 %token OCTAVECOMMAND
125 %token OUTPUT
126 %token PAPER
127 %token PARTIAL
128 %token PLET
129 %token PT_T
130 %token SCORE
131 %token SCRIPT
132 %token SKIP
133 %token SPANDYNAMIC
134 %token STAFF
135 %token START_T
136 %token STEM
137 %token SYMBOLTABLES
138 %token TABLE
139 %token TRANSPOSE
140 %token TEMPO
141 %token TEXID
142 %token TEXTSTYLE
143 %token TITLE
144 %token UNITSPACE
145 %token WIDTH
146 %token VERSION
147
148 /* escaped */
149 %token E_EXCLAMATION E_SMALLER E_BIGGER E_CHAR
150
151 %type <i>       dots
152 %token <i>      INT
153 %token <melreq> NOTENAME_ID
154 %token <id>     IDENTIFIER
155 %token <id>     MELODIC_REQUEST_IDENTIFIER 
156 %token <id>     MUSIC_IDENTIFIER
157 %token <id>     VOICE_IDENTIFIER
158 %token <id>     POST_REQUEST_IDENTIFIER
159 %token <id>     SCRIPT_IDENTIFIER
160 %token <id>     STAFF_IDENTIFIER
161 %token <id>     REAL_IDENTIFIER
162 %token <id>     INT_IDENTIFIER
163 %token <id>     SCORE_IDENTIFIER
164 %token <id>     PAPER_IDENTIFIER
165 %token <id>     REQUEST_IDENTIFIER
166 %token <real>   REAL 
167 %token <string> DURATION RESTNAME
168 %token <string> STRING
169 %token <i>      POST_QUOTES 
170 %token <i>      PRE_QUOTES
171
172
173 %type <box>     box
174 %type <c>       open_request_parens close_request_parens
175 %type <c>       open_plet_parens close_plet_parens
176 %type <music>   simple_element music_elt full_element lyrics_elt command_elt
177 %type <i>       int
178 %type <i>       script_dir
179 %type <id>      declaration
180 %type <duration>        explicit_duration notemode_duration
181 %type <interval>        dinterval
182 %type <intvec>  intastint_list
183 %type <lookup>  symtables symtables_body
184 %type <melreq>  melodic_request steno_melodic_req
185 %type <notereq> steno_note_req
186 %type <melreqvec>       pitch_list 
187 %type <midi>    midi_block midi_body
188 %type <moment>  duration_length
189
190 %type <music>   Music transposed_music
191 %type <musiclist> Voice Voice_body 
192 %type <chord>   Chord Chord_body
193 %type <paper>   paper_block paper_body
194 %type <real>    dim real
195 %type <real>    unit
196 %type <request> post_request pre_request command_req verbose_command_req abbrev_command_req
197 %type <request> script_req  dynamic_req 
198 %type <score>   score_block score_body
199 %type <script>  script_definition script_body mudela_script gen_script_def
200 %type <textdef> text_def
201 %type <string>  declarable_identifier
202 %type <string>  script_abbreviation
203 %type <id>      old_identifier
204 %type <symbol>  symboldef
205 %type <symtable>        symtable symtable_body
206 %type <iregs>   input_engraver_spec input_engraver_spec_body
207
208 %left PRIORITY
209
210 %%
211
212 mudela: /* empty */
213         | mudela score_block {
214                 add_score($2);          
215         }
216         | mudela add_declaration { }
217         | mudela error
218         | mudela check_version { } 
219         | mudela add_notenames { }
220         | mudela input_engraver_spec { add_global_input_engraver($2); }
221         ;
222
223 check_version:
224         VERSION STRING ';'              {
225                 if (*$2 != MUDELA_VERSION) {
226                         if (THIS->ignore_version_b_) {
227                                 THIS->here_input().error("Incorrect mudela version");
228                         } else {
229                                 THIS->fatal_error_i_ = 1;
230                                 THIS->parser_error("Incorrect mudela version");
231                         }
232                 }
233         }
234         ;
235
236 add_notenames:
237         NOTENAMES '{' notenames_body '}'
238         ;
239 notenames_body:
240         /**/    {
241         }
242         | notenames_body CLEAR  {
243                 THIS->clear_notenames();
244         }
245         | notenames_body STRING '=' melodic_request {
246                 THIS->add_notename(*$2, $4);
247                 delete $2;
248         }
249         ;
250 /*
251         DECLARATIONS
252 */
253 add_declaration: declaration    {
254                 THIS->lexer_p_->add_identifier($1);
255                 $1->init_b_ = THIS->init_parse_b_;
256                 $1->set_spot(THIS->pop_spot());
257         }
258         ;
259
260 declarable_identifier:
261         STRING {
262                 THIS->remember_spot();
263             $$ = $1;
264         }
265         | old_identifier { 
266                 THIS->remember_spot();
267                 $$ = new String($1->name_str_); 
268                 THIS->here_input().warning("redeclaration of `" + *$$ + "'");
269         }
270         ;
271
272
273 old_identifier:
274         IDENTIFIER
275         |       MELODIC_REQUEST_IDENTIFIER 
276         |       POST_REQUEST_IDENTIFIER
277         |       SCRIPT_IDENTIFIER
278         |       REAL_IDENTIFIER
279         |       SCORE_IDENTIFIER
280         |       REQUEST_IDENTIFIER
281         ;
282
283 declaration:
284         declarable_identifier '=' score_block {
285                 $$ = new Score_id(*$1, $3, SCORE_IDENTIFIER);
286                 delete $1;
287         }
288         | declarable_identifier '=' paper_block {
289                 $$ = new Paper_def_id(*$1, $3, PAPER_IDENTIFIER);
290                 delete $1;
291         }
292         | declarable_identifier '=' script_definition {
293                 $$ = new Script_id(*$1, $3, SCRIPT_IDENTIFIER);
294                 delete $1;
295         }
296         | declarable_identifier '=' Music  {
297                 $$ = new Music_id(*$1, $3, MUSIC_IDENTIFIER);
298                 delete $1;
299         }
300         | declarable_identifier '=' symtables {
301                 $$ = new Lookup_id(*$1, $3, IDENTIFIER);
302                 delete $1;
303         }
304         | declarable_identifier '=' real        {
305                 $$ = new Real_id(*$1, new Real($3), REAL_IDENTIFIER);
306                 delete $1;
307         }
308         
309         | declarable_identifier '=' post_request {
310                 $$ = new Request_id(*$1, $3, POST_REQUEST_IDENTIFIER);
311                 delete $1;
312         }
313         | declarable_identifier '=' melodic_request {
314                 $$ = new Request_id(*$1, $3, MELODIC_REQUEST_IDENTIFIER);
315                 delete $1;
316         }
317         ;
318
319
320
321 input_engraver_spec:
322         REQUESTENGRAVER '{' input_engraver_spec_body '}'
323                 { $$ = $3; }
324         ;
325
326 input_engraver_spec_body:
327         STRING  { 
328                 $$ = new Input_engraver; 
329                 $$->name_str_ =*$1;
330                 delete $1;
331         }
332         | input_engraver_spec_body ALIAS STRING ';' {
333                 $$-> alias_str_arr_.push(*$3);
334                 delete $3;
335         }
336         | input_engraver_spec_body CONSISTS STRING ';'  {
337                 $$-> consists_str_arr_.push(*$3);
338                 delete $3;
339         }
340         | input_engraver_spec_body CONTAINS input_engraver_spec {
341                 $$->add($3);
342         }
343         ;
344 /*
345         SCORE
346 */
347 score_block:
348         SCORE { THIS->remember_spot(); }
349         /*cont*/ '{' score_body '}'     {
350                 $$ = $4;
351                 $$->set_spot(THIS->pop_spot());
352                 if (!$$->paper_p_ && ! $$->midi_p_)
353                         $$->paper_p_ = THIS->default_paper();
354
355                 /* handle error levels. */
356                 $$->errorlevel_i_ = THIS->error_level_i_;
357                 THIS->error_level_i_ = 0;
358         }
359         ;
360
361 score_body:             { 
362                 $$ = new Score; 
363         }
364         | SCORE_IDENTIFIER {
365                 $$ = $1->score(true);
366         }
367         | score_body Music      {
368                 $$->music_p_ = $2;
369         }
370         | score_body paper_block                {
371                 $$->paper_p_ = $2;      
372         }
373         | score_body midi_block         { 
374                 $$->midi_p_ = $2;
375         }
376         | score_body error {
377
378         }
379         ;
380
381 intastint_list:
382         /* */   { $$ =new Array<int>; }
383         | intastint_list int '*' int    {
384                 $$->push($2); $$->push($4);
385         }
386         ;
387
388
389 /*
390         PAPER
391 */
392 paper_block:
393         PAPER
394         '{' paper_body '}'      { $$ = $3; }
395         ;
396
397 paper_body:
398         /* empty */                     {
399                 $$ = THIS->default_paper();
400         }
401         | paper_body OUTPUT STRING ';'  { $$->outfile_str_ = *$3;
402                 delete $3;
403         }
404         | paper_body symtables          { $$->set($2); }
405         | paper_body STRING '=' dim ';'         { 
406                 $$->set_var(*$2, $4);
407         }
408         | paper_body STRING '=' REAL ';' {
409                 $$->set_var(*$2, $4);
410         }
411         | paper_body error {
412
413         }
414         ;
415
416 /*
417         MIDI
418 */
419 midi_block:
420         MIDI
421
422         '{' midi_body '}'       { $$ = $3; }
423         ;
424
425 midi_body: { 
426                 $$ = new Midi_def; 
427         }
428         | midi_body OUTPUT STRING ';'   { 
429                 $$->outfile_str_ = *$3; 
430                 delete $3; 
431         }
432         | midi_body TEMPO notemode_duration ':' int ';' {
433                 $$->set_tempo( $3->length(), $5 );
434         }
435         | midi_body error {
436
437         }
438         ;
439
440
441
442
443 /*
444         MUSIC
445 */
446
447 Voice:
448         '{' Voice_body '}'      {
449                 $$ = $2;
450         }
451         ;
452
453 Voice_body:
454         /**/            {
455                 $$ = new Voice;
456         }
457         | Voice_body ID STRING STRING ';'       {
458                 $$ = new Voice;
459                 $$->type_str_ = *$3;    
460                 $$->id_str_ = *$4;
461                 delete $3;
462                 delete $4;
463         }
464         | Voice_body Music              {
465                 $$->add($2);
466         }
467         ;
468
469 Music:
470         full_element            { $$ = $1; }
471         | Voice         { $$ = $1; }
472         | Chord                 { $$ = $1; }
473         | transposed_music      { $$ = $1; }
474         | MUSIC_IDENTIFIER      { $$ = $1->music(true); }
475         | MELODIC 
476                 { THIS->lexer_p_->push_note_state(); } 
477         Music
478                 { $$=$3; THIS->lexer_p_->pop_state(); }
479
480         | LYRIC 
481                 { THIS->lexer_p_->push_lyric_state(); } 
482         Music
483                 { $$ = $3; THIS->lexer_p_->pop_state(); }
484         ; 
485
486 Chord:
487         '<' Chord_body '>'      { $$  = $2; }
488         ;
489
490 Chord_body:
491         /**/    {
492                 $$ = new Chord;
493                 $$-> multi_level_i_ = 1;
494         }
495         | Chord_body MULTI INT ';' {
496                 $$->multi_level_i_=$3;
497         }
498         | Chord_body ID STRING STRING ';'       {
499                 $$->type_str_ = *$3;    
500                 $$->id_str_ = *$4;
501                 delete $4; 
502                 delete $3;
503         }
504         | Chord_body Music {
505                 $$->add($2);
506         }
507         ;
508
509 transposed_music:
510         TRANSPOSE steno_melodic_req Music {
511                 $$ = $3;
512                 $$ -> transpose($2);
513                 delete $2;
514         }
515         ;
516
517
518 /*
519         VOICE ELEMENTS
520 */
521 full_element:
522         pre_requests simple_element post_requests       {
523                 THIS->add_requests((Chord*)$2);//ugh
524                 $$ = $2;
525         }
526         | voice_command ';'     { $$ = 0; }
527         ;       
528
529 simple_element:
530         music_elt 
531         | lyrics_elt
532         | command_elt
533         ;
534
535 command_elt:
536 /* empty */     {
537                 $$ = new Voice_element;
538                 $$-> set_spot( THIS->here_input());
539         }
540 /* cont: */
541         command_req {
542                 $2-> set_spot( THIS->here_input());
543                 ((Chord*)$$) ->add($2);//ugh
544
545         }
546         | GROUP STRING ';' { // ugh ugh ugh
547                 Change_reg *chr_p = new Change_reg;
548                 $$ = chr_p;
549                 chr_p-> type_str_ = "Voice_group_engravers"; //ugh
550                 chr_p-> id_str_ = *$2;
551                 delete $2;
552         }
553         ;
554
555 command_req:
556         abbrev_command_req      
557         | verbose_command_req ';'       { $$ = $1; }
558         ;
559
560 abbrev_command_req:
561          '|'                            { 
562                 $$ = new Barcheck_req;
563         }
564         ;
565
566 verbose_command_req:
567         BAR STRING                      {
568                 $$ = new Bar_req(*$2);
569                 delete $2;
570         }
571         | METER int '/' int     {
572                 Meter_change_req *m = new Meter_change_req;
573                 m->set($2,$4);
574                 // sorry hw, i need meter at output of track,
575                 // but don-t know where to get it... statics should go.
576                 // HW : default: 4/4, meterchange reqs may change it.
577                 
578                 Midi_def::num_i_s = $2;
579                 Midi_def::den_i_s = $4;
580                 $$ = m;
581         }
582         | SKIP duration_length {
583                 Skip_req * skip_p = new Skip_req;
584                 skip_p->duration_ = Duration(1,0);
585                 skip_p->duration_.set_plet($2->numerator().as_long(), 
586                         $2->denominator().as_long());
587                 
588                 delete $2;
589                 $$ = skip_p;
590         }
591         | CADENZA int   {
592                 $$ = new Cadenza_req($2);
593         }
594         | PARTIAL duration_length       {
595                 $$ = new Partial_measure_req(*$2);
596                 delete $2;
597         }
598         | STEM int      {
599                 $$ = get_stemdir_req($2);
600         }
601         | HSHIFT int    {
602                 $$ = get_hshift_req($2);
603         }
604         | CLEF STRING {
605                 $$ = new Clef_change_req(*$2);
606                 delete $2;
607         }
608         | KEY pitch_list        {       
609                 Key_change_req *key_p= new Key_change_req;
610                 key_p->melodic_p_arr_ = *$2;
611                 $$ = key_p;
612                 delete $2;
613         }
614         | GROUPING intastint_list {
615                 $$ = get_grouping_req(*$2); delete $2;
616         }
617         
618         ;
619
620 post_requests:
621         {
622                 assert(THIS->post_reqs.empty());
623         }
624         | post_requests post_request {
625                 $2->set_spot( THIS->here_input());
626                 THIS->post_reqs.push($2);
627         }
628         ;
629
630
631 post_request:
632         POST_REQUEST_IDENTIFIER {
633                 $$ = (Request*)$1->request(true);
634         }
635         |close_request_parens   { 
636                 $$ = THIS->get_parens_request($1); 
637         }
638         | script_req
639         | dynamic_req
640         ;
641
642
643
644 /*
645         URG!!
646 */
647 steno_melodic_req:
648         NOTENAME_ID     {
649                 $$ = $1->clone()->musical()->melodic();
650                 $$->octave_i_ += THIS->default_octave_i_;
651         }
652         | steno_melodic_req POST_QUOTES         {  
653                 $$-> octave_i_ += $2;
654         }
655         | PRE_QUOTES steno_melodic_req   {  
656                 $$ = $2;
657                 $2-> octave_i_ -= $1;
658         }
659         ;
660
661 steno_note_req:
662         steno_melodic_req       {
663                 $$ = new Note_req;
664                 * (Melodic_req *) $$ = *$1;
665                 delete $1;
666         }
667         | steno_note_req   '!'          {
668                 $$->forceacc_b_ = ! $$->forceacc_b_;
669         } 
670         /* have to duration here. */
671         ;
672
673 melodic_request:
674         MELODIC_REQUEST '{' int int int '}'     {/* ugh */
675                 $$ = new Melodic_req;
676                 $$->octave_i_ = $3;
677                 $$->notename_i_ = $4;
678                 $$->accidental_i_ = $5;
679         }
680         ;
681
682 dynamic_req:
683         ABSDYNAMIC '{' int '}'  {
684                 Absolute_dynamic_req *ad_p = new Absolute_dynamic_req;
685                 ad_p ->loudness_ = (Dynamic_req::Loudness)$3;
686                 $$ =ad_p;
687         }
688         | SPANDYNAMIC '{' int int '}' {
689                 Span_dynamic_req * sp_p = new Span_dynamic_req;
690                 sp_p->spantype = $4;
691                 sp_p-> dynamic_dir_i_  = $3;
692                 $$ = sp_p;
693         }
694         ;
695
696 close_plet_parens:
697         ']' INT '/' INT {
698                 $$ = ']';
699                 THIS->default_duration_.set_plet($2,$4);
700         }
701         ;
702
703 close_request_parens:
704         '~'     {
705                 $$ = '~';
706         }
707         | '('   { 
708                 $$='(';
709         }
710         | ']'   { 
711                 $$ = ']';
712         }
713         | close_plet_parens {
714                 $$ = ']';
715         }
716         | E_SMALLER {
717                 $$ = '<';
718         }
719         | E_BIGGER {
720                 $$ = '>';
721         }
722         ;
723
724 open_plet_parens:
725         '[' INT '/' INT {
726                 $$ = '[';
727                 THIS->default_duration_.set_plet($2,$4);
728         }
729         ;
730
731 open_request_parens:
732         E_EXCLAMATION   {
733                 $$ = '!';
734         }
735         | ')'   { 
736                 $$=')';
737         }
738         | '['   {
739                 $$='[';
740         }
741         | open_plet_parens {
742         }
743         ;
744
745
746
747 script_definition:
748         SCRIPT '{' script_body '}'      { $$ = $3; }
749         ;
750
751 script_body:
752         STRING int int int int int              {
753                 Script_def *s = new Script_def;
754                 s->set_from_input(*$1,$2, $3,$4,$5, $6);
755                 $$  = s;
756                 delete $1;
757         }       
758         ;
759
760 script_req:
761         script_dir gen_script_def               { 
762                 Musical_script_req *m = new Musical_script_req;
763                 $$ = m; 
764                 m-> scriptdef_p_ = $2;
765                 m-> set_spot ( THIS->here_input() );
766                 m-> dir_i_  = $1;
767         }
768         ;
769
770 gen_script_def:
771         text_def        { $$ = $1; }
772         | mudela_script { $$ = $1; 
773                 $$-> set_spot( THIS->here_input() );
774         }
775         ;
776
777 text_def:
778         STRING { 
779                 Text_def *t  = new Text_def;
780                 $$ = t;
781                 t->text_str_ = *$1; 
782                 delete $1;
783                 t->style_str_ = THIS->textstyle_str_;
784                 $$->set_spot( THIS->here_input() );
785         }
786         ;
787
788 script_abbreviation:
789         '^'             { $$ = get_scriptdef('^'); }
790         | '+'           { $$ = get_scriptdef('+'); }
791         | '-'           { $$ = get_scriptdef('-'); }
792         | '|'           { $$ = get_scriptdef('|'); }
793         | 'o'           { $$ = get_scriptdef('o'); }
794         | '>'           { $$ = get_scriptdef('>'); }
795         | '.'           {
796                 $$ = get_scriptdef('.');
797         }
798         ;
799         
800 mudela_script:
801         SCRIPT_IDENTIFIER               { $$ = $1->script(true); }
802         | script_definition             { $$ = $1; }
803         | script_abbreviation           { 
804                 $$ = THIS->lexer_p_->lookup_identifier(*$1)->script(true);
805                 delete $1;
806         }
807         ;
808
809 script_dir:
810         '_'     { $$ = -1; }
811         |'^'    { $$ = 1; }
812         |'-'    { $$ = 0; }
813         ;
814
815 pre_requests:
816         | pre_requests pre_request {
817                 THIS->pre_reqs.push($2);
818                 $2->set_spot( THIS->here_input());
819         }
820         ;
821
822 pre_request: 
823         open_request_parens     { 
824                 $$ = THIS->get_parens_request($1); 
825         }
826         ;
827
828 voice_command:
829         PLET     INT '/' INT {
830                 THIS->default_duration_.set_plet($2,$4);
831         }
832         | DURATIONCOMMAND STRING {
833                 THIS->set_duration_mode(*$2);
834                 delete $2;
835         }
836         | DURATIONCOMMAND notemode_duration {
837                 THIS->set_default_duration($2);
838                 delete $2;
839         }
840         | OCTAVECOMMAND { 
841                 /*
842                         This is weird, but default_octave_i_
843                         is used in steno_note_req too
844
845                         c' -> default_octave_i_ == 1
846                 */
847                 /* why can't we have \oct{0} iso \oct{c'}*/
848                 THIS->default_octave_i_ = 1; }
849 /* cont */
850         steno_melodic_req {
851                 THIS->default_octave_i_ = $3->octave_i_;
852                 delete $3;
853         }
854         | TEXTSTYLE STRING      {
855                 THIS->textstyle_str_ = *$2;
856                 delete $2;
857         }
858         ;
859
860 duration_length:        
861         {
862                 $$ = new Moment(0,1);
863         }
864         | duration_length explicit_duration             {       
865                 *$$ += $2->length();
866         }
867         ;
868
869 dots:
870         '.'             { $$ = 1; }
871         | dots '.'      { $$ ++; }
872         ;
873
874 notemode_duration:
875         /* */           { 
876                 $$ = new Duration(THIS->default_duration_);
877         }
878         | dots          {
879                 $$ = new Duration(THIS->default_duration_);
880                 $$->dots_i_  = $1;
881         }
882         | explicit_duration     {
883                 THIS->set_last_duration($1);
884                 $$ = $1;
885         }
886         ;
887
888 explicit_duration:
889         int             {
890                 $$ = new Duration;
891                 if ( !Duration::duration_type_b($1) )
892                         THIS->parser_error("Not a duration");
893                 else {
894                         $$->type_i_ = $1;
895                         $$->set_plet(THIS->default_duration_);
896                      }
897         }
898         | explicit_duration '.'         {
899                 $$->dots_i_ ++;
900         }
901         | explicit_duration '*' int  {
902                 $$->plet_.iso_i_ *= $3; 
903         }
904         | explicit_duration '/' int {
905                 $$->plet_.type_i_ *= $3; 
906         }
907         ;
908
909
910 music_elt:
911         steno_note_req notemode_duration                {
912                 if (!THIS->lexer_p_->note_state_b())
913                         THIS->parser_error("have to be in Note mode for notes");
914                 $1->set_duration (*$2);
915                 $$ = THIS->get_note_element($1, $2);
916         }
917         | RESTNAME notemode_duration            {
918                 $$ = THIS->get_rest_element(*$1, $2);
919                 delete $1;
920         }
921         ;
922
923 lyrics_elt:
924         text_def notemode_duration                      {
925                 if (!THIS->lexer_p_->lyric_state_b())
926                         THIS->parser_error("Have to be in Lyric mode for lyrics");
927                 $$ = THIS->get_word_element($1, $2);
928
929         };
930
931 /*
932         UTILITIES
933  */
934 pitch_list:                     {
935                 $$ = new Array<Melodic_req*>;
936         }
937         | pitch_list NOTENAME_ID        {
938                 $$->push($2->clone()->musical()->melodic());
939         }
940         ;
941
942 int:
943         INT                     {
944                 $$ = $1;
945         }
946         | INT_IDENTIFIER        {
947                 $$ = * $1->intid(0);
948         }
949         ;
950
951
952 real:
953         REAL            {
954                 $$ = $1;
955         }
956         | REAL_IDENTIFIER               {
957                 $$ = * $1->real(0);             
958         }
959         ;
960         
961
962
963 dim:
964         real unit       { $$ = $1*$2; }
965         ;
966
967
968 unit:   CM_T            { $$ = 1 CM; }
969         |IN_T           { $$ = 1 INCH; }
970         |MM_T           { $$ = 1 MM; }
971         |PT_T           { $$ = 1 PT; }
972         ;
973         
974 /*
975         symbol tables
976 */
977 symtables:
978         SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
979         ;
980
981 symtables_body:
982                         {
983                 $$ = new Lookup;
984         }
985         | IDENTIFIER            {
986                 $$ = $1->lookup(true);
987         }
988         | symtables_body TEXID STRING           {
989                 $$->texsetting = *$3;
990                 delete $3;
991         }
992         | symtables_body STRING '=' symtable            {
993                 $$->add(*$2, $4);
994                 delete $2;
995         }
996         ;
997
998 symtable:
999         TABLE '{' symtable_body '}' { $$ = $3; }
1000         ;
1001
1002 symtable_body:
1003                                 { $$ = new Symtable; }
1004         | symtable_body STRING  symboldef {
1005                 $$->add(*$2, *$3);
1006                 delete $2;
1007                 delete $3;
1008         }
1009         ;
1010
1011 symboldef:
1012         STRING  box             {
1013                 $$ = new Symbol(*$1, *$2);
1014                 delete $1;
1015                 delete $2;
1016         }
1017         | STRING {
1018                 Box b(Interval(0,0), Interval(0,0));
1019                 $$ = new Symbol(*$1, b);
1020                 delete $1;
1021         }
1022         ;
1023
1024 box:
1025         dinterval dinterval     {
1026                 $$ = new Box(*$1, *$2);
1027                 delete $1;
1028                 delete $2;
1029         }
1030         ;
1031
1032 dinterval: dim  dim             {
1033                 $$ = new Interval($1, $2);      
1034         }
1035         ;
1036
1037 %%
1038
1039 void 
1040 My_lily_parser::set_yydebug(bool b )
1041 {
1042 #ifdef YYDEBUG
1043         yydebug = b;
1044 #endif
1045 }
1046 void
1047 My_lily_parser::do_yyparse()
1048 {
1049         yyparse((void*)this);
1050 }
1051
1052 Paper_def*
1053 My_lily_parser::default_paper()
1054 {
1055         Identifier *id = lexer_p_->lookup_identifier( "default_paper" );
1056         return id ? id->paperdef(true) : new Paper_def ;
1057 }
1058