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