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