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