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