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