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