]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.y
release: 0.0.39-1
[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
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
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
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);
150                 delete $1; 
151         }
152         | declarable_identifier '=' music_voice {
153                 $$ = new M_voice_id(*$1, $3);
154                 delete $1;
155         }
156         | declarable_identifier '=' script_definition {
157                 $$ = new Script_id(*$1, $3);
158                 delete $1;
159         }
160         | declarable_identifier '=' music_chord  {
161                 $$ = new M_chord_id(*$1, $3);
162                 delete $1;
163         }
164         | declarable_identifier '=' symtables {
165                 $$ = new Lookup_id(*$1, $3);
166                 delete $1;
167         }
168         | declarable_identifier '=' notename_tab {
169                 $$ = new Notetab_id(*$1, $3);
170                 delete $1;
171         }
172         | declarable_identifier '=' real        {
173                 $$ = new Real_id(*$1, new Real($3));
174                 delete $1;
175         }
176         | declarable_identifier error '}' {
177
178         }
179         ;
180
181 notename_tab:
182         NOTENAMES '{' notename_tab_body '}'     { $$ = $3; }
183         ;
184
185 notename_tab_body:                              {
186                 $$ = new Notename_tab;
187         }
188         | IDENTIFIER                            {
189                 $$ = $1->notename_tab(true);
190         }
191         | notename_tab_body STRING int int                      {
192                 $$->set($3, $4, *$2);
193                 delete $2;
194         }
195         ;
196
197 /*
198         SCORE
199 */
200 score_block:
201         SCORE { define_spots.push(lexer->here_ch_c_l()); }
202         /*cont*/ '{' score_body '}'     {
203                 $$ = $4;
204                 $$->defined_ch_c_l_ = define_spots.pop();
205                 if (!$$->paper_p_ && ! $$->midi_p_)
206                         $$->paper_p_ = default_paper();
207
208                 /* handle error levels. */
209                 $$->errorlevel_i_ = lexer->errorlevel_i_;
210                 lexer->errorlevel_i_ = 0;
211         }
212         ;
213
214 score_body:             { 
215                 $$ = new Input_score; 
216         }
217         | score_body staff_block        { $$->add($2); }
218         | score_body COMMANDS '{' music_voice_body '}'          {
219                 $$->set($4);
220         }
221         | score_body paper_block                { $$->set($2);  }
222         | score_body midi_block         { $$->set($2);  }
223         | score_body error {
224
225         }
226         ;
227
228 intastint_list:
229         /* */   { $$ =new Array<int>; }
230         | intastint_list int '*' int    {
231                 $$->push($2); $$->push($4);
232         }
233         ;
234
235
236 /*
237         PAPER
238 */
239 paper_block:
240         PAPER
241
242         '{' paper_body '}'      { $$ = $3; }
243         ;
244
245 paper_body:
246         /* empty */                     {
247                 $$ = default_paper();
248         }
249         | paper_body WIDTH dim          { $$->linewidth = $3;}
250         | paper_body OUTPUT STRING      { $$->outfile = *$3;
251                 delete $3;
252         }
253         | paper_body symtables          { $$->set($2); }
254         | paper_body UNITSPACE dim      { $$->whole_width = $3; }
255         | paper_body GEOMETRIC REAL     { $$->geometric_ = $3; }
256         | paper_body error {
257
258         }
259         ;
260
261 /*
262         MIDI
263 */
264 midi_block:
265         MIDI
266
267         '{' midi_body '}'       { $$ = $3; }
268         ;
269
270 midi_body: { 
271                 $$ = new Midi_def; 
272         }
273         | midi_body OUTPUT STRING       { 
274                 $$->outfile_str_ = *$3; 
275                 delete $3; 
276         }
277         | midi_body TEMPO mudela_duration ':' int {
278                 $$->set_tempo( wholes( $3[0], $3[1] ), $5 );
279         }
280         | midi_body error {
281
282         }
283         ;
284
285 /*
286         STAFFs
287 */
288 staff_block:
289         STAFF   { define_spots.push(lexer->here_ch_c_l()); }
290 /*cont*/        '{' staff_body '}'      {
291                 $$ = $4; 
292                 $$-> defined_ch_c_l_ = define_spots.pop();
293         }
294         ;
295
296
297
298 staff_init:
299         IDENTIFIER              { $$ = $1->staff(true); }
300         | STRING                {
301                 $$ = new Input_staff(*$1);
302                 delete $1;
303         }
304         ;
305
306 staff_body:
307         staff_init
308         | staff_body COMMANDS '{' music_voice_body '}'  {
309                 $$->set_score_wide($4);
310         }
311         | staff_body music      {
312                 $2->set_default_group( "staff_music" + String($$->music_.size()));
313                 $$->add($2);
314         }
315         | staff_body error {
316         }
317         ;
318
319 /*
320         MUSIC
321 */
322 music:
323         music_voice     { $$ = $1; }
324         | music_chord   { $$ = $1; }
325         ;
326
327 music_voice:  MUSIC '{' music_voice_body '}'    { $$ = $3; }
328         ;
329
330 music_voice_body:
331         /* */   {
332                 $$ = new Music_voice;
333         }
334         | music_voice_body IDENTIFIER {
335                 $$->concatenate($2->mvoice(true));
336         }
337         | music_voice_body full_element {
338                 $$->add_elt($2);
339         }
340         | music_voice_body voice_command {
341         }
342         | music_voice_body music        {
343                 $$->add($2);
344         }
345         | music_voice_body error {
346         }
347         ;
348
349 music_chord:  '{' music_chord_body '}'  { $$ = $2; }
350         ;
351
352 music_chord_body:
353         /* */   {
354                 $$ = new Voice_group_chord;
355         }
356         | MULTIVOICE {
357                 $$ = new Multi_voice_chord;
358         }
359         | music_chord_body IDENTIFIER {
360                 $$->concatenate($2->mchord(true));
361         }
362         | music_chord_body music {
363                 $$->add($2);
364         }
365         | music_chord_body full_element {
366                 $$ ->add_elt($2);
367         }
368         | music_chord_body error {
369         }
370         ;
371
372
373 /*
374         VOICE ELEMENTS
375 */
376 full_element:   pre_requests voice_elt post_requests {
377                 add_requests($2, pre_reqs);
378                 add_requests($2, post_reqs);
379                 $$ = $2;
380         }
381         | pre_requests lyrics_elt post_requests {
382                 add_requests($2, pre_reqs);
383                 add_requests($2, post_reqs);
384                 $$ = $2;
385         }
386         | command_elt
387         ;
388
389 command_elt:
390 /* empty */     {
391                 $$ = new Voice_element;
392                 $$-> defined_ch_c_l_ = lexer->here_ch_c_l();
393         }
394 /* cont: */
395         command_req     {
396                 $2-> defined_ch_c_l_ = $$->defined_ch_c_l_;
397                 $$->add($2);
398
399         }
400         ;
401
402 command_req:
403          '|'                            { 
404                 $$ = new Barcheck_req;
405         }
406         | BAR STRING                    {
407                 $$ = new Bar_req(*$2);
408                 delete $2;
409         }
410         | METER '{' int '*' int '}'     {
411                 Meter_change_req *m = new Meter_change_req;
412                 m->set($3,$5);
413                 $$ = m;
414         }
415         | SKIP '{' duration_length '}' {
416                 Skip_req * skip_p = new Skip_req;
417                 skip_p->duration_ = *$3;
418                 delete $3;
419                 $$ = skip_p;
420         }
421         | CADENZA '{' int '}'   {
422                 $$ = new Cadenza_req($3);
423         }
424         | PARTIAL '{' duration_length '}'       {
425                 $$ = new Partial_measure_req(*$3);
426                 delete $3;
427         }
428         | STEM '{' int '}'              {
429                 $$ = get_stemdir_req($3);
430         }
431         | CLEF STRING {
432                 $$ = new Clef_change_req(*$2);
433                 delete $2;
434         }
435         | KEY '{' pitch_list '}'        {       
436                 Key_change_req *key_p= new Key_change_req;
437                 key_p->melodic_p_arr_ = *$3;
438                 $$ = key_p;
439                 delete $3;
440         }
441         | GROUPING '{' intastint_list '}' {
442                 $$ = get_grouping_req(*$3); delete $3;
443         }
444         ;
445
446 post_requests:
447         {
448                 assert(post_reqs.empty());
449         }
450         | post_requests post_request {
451                 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
452                 post_reqs.push($2);
453         }
454         | post_requests close_plet_parens INT '/' INT { 
455                 post_reqs.push( get_request($2) ); 
456                 req_defined_ch_c_l = lexer->here_ch_c_l();
457                 post_reqs.push( get_plet_request( $2, $3, $5 ) ); 
458         }
459         ;
460
461 post_request:
462         close_request_parens    { 
463                 $$ = get_request($1); 
464         }
465         | script_req
466         | textscript_req
467         ;
468
469 close_plet_parens:
470         ']' {
471                 req_defined_ch_c_l = lexer->here_ch_c_l();
472                 $$ = ']';
473         }
474         ;
475
476 close_request_parens:
477         '('     { 
478                 $$='(';
479         }
480         | ']'   { 
481                 $$ = ']';
482         }
483         ;
484   
485 open_request_parens:
486         ')'     { 
487                 $$=')';
488         }
489         | '['   {
490                 $$='[';
491         }
492         ;
493
494 script_definition:
495         SCRIPT '{' script_body '}'      { $$ = $3; }
496         ;
497
498 script_body:
499         STRING int int int              {
500                 $$ = new Script_def(*$1,$2, $3,$4);
501                 delete $1;
502         }       
503         ;
504
505 textscript_req:
506         script_dir mudela_text          { $$ = get_text_req($1,$2); }
507         ;
508
509 mudela_text:
510         STRING                  { 
511                 defined_ch_c_l = lexer->here_ch_c_l();
512                 $$ = get_text(*$1); 
513                 delete $1;
514         }
515         ;
516
517 script_req:
518         script_dir mudela_script        { 
519                 $$ = get_script_req($1, $2);
520         }
521         ;
522
523 mudela_script:
524         IDENTIFIER              { $$ = $1->script(true); }
525         | script_definition             { $$ = $1; }
526         | '^'           { $$ = get_scriptdef('^'); }
527         | '+'           { $$ = get_scriptdef('+'); }
528         | '-'           { $$ = get_scriptdef('-'); }
529         | '|'           { $$ = get_scriptdef('|'); }
530         | 'o'           { $$ = get_scriptdef('o'); }
531         | '>'           { $$ = get_scriptdef('>'); }
532         | '.'           { $$ = get_scriptdef('.'); }
533         | DOTS          {
534                 if ( $1 > 1 ) 
535                     warning( "too many staccato dots", lexer->here_ch_c_l() );
536                 $$ = get_scriptdef('.');
537         }
538         | error {
539                 $$ = get_scriptdef('.');
540                 yyerrok;
541         }
542         ;
543
544 script_dir:
545         '_'     { $$ = -1; }
546         |'^'    { $$ = 1; }
547         |'-'    { $$ = 0; }
548         ;
549
550 pre_requests:
551         | pre_requests pre_request {
552                 pre_reqs.push($2);
553                 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
554         }
555         ;
556
557 pre_request: 
558         open_request_parens     { 
559                 defined_ch_c_l = lexer->here_ch_c_l();
560                 $$ = get_request($1); 
561         }
562         ;
563
564 voice_command:
565         PLET    '{' INT '/' INT '}'             {
566                 set_plet($3,$5);
567         }
568         | DURATIONCOMMAND '{' STRING '}'        {
569                 set_duration_mode(*$3);
570                 delete $3;
571         }
572         | DURATIONCOMMAND '{' notemode_duration '}'     {
573                 set_default_duration($3);
574         }
575         | OCTAVECOMMAND '{' pitchmod '}'        {
576                 set_default_octave(*$3);
577                 delete $3;
578         }
579         | TEXTSTYLE STRING      {
580                 set_text_style(*$2);
581                 delete $2;
582         }
583         ;
584
585 duration_length:        
586         mudela_duration         {
587                 $$ = new Moment(wholes($1[0], $1[1]));
588         }
589         |int '*' mudela_duration        {
590                 $$ = new Moment(Rational($1) * wholes($3[0], $3[1]));
591         }
592         ;
593
594 notemode_duration:
595         explicit_duration
596         | default_duration
597         ;
598
599 mudela_duration:
600         int             {
601                 $$[0] = $1;
602                 $$[1] = 0;
603         }
604         | int DOTS      {
605                 $$[0] = $1;
606                 $$[1] = $2;
607         }
608         ;
609
610
611 explicit_duration:
612         INT             {
613                 last_duration($1);
614                 $$[0] = $1;
615                 $$[1] = 0;
616         }
617         | INT DOTS      {
618                 last_duration($1);
619                 $$[0] = $1;
620                 $$[1] = $2;
621         }
622         | DOTS  {
623                 get_default_duration($$);
624                 $$[1] = $1;
625         }
626         | INT '*' INT '/' INT {
627                 // ugh, must use Duration
628                 set_plet( $3, $5 );
629                 $$[ 0 ] = $1;
630                 $$[ 1 ] = 0;
631                 set_plet( 1, 1 );
632         }
633         ;
634
635 default_duration:
636         {
637                 get_default_duration($$);
638         }
639         ;
640
641 pitchmod:               { 
642                 defined_ch_c_l = lexer->here_ch_c_l();
643                 $$ = new String; 
644         }
645         | PITCHMOD      { 
646                 defined_ch_c_l = lexer->here_ch_c_l();
647                 $$ = $1;
648         }
649         ;
650
651 notename:
652         NOTENAME
653         ;
654
655 voice_elt:
656         pitchmod notename notemode_duration                     {
657                 $$ = get_note_element(*$1, $2, $3);
658                 delete $1;
659         }
660         | RESTNAME notemode_duration            {
661                 $$ = get_rest_element(*$1, $2);
662                 delete $1;
663
664         }
665         ;
666
667 lyrics_elt:
668         mudela_text notemode_duration                   {
669                 $$ = get_word_element($1, $2);
670         };
671
672 /*
673         UTILITIES
674  */
675 pitch_list:                     {
676                 $$ = new Array<Melodic_req*>;
677         }
678         | pitch_list NOTENAME   {
679                 Melodic_req *m_p = new Melodic_req;
680                 m_p->notename_i_ = $2[0];
681                 m_p->accidental_i_ = $2[1];
682                 $$->push(m_p);
683         }
684         ;
685
686 int:
687         real                    {
688                 $$ = int($1);
689                 if ( distance($1,Real(int($$)) ) > 1e-8)
690                         error( "integer expected", lexer->here_ch_c_l() );
691         }
692         ;
693
694 real:
695         INT                     {
696                 $$ = Real($1);
697         }
698         | REAL          {
699                 $$ = $1;
700         }
701         | IDENTIFIER            {
702                 $$ = * $1->real(0);             
703         }
704         ;
705         
706
707
708 dim:
709         real unit       { $$ = $1*$2; }
710         ;
711
712
713 unit:   CM_T            { $$ = 1 CM; }
714         |IN_T           { $$ = 1 INCH; }
715         |MM_T           { $$ = 1 MM; }
716         |PT_T           { $$ = 1 PT; }
717         ;
718         
719 /*
720         symbol tables
721 */
722 symtables:
723         SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
724         ;
725
726 symtables_body:
727                         {
728                 $$ = new Lookup;
729         }
730         | IDENTIFIER            {
731                 $$ = new Lookup(*$1->lookup(true));
732         }
733         | symtables_body TEXID STRING           {
734                 $$->texsetting = *$3;
735                 delete $3;
736         }
737         | symtables_body STRING '=' symtable            {
738                 $$->add(*$2, $4);
739                 delete $2;
740         }
741         ;
742
743 symtable:
744         TABLE '{' symtable_body '}' { $$ = $3; }
745         ;
746
747 symtable_body:
748                                 { $$ = new Symtable; }
749         | symtable_body STRING  symboldef {
750                 $$->add(*$2, *$3);
751                 delete $2;
752                 delete $3;
753         }
754         ;
755
756 symboldef:
757         STRING  box             {
758                 $$ = new Symbol(*$1, *$2);
759                 delete $1;
760                 delete $2;
761         }
762         | STRING {
763                 Box b;
764                 $$ = new Symbol(*$1, b);
765                 delete $1;
766         }
767         ;
768
769 box:
770         dinterval dinterval     {
771                 $$ = new Box(*$1, *$2);
772                 delete $1;
773                 delete $2;
774         }
775         ;
776
777 dinterval: dim  dim             {
778                 $$ = new Interval($1, $2);      
779         }
780         ;
781
782 %%
783
784 void
785 yyerror(const char *s)
786 {
787         lexer->LexerError(s);
788
789         if ( fatal_error_i )
790                 exit( fatal_error_i );
791 }
792
793 void
794 parse_file(String init, String s)
795 {
796    *mlog << "Parsing ... ";
797    lexer = new My_flex_lexer;
798
799 #ifdef YYDEBUG
800    yydebug = !monitor->silence("InitParser") && check_debug;
801    lexer->set_debug( !monitor->silence("InitLexer") && check_debug);
802 #endif
803
804    lexer->new_input(init);
805    yyparse();
806
807 #ifdef YYDEBUG
808    yydebug = !monitor->silence("Parser") && check_debug;
809    lexer->set_debug( !monitor->silence("Lexer") && check_debug);
810 #endif
811
812    lexer->new_input(s);
813    yyparse();
814    delete lexer;
815    lexer = 0;
816
817    if(!define_spots.empty())
818         warning("Braces don't match.",0);
819 }
820
821 Paper_def*
822 default_paper()
823 {
824     return new Paper_def(
825         lexer->lookup_identifier("default_table")->lookup(true));
826 }
827
828