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