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