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