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