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