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