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