]> git.donarmstrong.com Git - lilypond.git/blob - src/parser.y
release: 0.0.30
[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 "paper.hh"
8 #include "inputscore.hh"
9 #include "main.hh"
10 #include "keyword.hh"
11 #include "inputcommand.hh"
12 #include "debug.hh"
13 #include "parseconstruct.hh"
14 #include "dimen.hh"
15 #include "identifier.hh"
16
17 #ifndef NDEBUG
18 #define YYDEBUG 1
19 #endif
20
21 Array<Request*> pre_reqs, post_reqs;
22 Array<const char *> define_spots;
23 Paperdef*default_paper();
24 char const* defined_ch_c_l;
25 char const* req_defined_ch_c_l;
26 int fatal_error_i = 0;
27
28 %}
29
30
31 %union {
32     Request * request;
33     Real real;
34     Input_command *command;
35     Identifier *id;    
36     Voice *voice;    
37     Voice_element *el;  
38     String *string;
39     const char *consstr;
40     Paperdef *paper;
41     Input_music *music;
42     Music_general_chord *chord;
43     Music_voice *mvoice; 
44     int i;
45     char c;
46     int ii[10];
47         Moment *moment;
48
49     Array<String> * strvec;
50     Array<Input_command*> *commandvec;
51     Array<int> *intvec;
52
53     Input_staff *staff;    
54     Input_score *score;
55     Symtables * symtables;
56     Symtable * symtable;
57     Symbol * symbol;
58     Lookup*lookup;
59     Interval *interval;
60     Box *box;
61     Notename_tab *notename_tab;
62     Script_def * script;
63     Text_def * textdef;
64 }
65
66 %token VOICE STAFF SCORE TITLE  BAR  OUTPUT MULTIVOICE
67 %token CM_T IN_T PT_T MM_T PAPER WIDTH METER UNITSPACE SKIP COMMANDS COMMAND
68 %token GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
69 %token KEY CLEF  TABLE  VOICES STEM
70 %token PARTIAL MUSIC GROUPING CADENZA
71 %token END SYMBOLTABLES TEXID TABLE NOTENAMES SCRIPT TEXTSTYLE PLET
72 %token MARK GOTO
73
74 %token <id>  IDENTIFIER
75 %token <string> PITCHMOD DURATION RESTNAME
76 %token <ii> NOTENAME 
77 %token <real> REAL 
78 %token <string> STRING
79
80 %token <i> DOTS INT
81 %type <real> unit
82 %type <intvec> pitch_list 
83 %type <c> open_request_parens close_request_parens
84 %type <id> declaration
85 %type <string> declarable_identifier
86 %type <paper> paper_block paper_body
87 %type <real> dim real
88 %type <ii>  default_duration explicit_duration notemode_duration mudela_duration
89 %type <ii> notename
90 %type <moment> duration_length
91 %type <el> voice_elt full_element lyrics_elt
92 %type <command> score_command staff_command position_command
93 %type <score> score_block score_body
94 %type <staff> staff_block staff_init staff_body
95 %type <i> int
96 %type <intvec> int_list intastint_list
97 %type <commandvec> score_commands_block score_commands_body
98 %type <commandvec> staff_commands_block staff_commands_body
99 %type <request> post_request pre_request 
100 %type <string> pitchmod
101 %type <music> music 
102 %type <chord> music_chord music_chord_body
103
104 %type <mvoice>  music_voice_body music_voice 
105
106 %type <interval> dinterval
107 %type <box> box
108 %type <symtable> symtable symtable_body
109 %type <lookup> symtables symtables_body
110 %type <symbol> symboldef
111 %type <notename_tab> notename_tab notename_tab_body
112 %type <i> script_dir
113 %type <script> script_definition script_body mudela_script
114 %type <request> script_req textscript_req
115 %type <textdef> mudela_text
116
117
118 %%
119
120 mudela: /* empty */
121         | mudela score_block {
122                 add_score($2);          
123         }
124         | mudela add_declaration { }
125         | mudela mudela_command  {}
126         ;
127
128 mudela_command:
129         notename_tab                    { lexer->set($1); }
130         ;
131
132 /*
133         DECLARATIONS
134 */
135 add_declaration: declaration    {
136                 lexer->add_identifier($1);
137         }
138         ;
139
140 declarable_identifier:
141         STRING { $$ = $1; }
142         | IDENTIFIER { $$ = new String($1->name); }
143         ;
144
145 declaration:
146         declarable_identifier '=' staff_block  {
147                 $$ = new Staff_id(*$1, $3);
148                 delete $1; // this sux
149         }
150         | declarable_identifier '=' music_voice {
151                 $$ = new M_voice_id(*$1, $3);
152                 delete $1;
153         }
154         | declarable_identifier '=' script_definition {
155                 $$ = new Script_id(*$1, $3);
156                 delete $1;
157         }
158         | declarable_identifier '=' music_chord  {
159                 $$ = new M_chord_id(*$1, $3);
160                 delete $1;
161         }
162         | declarable_identifier '=' symtables {
163                 $$ = new Lookup_id(*$1, $3);
164                 delete $1;
165         }
166         | declarable_identifier '=' notename_tab {
167                 $$ = new Notetab_id(*$1, $3);
168                 delete $1;
169         }
170         | declarable_identifier '=' real        {
171                 $$ = new Real_id(*$1, new Real($3));
172                 delete $1;
173         }
174         | declarable_identifier error '}' {
175 //              warning( "parse error", lexer->here_ch_c_l() );
176         }
177         ;
178
179 notename_tab:
180         NOTENAMES '{' notename_tab_body '}'     { $$ = $3; }
181         ;
182
183 notename_tab_body:                              {
184                 $$ = new Notename_tab;
185         }
186         | IDENTIFIER                            {
187                 $$ = $1->notename_tab(true);
188         }
189         | notename_tab_body STRING int int                      {
190                 $$->set($3, $4, *$2);
191                 delete $2;
192         }
193         ;
194
195 /*
196         SCORE
197 */
198 score_block: SCORE 
199                 { define_spots.push(lexer->here_ch_c_l()); }
200         '{' score_body '}'      {
201                 $$ = $4;
202                 $$->defined_ch_c_l_ = define_spots.pop();
203                 if (!$$->paper_)
204                         $$->paper_ = default_paper();
205
206                 /* handle error levels. */
207                 $$->errorlevel_i_ = lexer->errorlevel_i_;
208                 lexer->errorlevel_i_ = 0;
209         }
210         ;
211
212 score_body:             { 
213                 $$ = new Input_score; 
214         }
215         | score_body staff_block        { $$->add($2); }
216         | score_body score_commands_block       {
217                 $$->add(*$2);
218                 delete $2;
219         }
220         | score_body paper_block                { $$->set($2);  }
221         ;
222 /*
223         COMMANDS
224 */
225 score_commands_block:
226         COMMANDS '{' score_commands_body '}' { $$ =$3;}
227         | COMMANDS '{' error '}' {
228 //              warning( "parse error", lexer->here_ch_c_l() );
229         }
230         ;
231
232 score_commands_body:                    { $$ = new Array<Input_command*>; }
233         | score_commands_body score_command             {
234                 $$->push($2);
235         }
236         | score_commands_body position_command          {
237                 $$->push($2);
238         }
239         ;
240
241 staff_commands_block: COMMANDS '{' staff_commands_body '}'      {       
242                 $$ = $3; }
243         ;
244
245 staff_commands_body:
246         /* empty */                     { $$ = new Array<Input_command*>; }
247         | staff_commands_body staff_command     {
248                 $$->push($2);
249         }
250         | staff_commands_body position_command  {
251                 $$->push($2);
252         }
253         ;
254
255 staff_command:
256         KEY pitch_list  {/*UGH*/
257                 $$ = get_key_interpret_command(*$2);
258                 delete $2;
259         }
260         | CLEF STRING                   {
261                 $$ = get_clef_interpret_command(*$2);
262                 delete $2;
263         }
264         ;
265
266 position_command:
267         SKIP int ':' duration_length            {
268                 $$ = get_skip_command($2, *$4);
269                 delete $4;
270         }
271         | GOTO STRING   {
272                 $$ = get_goto_command(*$2);
273                 delete $2;
274         }
275         ;
276
277
278 intastint_list:
279         /* */   { $$ =new Array<int>; }
280         | intastint_list int '*' int    {
281                 $$->push($2); $$->push($4);
282         }
283         ;
284
285 score_command:
286         BAR STRING                      {
287                 $$ = get_bar_command(*$2);
288                 delete $2;
289         }
290         | METER  int '*' int            {
291                 $$ = get_meterchange_command($2, $4);
292         }
293         | PARTIAL duration_length               {
294                 $$ = get_partial_command(*$2);
295                 delete $2;
296         }
297         | GROUPING intastint_list               {
298                 $$ = get_grouping_command(*$2);
299                 delete $2;
300         }
301         | CADENZA int   {
302                 $$ = get_cadenza_toggle($2);
303         }
304         ;
305
306
307
308 /*
309         PAPER
310 */
311 paper_block:
312         PAPER
313
314         '{' paper_body '}'      { $$ = $3; }
315         ;
316
317 paper_body:
318         /* empty */                     {
319                 $$ = default_paper();
320         }
321         | paper_body WIDTH dim          { $$->linewidth = $3;}
322         | paper_body OUTPUT STRING      { $$->outfile = *$3;
323                 delete $3;
324         }
325         | paper_body symtables          { $$->set($2); }
326         | paper_body UNITSPACE dim      { $$->whole_width = $3; }
327         | paper_body GEOMETRIC REAL     { $$->geometric_ = $3; }
328         | paper_body error {
329 //              warning( "parse error", lexer->here_ch_c_l() );
330         }
331         ;
332
333 /*
334         STAFFs
335 */
336 staff_block:
337         STAFF   { define_spots.push(lexer->here_ch_c_l()); }
338 /*cont*/        '{' staff_body '}'      {
339                 $$ = $4; 
340                 $$-> defined_ch_c_l_ = define_spots.pop();
341         }
342         ;
343
344
345
346 staff_init:
347         IDENTIFIER              { $$ = $1->staff(true); }
348         | STRING                {
349                 $$ = new Input_staff(*$1);
350                 delete $1;
351         }
352         ;
353
354 staff_body:
355         staff_init
356         | staff_body music      {
357                 $2->set_default_group( "staff_music" + String($$->music_.size()));
358                 $$->add($2);
359         }
360         | staff_body staff_commands_block {
361                 $$->add(*$2);
362                 delete $2;
363         }
364         | staff_body error {
365 //              warning( "parse error", lexer->here_ch_c_l() );
366         }
367         ;
368
369 /*
370         MUSIC
371 */
372 music:
373         music_voice     { $$ = $1; }
374         | music_chord   { $$ = $1; }
375         ;
376
377 music_voice:  MUSIC '{' music_voice_body '}'    { $$ = $3; }
378         ;
379
380 music_voice_body:
381         /* */   {
382                 $$ = new Music_voice;
383         }
384         | music_voice_body IDENTIFIER {
385                 $$->concatenate($2->mvoice(true));
386         }
387         | music_voice_body full_element {
388                 $$->add_elt($2);
389         }
390         | music_voice_body voice_command {
391         }
392         | music_voice_body music        {
393                 $$->add($2);
394         }
395         | music_voice_body error {
396 //              warning( "parse error", lexer->here_ch_c_l() );
397         }
398         ;
399
400 music_chord:  '{' music_chord_body '}'  { $$ = $2; }
401         ;
402
403 music_chord_body:
404         /* */   {
405                 $$ = new Voice_group_chord;
406         }
407         | MULTIVOICE {
408                 $$ = new Multi_voice_chord;
409         }
410         | music_chord_body IDENTIFIER {
411                 $$->concatenate($2->mchord(true));
412         }
413         | music_chord_body music {
414                 $$ -> add($2);
415         }
416         | music_chord_body full_element {
417                 $$ ->add_elt($2);
418         }
419         | music_chord_body error {
420 //              warning( "parse error", lexer->here_ch_c_l() );
421         }
422         ;
423
424
425
426 /*
427         VOICE ELEMENTS
428 */
429 full_element:   pre_requests voice_elt post_requests {
430                 add_requests($2, pre_reqs);
431                 add_requests($2, post_reqs);
432                 $$ = $2;
433         }
434         | MARK STRING   {
435                 $$ = get_mark_element(*$2);
436                 delete $2;
437         }
438         | COMMAND '{' staff_command '}' { $$=get_command_element($3); }
439         | COMMAND '{' score_command '}' { $$=get_command_element($3); }
440         | '|'                           { 
441                 req_defined_ch_c_l = lexer->here_ch_c_l();
442                 $$ = get_barcheck_element(); 
443         }
444         | STEM '{' int '}'              {
445                 req_defined_ch_c_l = lexer->here_ch_c_l();
446                 $$ = get_stemdir_element($3);
447         }
448         | lyrics_elt
449 /*
450 +       | pre_requests voice_elt post_requests error '|' { 
451 +               warning( "parse error", lexer->here_ch_c_l() );
452 +       }
453 + */
454         ;
455                 
456 post_requests:
457         {
458                 assert(post_reqs.empty());
459         }
460         | post_requests post_request {
461                 post_reqs.push($2);
462         }
463         ;
464
465 post_request:
466         close_request_parens    { 
467                 req_defined_ch_c_l = lexer->here_ch_c_l();
468                 $$ = get_request($1); 
469         }
470         | script_req
471         | textscript_req
472         ;
473
474 close_request_parens:
475         '('     { 
476                 req_defined_ch_c_l = lexer->here_ch_c_l();
477                 $$='(';
478         }
479         | ']'   { 
480                 req_defined_ch_c_l = lexer->here_ch_c_l();
481                 $$ = ']';
482         }
483         ;
484   
485 open_request_parens:
486         ')'     { 
487                 req_defined_ch_c_l = lexer->here_ch_c_l();
488                 $$=')';
489         }
490         | '['   {
491                 req_defined_ch_c_l = lexer->here_ch_c_l();
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         }
556         ;
557
558 pre_request: 
559         open_request_parens     { 
560                 defined_ch_c_l = lexer->here_ch_c_l();
561                 $$ = get_request($1); 
562         }
563         ;
564
565 voice_command:
566         PLET    '{' INT '/' INT '}'             {
567                 set_plet($3,$5);
568         }
569         | DURATIONCOMMAND '{' STRING '}'        {
570                 set_duration_mode(*$3);
571                 delete $3;
572         }
573         | DURATIONCOMMAND '{' notemode_duration '}'     {
574                 set_default_duration($3);
575         }
576         | OCTAVECOMMAND '{' pitchmod '}'        {
577                 set_default_octave(*$3);
578                 delete $3;
579         }
580         | TEXTSTYLE STRING      {
581                 set_text_style(*$2);
582                 delete $2;
583         }
584         ;
585
586 duration_length:        
587         mudela_duration         {
588                 $$ = new Moment(wholes($1[0], $1[1]));
589         }
590         |int '*' mudela_duration        {
591                 $$ = new Moment(Rational($1) * wholes($3[0], $3[1]));
592         }
593         ;
594
595 notemode_duration:
596         explicit_duration
597         | default_duration
598         ;
599
600 mudela_duration:
601         int             {
602                 $$[0] = $1;
603                 $$[1] = 0;
604         }
605         | int DOTS      {
606                 $$[0] = $1;
607                 $$[1] = $2;
608         }
609         ;
610
611
612 explicit_duration:
613         INT             {
614                 last_duration($1);
615                 $$[0] = $1;
616                 $$[1] = 0;
617         }
618         | INT DOTS      {
619                 last_duration($1);
620                 $$[0] = $1;
621                 $$[1] = $2;
622         }
623         | DOTS  {
624                 get_default_duration($$);
625                 $$[1] = $1;
626         }
627         ;
628
629 default_duration:
630         {
631                 get_default_duration($$);
632         }
633         ;
634
635 pitchmod:               { 
636                 defined_ch_c_l = lexer->here_ch_c_l();
637                 $$ = new String; 
638         }
639         | PITCHMOD      { 
640                 defined_ch_c_l = lexer->here_ch_c_l();
641                 $$ = $1;
642         }
643         ;
644
645 notename:
646         NOTENAME
647         ;
648
649 voice_elt:
650         pitchmod notename notemode_duration                     {
651                 $$ = get_note_element(*$1, $2, $3);
652                 delete $1;
653         }
654         | RESTNAME notemode_duration            {
655                 $$ = get_rest_element(*$1, $2);
656                 delete $1;
657
658         }
659         ;
660
661 lyrics_elt:
662         mudela_text notemode_duration                   {
663                 $$ = get_word_element($1, $2);
664         };
665
666 /*
667         UTILITIES
668 */
669 pitch_list:                     {
670                 $$ = new Array<int>;
671         }
672         | pitch_list NOTENAME   {
673                 $$->push($2[0]);
674                 $$->push($2[1]);                
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 int_list:               {
700                 $$ = new Array<int>;
701         }
702         | int_list int          {
703                 $$->push($2);
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 //      if ( YYRECOVERING() ) 
788 //              return;
789         lexer->LexerError(s);
790
791         if ( fatal_error_i )
792                 exit( fatal_error_i );
793 }
794
795 void
796 parse_file(String init, String s)
797 {
798    *mlog << "Parsing ... ";
799    lexer = new My_flex_lexer;
800
801 #ifdef YYDEBUG
802    yydebug = !monitor.silence("InitParser") && check_debug;
803    lexer->set_debug( !monitor.silence("InitLexer") && check_debug);
804 #endif
805
806    lexer->new_input(init);
807    yyparse();
808
809 #ifdef YYDEBUG
810    yydebug = !monitor.silence("Parser") && check_debug;
811    lexer->set_debug( !monitor.silence("Lexer") && check_debug);
812 #endif
813
814    lexer->new_input(s);
815    yyparse();
816    delete lexer;
817    lexer = 0;
818
819    assert(define_spots.empty());
820 }
821
822 Paperdef*
823 default_paper()
824 {
825     return new Paperdef(
826         lexer->lookup_identifier("default_table")->lookup(true));
827 }
828
829