]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.y
release: 0.0.40
[lilypond.git] / lily / parser.y
1 %{ // -*-Fundamental-*-
2 #include <iostream.h>
3
4 #include "lookup.hh"
5 #include "misc.hh"
6 #include "lexer.hh"
7 #include "paper-def.hh"
8 #include "midi-def.hh"
9 #include "input-score.hh"
10 #include "main.hh"
11 #include "keyword.hh"
12 #include "debug.hh"
13 #include "parseconstruct.hh"
14 #include "dimen.hh"
15 #include "identifier.hh"
16 #include "commandrequest.hh"
17 #include "musicalrequest.hh"
18 #include "voice-element.hh"
19
20 #ifndef NDEBUG
21 #define YYDEBUG 1
22 #endif
23
24 Array<Request*> pre_reqs, post_reqs;
25 Array<const char *> define_spots;
26 Paper_def*default_paper();
27 char const* defined_ch_c_l;
28 char const* req_defined_ch_c_l;
29 int fatal_error_i = 0;
30
31 %}
32
33
34 %union {
35     Request * request;
36     Real real;
37     Identifier *id;    
38    Voice *voice;    
39     Voice_element *el;  
40     String *string;
41     const char *consstr;
42     Paper_def *paper;
43     Midi_def* midi;
44     Input_music *music;
45     Music_general_chord *chord;
46     Music_voice *mvoice; 
47     int i;
48     char c;
49     int ii[10];
50         Moment *moment;
51
52     Array<String> * strvec;
53     Array<int> *intvec;
54     Array<Melodic_req*> *melreqvec;
55     Input_staff *staff;    
56     Input_score *score;
57     Symtables * symtables;
58     Symtable * symtable;
59     Symbol * symbol;
60     Lookup*lookup;
61     Interval *interval;
62     Box *box;
63     Notename_tab *notename_tab;
64     Script_def * script;
65     Text_def * textdef;
66 }
67
68 %token VOICE STAFF SCORE TITLE  BAR  OUTPUT MULTIVOICE DYNAMIC
69 %token CM_T IN_T PT_T MM_T PAPER WIDTH METER UNITSPACE SKIP COMMANDS COMMAND
70 %token GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
71 %token KEY CLEF  TABLE  VOICES STEM
72 %token PARTIAL MUSIC GROUPING CADENZA
73 %token END SYMBOLTABLES TEXID TABLE NOTENAMES SCRIPT TEXTSTYLE PLET
74 %token  GOTO
75 %token MIDI TEMPO
76
77 %token <id>  IDENTIFIER REAL_IDENTIFIER REQUEST_IDENTIFIER 
78 %token <string> PITCHMOD DURATION RESTNAME
79 %token <ii> NOTENAME 
80 %token <real> REAL 
81 %token <string> STRING
82
83 %token <i> DOTS INT
84 %type <real> unit
85 %type <melreqvec> pitch_list 
86 %type <c> open_request_parens close_request_parens close_plet_parens
87 %type <id> declaration
88 %type <string> declarable_identifier
89 %type <paper> paper_block paper_body
90 %type <midi> midi_block midi_body
91 %type <real> dim real
92 %type <ii>  default_duration explicit_duration notemode_duration mudela_duration
93 %type <ii> notename
94 %type <moment> duration_length
95 %type <el> voice_elt full_element lyrics_elt command_elt
96
97 %type <score> score_block score_body
98 %type <staff> staff_block staff_init staff_body
99 %type <i> int
100 %type <intvec> intastint_list
101 %type <request> post_request pre_request command_req 
102 %type <string> pitchmod
103 %type <music> music 
104 %type <chord> music_chord music_chord_body
105
106 %type <mvoice>  music_voice_body music_voice 
107
108 %type <interval> dinterval
109 %type <box> box
110 %type <symtable> symtable symtable_body
111 %type <lookup> symtables symtables_body
112 %type <symbol> symboldef
113 %type <notename_tab> notename_tab notename_tab_body
114 %type <i> script_dir
115 %type <script> script_definition script_body mudela_script
116 %type <request> script_req textscript_req dynamic_req basic_request
117 %type <textdef> mudela_text
118
119
120 %%
121
122 mudela: /* empty */
123         | mudela score_block {
124                 add_score($2);          
125         }
126         | mudela add_declaration { }
127         | mudela mudela_command  {}
128         ;
129
130 mudela_command:
131         notename_tab                    { lexer->set($1); }
132         ;
133
134 /*
135         DECLARATIONS
136 */
137 add_declaration: declaration    {
138                 lexer->add_identifier($1);
139         }
140         ;
141
142 declarable_identifier:
143         STRING { $$ = $1; }
144         | IDENTIFIER { $$ = new String($1->name); }
145         ;
146
147 declaration:
148         declarable_identifier '=' staff_block  {
149                 $$ = new Staff_id(*$1, $3, IDENTIFIER);
150                 delete $1; 
151         }
152         | declarable_identifier '=' music_voice {
153                 $$ = new M_voice_id(*$1, $3, IDENTIFIER);
154                 delete $1;
155         }
156         | declarable_identifier '=' script_definition {
157                 $$ = new Script_id(*$1, $3, IDENTIFIER);
158                 delete $1;
159         }
160         | declarable_identifier '=' music_chord  {
161                 $$ = new M_chord_id(*$1, $3, IDENTIFIER);
162                 delete $1;
163         }
164         | declarable_identifier '=' symtables {
165                 $$ = new Lookup_id(*$1, $3, IDENTIFIER);
166                 delete $1;
167         }
168         | declarable_identifier '=' notename_tab {
169                 $$ = new Notetab_id(*$1, $3, IDENTIFIER);
170                 delete $1;
171         }
172         | declarable_identifier '=' real        {
173                 $$ = new Real_id(*$1, new Real($3), REAL_IDENTIFIER);
174                 delete $1;
175         }
176         | declarable_identifier error '}' {
177
178         }
179         | declarable_identifier '=' basic_request {
180                 $$ = new Request_id(*$1, $3, REQUEST_IDENTIFIER);
181                 delete $1;
182         }
183         ;
184
185 notename_tab:
186         NOTENAMES '{' notename_tab_body '}'     { $$ = $3; }
187         ;
188
189 notename_tab_body:                              {
190                 $$ = new Notename_tab;
191         }
192         | IDENTIFIER                            {
193                 $$ = $1->notename_tab(true);
194         }
195         | notename_tab_body STRING int int                      {
196                 $$->set($3, $4, *$2);
197                 delete $2;
198         }
199         ;
200
201 /*
202         SCORE
203 */
204 score_block:
205         SCORE { define_spots.push(lexer->here_ch_c_l()); }
206         /*cont*/ '{' score_body '}'     {
207                 $$ = $4;
208                 $$->defined_ch_c_l_ = define_spots.pop();
209                 if (!$$->paper_p_ && ! $$->midi_p_)
210                         $$->paper_p_ = default_paper();
211
212                 /* handle error levels. */
213                 $$->errorlevel_i_ = lexer->errorlevel_i_;
214                 lexer->errorlevel_i_ = 0;
215         }
216         ;
217
218 score_body:             { 
219                 $$ = new Input_score; 
220         }
221         | score_body staff_block        { $$->add($2); }
222         | score_body COMMANDS '{' music_voice_body '}'          {
223                 $$->set($4);
224         }
225         | score_body paper_block                { $$->set($2);  }
226         | score_body midi_block         { $$->set($2);  }
227         | score_body error {
228
229         }
230         ;
231
232 intastint_list:
233         /* */   { $$ =new Array<int>; }
234         | intastint_list int '*' int    {
235                 $$->push($2); $$->push($4);
236         }
237         ;
238
239
240 /*
241         PAPER
242 */
243 paper_block:
244         PAPER
245
246         '{' paper_body '}'      { $$ = $3; }
247         ;
248
249 paper_body:
250         /* empty */                     {
251                 $$ = default_paper();
252         }
253         | paper_body WIDTH dim          { $$->linewidth = $3;}
254         | paper_body OUTPUT STRING      { $$->outfile = *$3;
255                 delete $3;
256         }
257         | paper_body symtables          { $$->set($2); }
258         | paper_body UNITSPACE dim      { $$->whole_width = $3; }
259         | paper_body GEOMETRIC REAL     { $$->geometric_ = $3; }
260         | paper_body error {
261
262         }
263         ;
264
265 /*
266         MIDI
267 */
268 midi_block:
269         MIDI
270
271         '{' midi_body '}'       { $$ = $3; }
272         ;
273
274 midi_body: { 
275                 $$ = new Midi_def; 
276         }
277         | midi_body OUTPUT STRING       { 
278                 $$->outfile_str_ = *$3; 
279                 delete $3; 
280         }
281         | midi_body TEMPO mudela_duration ':' int {
282                 $$->set_tempo( wholes( $3[0], $3[1] ), $5 );
283         }
284         | midi_body error {
285
286         }
287         ;
288
289 /*
290         STAFFs
291 */
292 staff_block:
293         STAFF   { define_spots.push(lexer->here_ch_c_l()); }
294 /*cont*/        '{' staff_body '}'      {
295                 $$ = $4; 
296                 $$-> defined_ch_c_l_ = define_spots.pop();
297         }
298         ;
299
300
301
302 staff_init:
303         IDENTIFIER              { $$ = $1->staff(true); }
304         | STRING                {
305                 $$ = new Input_staff(*$1);
306                 delete $1;
307         }
308         ;
309
310 staff_body:
311         staff_init
312         | staff_body COMMANDS '{' music_voice_body '}'  {
313                 $$->set_score_wide($4);
314         }
315         | staff_body music      {
316                 $2->set_default_group( "staff_music" + String($$->music_.size()));
317                 $$->add($2);
318         }
319         | staff_body error {
320         }
321         ;
322
323 /*
324         MUSIC
325 */
326 music:
327         music_voice     { $$ = $1; }
328         | music_chord   { $$ = $1; }
329         ;
330
331 music_voice:  MUSIC '{' music_voice_body '}'    { $$ = $3; }
332         ;
333
334 music_voice_body:
335         IDENTIFIER {
336                 $$ = $1->mvoice(true);
337         }
338         | /* */         {
339                 $$ = new Music_voice;
340         }
341         | music_voice_body '+' IDENTIFIER {
342                 $$->concatenate($3->mvoice(true));
343         }
344         | music_voice_body full_element {
345                 $$->add_elt($2);
346         }
347         | music_voice_body voice_command {
348         }
349         | music_voice_body music        {
350                 $$->add($2);
351         }
352         | music_voice_body error {
353         }
354         ;
355
356 music_chord:  '{' music_chord_body '}'  { $$ = $2; }
357         ;
358
359 music_chord_body:
360         IDENTIFIER {
361                 $$=$1->mchord(true);
362         }
363         | /* */ {
364                 $$ = new Voice_group_chord;
365         }
366         | MULTIVOICE {
367                 $$ = new Multi_voice_chord;
368         }
369         | music_chord_body '+' IDENTIFIER {
370                 $$->concatenate($3->mchord(true));
371         }
372         | music_chord_body music {
373                 $$->add($2);
374         }
375         | music_chord_body full_element {
376                 $$ ->add_elt($2);
377         }
378         | music_chord_body error {
379         }
380         ;
381
382 basic_request:
383         command_req
384         | pre_request
385         | post_request
386         ;
387
388 /*
389         VOICE ELEMENTS
390 */
391 full_element:   pre_requests voice_elt post_requests {
392                 add_requests($2, pre_reqs);
393                 add_requests($2, post_reqs);
394                 $$ = $2;
395         }
396         | pre_requests lyrics_elt post_requests {
397                 add_requests($2, pre_reqs);
398                 add_requests($2, post_reqs);
399                 $$ = $2;
400         }
401         | command_elt
402         ;
403
404 command_elt:
405 /* empty */     {
406                 $$ = new Voice_element;
407                 $$-> defined_ch_c_l_ = lexer->here_ch_c_l();
408         }
409 /* cont: */
410         command_req     {
411                 $2-> defined_ch_c_l_ = $$->defined_ch_c_l_;
412                 $$->add($2);
413
414         }
415         ;
416
417 command_req:
418          '|'                            { 
419                 $$ = new Barcheck_req;
420         }
421         | BAR STRING                    {
422                 $$ = new Bar_req(*$2);
423                 delete $2;
424         }
425         | METER '{' int '*' int '}'     {
426                 Meter_change_req *m = new Meter_change_req;
427                 m->set($3,$5);
428                 $$ = m;
429         }
430         | SKIP '{' duration_length '}' {
431                 Skip_req * skip_p = new Skip_req;
432                 skip_p->duration_ = *$3;
433                 delete $3;
434                 $$ = skip_p;
435         }
436         | CADENZA '{' int '}'   {
437                 $$ = new Cadenza_req($3);
438         }
439         | PARTIAL '{' duration_length '}'       {
440                 $$ = new Partial_measure_req(*$3);
441                 delete $3;
442         }
443         | STEM '{' int '}'              {
444                 $$ = get_stemdir_req($3);
445         }
446         | CLEF STRING {
447                 $$ = new Clef_change_req(*$2);
448                 delete $2;
449         }
450         | KEY '{' pitch_list '}'        {       
451                 Key_change_req *key_p= new Key_change_req;
452                 key_p->melodic_p_arr_ = *$3;
453                 $$ = key_p;
454                 delete $3;
455         }
456         | GROUPING '{' intastint_list '}' {
457                 $$ = get_grouping_req(*$3); delete $3;
458         }
459         ;
460
461 post_requests:
462         {
463                 assert(post_reqs.empty());
464         }
465         | post_requests post_request {
466                 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
467                 post_reqs.push($2);
468         }
469         | post_requests close_plet_parens INT '/' INT { 
470                 post_reqs.push( get_request($2) ); 
471                 req_defined_ch_c_l = lexer->here_ch_c_l();
472                 post_reqs.push( get_plet_request( $2, $3, $5 ) ); 
473         }
474         ;
475
476 post_request:
477         close_request_parens    { 
478                 $$ = get_request($1); 
479         }
480         | script_req
481         | textscript_req
482         | dynamic_req
483         | REQUEST_IDENTIFIER    {
484                 $$ = $1->request(false)->clone();
485         }
486         ;
487
488 dynamic_req:
489         DYNAMIC '{' int '}'     {
490                 Absolute_dynamic_req *ad_p = new Absolute_dynamic_req;
491                 ad_p ->loudness_ = $3;
492                 $$ =ad_p;
493         }
494         ;
495
496 close_plet_parens:
497         ']' {
498                 req_defined_ch_c_l = lexer->here_ch_c_l();
499                 $$ = ']';
500         }
501         ;
502
503 close_request_parens:
504         '('     { 
505                 $$='(';
506         }
507         | ']'   { 
508                 $$ = ']';
509         }
510         ;
511   
512 open_request_parens:
513         ')'     { 
514                 $$=')';
515         }
516         | '['   {
517                 $$='[';
518         }
519         ;
520
521 script_definition:
522         SCRIPT '{' script_body '}'      { $$ = $3; }
523         ;
524
525 script_body:
526         STRING int int int              {
527                 $$ = new Script_def(*$1,$2, $3,$4);
528                 delete $1;
529         }       
530         ;
531
532 textscript_req:
533         script_dir mudela_text          { $$ = get_text_req($1,$2); }
534         ;
535
536 mudela_text:
537         STRING                  { 
538                 defined_ch_c_l = lexer->here_ch_c_l();
539                 $$ = get_text(*$1); 
540                 delete $1;
541         }
542         ;
543
544 script_req:
545         script_dir mudela_script        { 
546                 $$ = get_script_req($1, $2);
547         }
548         ;
549
550 mudela_script:
551         IDENTIFIER              { $$ = $1->script(true); }
552         | script_definition             { $$ = $1; }
553         | '^'           { $$ = get_scriptdef('^'); }
554         | '+'           { $$ = get_scriptdef('+'); }
555         | '-'           { $$ = get_scriptdef('-'); }
556         | '|'           { $$ = get_scriptdef('|'); }
557         | 'o'           { $$ = get_scriptdef('o'); }
558         | '>'           { $$ = get_scriptdef('>'); }
559         | '.'           { $$ = get_scriptdef('.'); }
560         | DOTS          {
561                 if ( $1 > 1 ) 
562                     warning( "too many staccato dots", lexer->here_ch_c_l() );
563                 $$ = get_scriptdef('.');
564         }
565         | error {
566                 $$ = get_scriptdef('.');
567                 yyerrok;
568         }
569         ;
570
571 script_dir:
572         '_'     { $$ = -1; }
573         |'^'    { $$ = 1; }
574         |'-'    { $$ = 0; }
575         ;
576
577 pre_requests:
578         | pre_requests pre_request {
579                 pre_reqs.push($2);
580                 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
581         }
582         ;
583
584 pre_request: 
585         open_request_parens     { 
586                 defined_ch_c_l = lexer->here_ch_c_l();
587                 $$ = get_request($1); 
588         }
589         ;
590
591 voice_command:
592         PLET    '{' INT '/' INT '}'             {
593                 set_plet($3,$5);
594         }
595         | DURATIONCOMMAND '{' STRING '}'        {
596                 set_duration_mode(*$3);
597                 delete $3;
598         }
599         | DURATIONCOMMAND '{' notemode_duration '}'     {
600                 set_default_duration($3);
601         }
602         | OCTAVECOMMAND '{' pitchmod '}'        {
603                 set_default_octave(*$3);
604                 delete $3;
605         }
606         | TEXTSTYLE STRING      {
607                 set_text_style(*$2);
608                 delete $2;
609         }
610         ;
611
612 duration_length:        
613         mudela_duration         {
614                 $$ = new Moment(wholes($1[0], $1[1]));
615         }
616         |int '*' mudela_duration        {
617                 $$ = new Moment(Rational($1) * wholes($3[0], $3[1]));
618         }
619         ;
620
621 notemode_duration:
622         explicit_duration
623         | default_duration
624         ;
625
626 mudela_duration:
627         int             {
628                 $$[0] = $1;
629                 $$[1] = 0;
630         }
631         | int DOTS      {
632                 $$[0] = $1;
633                 $$[1] = $2;
634         }
635         ;
636
637
638 explicit_duration:
639         INT             {
640                 last_duration($1);
641                 $$[0] = $1;
642                 $$[1] = 0;
643         }
644         | INT DOTS      {
645                 last_duration($1);
646                 $$[0] = $1;
647                 $$[1] = $2;
648         }
649         | DOTS  {
650                 get_default_duration($$);
651                 $$[1] = $1;
652         }
653         | INT '*' INT '/' INT {
654                 // ugh, must use Duration
655                 set_plet( $3, $5 );
656                 $$[ 0 ] = $1;
657                 $$[ 1 ] = 0;
658                 set_plet( 1, 1 );
659         }
660         ;
661
662 default_duration:
663         {
664                 get_default_duration($$);
665         }
666         ;
667
668 pitchmod:               { 
669                 defined_ch_c_l = lexer->here_ch_c_l();
670                 $$ = new String; 
671         }
672         | PITCHMOD      { 
673                 defined_ch_c_l = lexer->here_ch_c_l();
674                 $$ = $1;
675         }
676         ;
677
678 notename:
679         NOTENAME
680         ;
681
682 voice_elt:
683         pitchmod notename notemode_duration                     {
684                 $$ = get_note_element(*$1, $2, $3);
685                 delete $1;
686         }
687         | RESTNAME notemode_duration            {
688                 $$ = get_rest_element(*$1, $2);
689                 delete $1;
690
691         }
692         ;
693
694 lyrics_elt:
695         mudela_text notemode_duration                   {
696                 $$ = get_word_element($1, $2);
697         };
698
699 /*
700         UTILITIES
701  */
702 pitch_list:                     {
703                 $$ = new Array<Melodic_req*>;
704         }
705         | pitch_list NOTENAME   {
706                 Melodic_req *m_p = new Melodic_req;
707                 m_p->notename_i_ = $2[0];
708                 m_p->accidental_i_ = $2[1];
709                 $$->push(m_p);
710         }
711         ;
712
713 int:
714         real                    {
715                 $$ = int($1);
716                 if ( distance($1,Real(int($$)) ) > 1e-8)
717                         error( "integer expected", lexer->here_ch_c_l() );
718         }
719         ;
720
721 real:
722         INT                     {
723                 $$ = Real($1);
724         }
725         | REAL          {
726                 $$ = $1;
727         }
728         | REAL_IDENTIFIER               {
729                 $$ = * $1->real(0);             
730         }
731         ;
732         
733
734
735 dim:
736         real unit       { $$ = $1*$2; }
737         ;
738
739
740 unit:   CM_T            { $$ = 1 CM; }
741         |IN_T           { $$ = 1 INCH; }
742         |MM_T           { $$ = 1 MM; }
743         |PT_T           { $$ = 1 PT; }
744         ;
745         
746 /*
747         symbol tables
748 */
749 symtables:
750         SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
751         ;
752
753 symtables_body:
754                         {
755                 $$ = new Lookup;
756         }
757         | IDENTIFIER            {
758                 $$ = new Lookup(*$1->lookup(true));
759         }
760         | symtables_body TEXID STRING           {
761                 $$->texsetting = *$3;
762                 delete $3;
763         }
764         | symtables_body STRING '=' symtable            {
765                 $$->add(*$2, $4);
766                 delete $2;
767         }
768         ;
769
770 symtable:
771         TABLE '{' symtable_body '}' { $$ = $3; }
772         ;
773
774 symtable_body:
775                                 { $$ = new Symtable; }
776         | symtable_body STRING  symboldef {
777                 $$->add(*$2, *$3);
778                 delete $2;
779                 delete $3;
780         }
781         ;
782
783 symboldef:
784         STRING  box             {
785                 $$ = new Symbol(*$1, *$2);
786                 delete $1;
787                 delete $2;
788         }
789         | STRING {
790                 Box b;
791                 $$ = new Symbol(*$1, b);
792                 delete $1;
793         }
794         ;
795
796 box:
797         dinterval dinterval     {
798                 $$ = new Box(*$1, *$2);
799                 delete $1;
800                 delete $2;
801         }
802         ;
803
804 dinterval: dim  dim             {
805                 $$ = new Interval($1, $2);      
806         }
807         ;
808
809 %%
810
811 void
812 yyerror(const char *s)
813 {
814         lexer->LexerError(s);
815
816         if ( fatal_error_i )
817                 exit( fatal_error_i );
818 }
819
820 void
821 parse_file(String init, String s)
822 {
823    *mlog << "Parsing ... ";
824    lexer = new My_flex_lexer;
825
826 #ifdef YYDEBUG
827    yydebug = !monitor->silence("InitParser") && check_debug;
828    lexer->set_debug( !monitor->silence("InitLexer") && check_debug);
829 #endif
830
831    lexer->new_input(init);
832    yyparse();
833
834 #ifdef YYDEBUG
835    yydebug = !monitor->silence("Parser") && check_debug;
836    lexer->set_debug( !monitor->silence("Lexer") && check_debug);
837 #endif
838
839    lexer->new_input(s);
840    yyparse();
841    delete lexer;
842    lexer = 0;
843
844    if(!define_spots.empty())
845         warning("Braces don't match.",0);
846 }
847
848 Paper_def*
849 default_paper()
850 {
851     return new Paper_def(
852         lexer->lookup_identifier("default_table")->lookup(true));
853 }
854
855