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