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