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