]> git.donarmstrong.com Git - lilypond.git/blob - src/parser.y
release: 0.0.34
[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         ;
626
627 default_duration:
628         {
629                 get_default_duration($$);
630         }
631         ;
632
633 pitchmod:               { 
634                 defined_ch_c_l = lexer->here_ch_c_l();
635                 $$ = new String; 
636         }
637         | PITCHMOD      { 
638                 defined_ch_c_l = lexer->here_ch_c_l();
639                 $$ = $1;
640         }
641         ;
642
643 notename:
644         NOTENAME
645         ;
646
647 voice_elt:
648         pitchmod notename notemode_duration                     {
649                 $$ = get_note_element(*$1, $2, $3);
650                 delete $1;
651         }
652         | RESTNAME notemode_duration            {
653                 $$ = get_rest_element(*$1, $2);
654                 delete $1;
655
656         }
657         ;
658
659 lyrics_elt:
660         mudela_text notemode_duration                   {
661                 $$ = get_word_element($1, $2);
662         };
663
664 /*
665         UTILITIES
666  */
667 pitch_list:                     {
668                 $$ = new Array<Melodic_req*>;
669         }
670         | pitch_list NOTENAME   {
671                 Melodic_req *m_p = new Melodic_req;
672                 m_p->notename_i_ = $2[0];
673                 m_p->accidental_i_ = $2[1];
674                 $$->push(m_p);
675         }
676         ;
677
678 int:
679         real                    {
680                 $$ = int($1);
681                 if ( distance($1,Real(int($$)) ) > 1e-8)
682                         error( "integer expected", lexer->here_ch_c_l() );
683         }
684         ;
685
686 real:
687         INT                     {
688                 $$ = Real($1);
689         }
690         | REAL          {
691                 $$ = $1;
692         }
693         | IDENTIFIER            {
694                 $$ = * $1->real(0);             
695         }
696         ;
697         
698
699
700 dim:
701         real unit       { $$ = $1*$2; }
702         ;
703
704
705 unit:   CM_T            { $$ = 1 CM; }
706         |IN_T           { $$ = 1 INCH; }
707         |MM_T           { $$ = 1 MM; }
708         |PT_T           { $$ = 1 PT; }
709         ;
710         
711 /*
712         symbol tables
713 */
714 symtables:
715         SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
716         ;
717
718 symtables_body:
719                         {
720                 $$ = new Lookup;
721         }
722         | IDENTIFIER            {
723                 $$ = new Lookup(*$1->lookup(true));
724         }
725         | symtables_body TEXID STRING           {
726                 $$->texsetting = *$3;
727                 delete $3;
728         }
729         | symtables_body STRING '=' symtable            {
730                 $$->add(*$2, $4);
731                 delete $2;
732         }
733         ;
734
735 symtable:
736         TABLE '{' symtable_body '}' { $$ = $3; }
737         ;
738
739 symtable_body:
740                                 { $$ = new Symtable; }
741         | symtable_body STRING  symboldef {
742                 $$->add(*$2, *$3);
743                 delete $2;
744                 delete $3;
745         }
746         ;
747
748 symboldef:
749         STRING  box             {
750                 $$ = new Symbol(*$1, *$2);
751                 delete $1;
752                 delete $2;
753         }
754         | STRING {
755                 Box b;
756                 $$ = new Symbol(*$1, b);
757                 delete $1;
758         }
759         ;
760
761 box:
762         dinterval dinterval     {
763                 $$ = new Box(*$1, *$2);
764                 delete $1;
765                 delete $2;
766         }
767         ;
768
769 dinterval: dim  dim             {
770                 $$ = new Interval($1, $2);      
771         }
772         ;
773
774 %%
775
776 void
777 yyerror(const char *s)
778 {
779         lexer->LexerError(s);
780
781         if ( fatal_error_i )
782                 exit( fatal_error_i );
783 }
784
785 void
786 parse_file(String init, String s)
787 {
788    *mlog << "Parsing ... ";
789    lexer = new My_flex_lexer;
790
791 #ifdef YYDEBUG
792    yydebug = !monitor->silence("InitParser") && check_debug;
793    lexer->set_debug( !monitor->silence("InitLexer") && check_debug);
794 #endif
795
796    lexer->new_input(init);
797    yyparse();
798
799 #ifdef YYDEBUG
800    yydebug = !monitor->silence("Parser") && check_debug;
801    lexer->set_debug( !monitor->silence("Lexer") && check_debug);
802 #endif
803
804    lexer->new_input(s);
805    yyparse();
806    delete lexer;
807    lexer = 0;
808
809    if(!define_spots.empty())
810         warning("Braces don't match.",0);
811 }
812
813 Paperdef*
814 default_paper()
815 {
816     return new Paperdef(
817         lexer->lookup_identifier("default_table")->lookup(true));
818 }
819
820