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