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