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