]> git.donarmstrong.com Git - lilypond.git/blob - src/parser.y
f761069e3e7b8c7a1efa1502891dc7f18ae4b925
[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     Mididef* 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_)
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 Mididef; 
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         | MIDI          {
304                 $$ = new Input_staff("midi");
305         }
306         ;
307
308 staff_body:
309         staff_init
310         | staff_body COMMANDS '{' music_voice_body '}'  {
311                 $$->set_score_wide($4);
312         }
313         | staff_body music      {
314                 $2->set_default_group( "staff_music" + String($$->music_.size()));
315                 $$->add($2);
316         }
317         | staff_body error {
318         }
319         ;
320
321 /*
322         MUSIC
323 */
324 music:
325         music_voice     { $$ = $1; }
326         | music_chord   { $$ = $1; }
327         ;
328
329 music_voice:  MUSIC '{' music_voice_body '}'    { $$ = $3; }
330         ;
331
332 music_voice_body:
333         /* */   {
334                 $$ = new Music_voice;
335         }
336         | music_voice_body IDENTIFIER {
337                 $$->concatenate($2->mvoice(true));
338         }
339         | music_voice_body full_element {
340                 $$->add_elt($2);
341         }
342         | music_voice_body voice_command {
343         }
344         | music_voice_body music        {
345                 $$->add($2);
346         }
347         | music_voice_body error {
348         }
349         ;
350
351 music_chord:  '{' music_chord_body '}'  { $$ = $2; }
352         ;
353
354 music_chord_body:
355         /* */   {
356                 $$ = new Voice_group_chord;
357         }
358         | MULTIVOICE {
359                 $$ = new Multi_voice_chord;
360         }
361         | music_chord_body IDENTIFIER {
362                 $$->concatenate($2->mchord(true));
363         }
364         | music_chord_body music {
365                 $$->add($2);
366         }
367         | music_chord_body full_element {
368                 $$ ->add_elt($2);
369         }
370         | music_chord_body error {
371         }
372         ;
373
374
375 /*
376         VOICE ELEMENTS
377 */
378 full_element:   pre_requests voice_elt post_requests {
379                 add_requests($2, pre_reqs);
380                 add_requests($2, post_reqs);
381                 $$ = $2;
382         }
383         | pre_requests lyrics_elt post_requests {
384                 add_requests($2, pre_reqs);
385                 add_requests($2, post_reqs);
386                 $$ = $2;
387         }
388         | command_elt
389         ;
390
391 command_elt:
392 /* empty */     {
393                 $$ = new Voice_element;
394                 $$-> defined_ch_c_l_ = lexer->here_ch_c_l();
395         }
396 /* cont: */
397         command_req     {
398                 $2-> defined_ch_c_l_ = $$->defined_ch_c_l_;
399                 $$->add($2);
400
401         }
402         ;
403
404 command_req:
405          '|'                            { 
406                 $$ = new Barcheck_req;
407         }
408         | BAR STRING                    {
409                 $$ = new Bar_req(*$2);
410                 delete $2;
411         }
412         | METER '{' int '*' int '}'     {
413                 Meter_change_req *m = new Meter_change_req;
414                 m->set($3,$5);
415                 $$ = m;
416         }
417         | SKIP '{' duration_length '}' {
418                 Skip_req * skip_p = new Skip_req;
419                 skip_p->duration_ = *$3;
420                 delete $3;
421                 $$ = skip_p;
422         }
423         | CADENZA '{' int '}'   {
424                 $$ = new Cadenza_req($3);
425         }
426         | PARTIAL '{' duration_length '}'       {
427                 $$ = new Partial_measure_req(*$3);
428                 delete $3;
429         }
430         | STEM '{' int '}'              {
431                 $$ = get_stemdir_req($3);
432         }
433         | CLEF STRING {
434                 $$ = new Clef_change_req(*$2);
435                 delete $2;
436         }
437         | KEY '{' pitch_list '}'        {       
438                 Key_change_req *key_p= new Key_change_req;
439                 key_p->melodic_p_arr_ = *$3;
440                 $$ = key_p;
441                 delete $3;
442         }
443         | GROUPING '{' intastint_list '}' {
444                 $$ = get_grouping_req(*$3); delete $3;
445         }
446         ;
447
448 post_requests:
449         {
450                 assert(post_reqs.empty());
451         }
452         | post_requests post_request {
453                 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
454                 post_reqs.push($2);
455         }
456         | post_requests close_plet_parens INT '/' INT { 
457                 post_reqs.push( get_request($2) ); 
458                 req_defined_ch_c_l = lexer->here_ch_c_l();
459                 post_reqs.push( get_plet_request( $2, $3, $5 ) ); 
460         }
461         ;
462
463 post_request:
464         close_request_parens    { 
465                 $$ = get_request($1); 
466         }
467         | script_req
468         | textscript_req
469         ;
470
471 close_plet_parens:
472         ']' {
473                 req_defined_ch_c_l = lexer->here_ch_c_l();
474                 $$ = ']';
475         }
476         ;
477
478 close_request_parens:
479         '('     { 
480                 $$='(';
481         }
482         | ']'   { 
483                 $$ = ']';
484         }
485         ;
486   
487 open_request_parens:
488         ')'     { 
489                 $$=')';
490         }
491         | '['   {
492                 $$='[';
493         }
494         ;
495
496 script_definition:
497         SCRIPT '{' script_body '}'      { $$ = $3; }
498         ;
499
500 script_body:
501         STRING int int int              {
502                 $$ = new Script_def(*$1,$2, $3,$4);
503                 delete $1;
504         }       
505         ;
506
507 textscript_req:
508         script_dir mudela_text          { $$ = get_text_req($1,$2); }
509         ;
510
511 mudela_text:
512         STRING                  { 
513                 defined_ch_c_l = lexer->here_ch_c_l();
514                 $$ = get_text(*$1); 
515                 delete $1;
516         }
517         ;
518
519 script_req:
520         script_dir mudela_script        { 
521                 $$ = get_script_req($1, $2);
522         }
523         ;
524
525 mudela_script:
526         IDENTIFIER              { $$ = $1->script(true); }
527         | script_definition             { $$ = $1; }
528         | '^'           { $$ = get_scriptdef('^'); }
529         | '+'           { $$ = get_scriptdef('+'); }
530         | '-'           { $$ = get_scriptdef('-'); }
531         | '|'           { $$ = get_scriptdef('|'); }
532         | 'o'           { $$ = get_scriptdef('o'); }
533         | '>'           { $$ = get_scriptdef('>'); }
534         | '.'           { $$ = get_scriptdef('.'); }
535         | DOTS          {
536                 if ( $1 > 1 ) 
537                     warning( "too many staccato dots", lexer->here_ch_c_l() );
538                 $$ = get_scriptdef('.');
539         }
540         | error {
541                 $$ = get_scriptdef('.');
542                 yyerrok;
543         }
544         ;
545
546 script_dir:
547         '_'     { $$ = -1; }
548         |'^'    { $$ = 1; }
549         |'-'    { $$ = 0; }
550         ;
551
552 pre_requests:
553         | pre_requests pre_request {
554                 pre_reqs.push($2);
555                 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
556         }
557         ;
558
559 pre_request: 
560         open_request_parens     { 
561                 defined_ch_c_l = lexer->here_ch_c_l();
562                 $$ = get_request($1); 
563         }
564         ;
565
566 voice_command:
567         PLET    '{' INT '/' INT '}'             {
568                 set_plet($3,$5);
569         }
570         | DURATIONCOMMAND '{' STRING '}'        {
571                 set_duration_mode(*$3);
572                 delete $3;
573         }
574         | DURATIONCOMMAND '{' notemode_duration '}'     {
575                 set_default_duration($3);
576         }
577         | OCTAVECOMMAND '{' pitchmod '}'        {
578                 set_default_octave(*$3);
579                 delete $3;
580         }
581         | TEXTSTYLE STRING      {
582                 set_text_style(*$2);
583                 delete $2;
584         }
585         ;
586
587 duration_length:        
588         mudela_duration         {
589                 $$ = new Moment(wholes($1[0], $1[1]));
590         }
591         |int '*' mudela_duration        {
592                 $$ = new Moment(Rational($1) * wholes($3[0], $3[1]));
593         }
594         ;
595
596 notemode_duration:
597         explicit_duration
598         | default_duration
599         ;
600
601 mudela_duration:
602         int             {
603                 $$[0] = $1;
604                 $$[1] = 0;
605         }
606         | int DOTS      {
607                 $$[0] = $1;
608                 $$[1] = $2;
609         }
610         ;
611
612
613 explicit_duration:
614         INT             {
615                 last_duration($1);
616                 $$[0] = $1;
617                 $$[1] = 0;
618         }
619         | INT DOTS      {
620                 last_duration($1);
621                 $$[0] = $1;
622                 $$[1] = $2;
623         }
624         | DOTS  {
625                 get_default_duration($$);
626                 $$[1] = $1;
627         }
628         ;
629
630 default_duration:
631         {
632                 get_default_duration($$);
633         }
634         ;
635
636 pitchmod:               { 
637                 defined_ch_c_l = lexer->here_ch_c_l();
638                 $$ = new String; 
639         }
640         | PITCHMOD      { 
641                 defined_ch_c_l = lexer->here_ch_c_l();
642                 $$ = $1;
643         }
644         ;
645
646 notename:
647         NOTENAME
648         ;
649
650 voice_elt:
651         pitchmod notename notemode_duration                     {
652                 $$ = get_note_element(*$1, $2, $3);
653                 delete $1;
654         }
655         | RESTNAME notemode_duration            {
656                 $$ = get_rest_element(*$1, $2);
657                 delete $1;
658
659         }
660         ;
661
662 lyrics_elt:
663         mudela_text notemode_duration                   {
664                 $$ = get_word_element($1, $2);
665         };
666
667 /*
668         UTILITIES
669  */
670 pitch_list:                     {
671                 $$ = new Array<Melodic_req*>;
672         }
673         | pitch_list NOTENAME   {
674                 Melodic_req *m_p = new Melodic_req;
675                 m_p->notename_i_ = $2[0];
676                 m_p->accidental_i_ = $2[1];
677                 $$->push(m_p);
678         }
679         ;
680
681 int:
682         real                    {
683                 $$ = int($1);
684                 if ( distance($1,Real(int($$)) ) > 1e-8)
685                         error( "integer expected", lexer->here_ch_c_l() );
686         }
687         ;
688
689 real:
690         INT                     {
691                 $$ = Real($1);
692         }
693         | REAL          {
694                 $$ = $1;
695         }
696         | IDENTIFIER            {
697                 $$ = * $1->real(0);             
698         }
699         ;
700         
701
702
703 dim:
704         real unit       { $$ = $1*$2; }
705         ;
706
707
708 unit:   CM_T            { $$ = 1 CM; }
709         |IN_T           { $$ = 1 INCH; }
710         |MM_T           { $$ = 1 MM; }
711         |PT_T           { $$ = 1 PT; }
712         ;
713         
714 /*
715         symbol tables
716 */
717 symtables:
718         SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
719         ;
720
721 symtables_body:
722                         {
723                 $$ = new Lookup;
724         }
725         | IDENTIFIER            {
726                 $$ = new Lookup(*$1->lookup(true));
727         }
728         | symtables_body TEXID STRING           {
729                 $$->texsetting = *$3;
730                 delete $3;
731         }
732         | symtables_body STRING '=' symtable            {
733                 $$->add(*$2, $4);
734                 delete $2;
735         }
736         ;
737
738 symtable:
739         TABLE '{' symtable_body '}' { $$ = $3; }
740         ;
741
742 symtable_body:
743                                 { $$ = new Symtable; }
744         | symtable_body STRING  symboldef {
745                 $$->add(*$2, *$3);
746                 delete $2;
747                 delete $3;
748         }
749         ;
750
751 symboldef:
752         STRING  box             {
753                 $$ = new Symbol(*$1, *$2);
754                 delete $1;
755                 delete $2;
756         }
757         | STRING {
758                 Box b;
759                 $$ = new Symbol(*$1, b);
760                 delete $1;
761         }
762         ;
763
764 box:
765         dinterval dinterval     {
766                 $$ = new Box(*$1, *$2);
767                 delete $1;
768                 delete $2;
769         }
770         ;
771
772 dinterval: dim  dim             {
773                 $$ = new Interval($1, $2);      
774         }
775         ;
776
777 %%
778
779 void
780 yyerror(const char *s)
781 {
782         lexer->LexerError(s);
783
784         if ( fatal_error_i )
785                 exit( fatal_error_i );
786 }
787
788 void
789 parse_file(String init, String s)
790 {
791    *mlog << "Parsing ... ";
792    lexer = new My_flex_lexer;
793
794 #ifdef YYDEBUG
795    yydebug = !monitor->silence("InitParser") && check_debug;
796    lexer->set_debug( !monitor->silence("InitLexer") && check_debug);
797 #endif
798
799    lexer->new_input(init);
800    yyparse();
801
802 #ifdef YYDEBUG
803    yydebug = !monitor->silence("Parser") && check_debug;
804    lexer->set_debug( !monitor->silence("Lexer") && check_debug);
805 #endif
806
807    lexer->new_input(s);
808    yyparse();
809    delete lexer;
810    lexer = 0;
811
812    if(!define_spots.empty())
813         warning("Braces don't match.",0);
814 }
815
816 Paperdef*
817 default_paper()
818 {
819     return new Paperdef(
820         lexer->lookup_identifier("default_table")->lookup(true));
821 }
822
823