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