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