]> git.donarmstrong.com Git - lilypond.git/blob - src/parser.y
release: 0.0.18
[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 "inputstaff.hh"
10 #include "inputscore.hh"
11 #include "inputmusic.hh"
12 #include "main.hh"
13 #include "keyword.hh"
14 #include "inputcommand.hh"
15 #include "debug.hh"
16 #include "parseconstruct.hh"
17 #include "dimen.hh"
18 #include "identifier.hh"
19
20 #ifndef NDEBUG
21 #define YYDEBUG 1
22 #endif
23
24 svec<Request*> pre_reqs, post_reqs;
25
26 Paperdef*default_paper();
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
47     svec<String> * strvec;
48     svec<Input_command*> *commandvec;
49     svec<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 }
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
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
108 %%
109
110 mudela: /* empty */
111         | mudela score_block { 
112                 add_score($2);
113         }
114         | mudela add_declaration { }
115         | mudela mudela_command  {}
116         ;
117
118 mudela_command:
119         notename_tab                    { lexer->set($1); }
120         ;
121
122 /*
123         DECLARATIONS
124 */
125 add_declaration: declaration    {
126                 lexer->add_identifier($1);
127         }
128         ;
129
130 declarable_identifier:
131         NEWIDENTIFIER { $$ = $1; }
132         | IDENTIFIER { $$ = new String($1->name); }
133         ;
134
135 declaration:
136         declarable_identifier '=' staff_block  {
137                 $$ = new Staff_id(*$1, $3);
138                 delete $1; // this sux
139         }
140         | declarable_identifier '=' music_voice {
141                 $$ = new M_voice_id(*$1, $3);
142                 delete $1;
143         }
144         | declarable_identifier '=' music_chord  {
145                 $$ = new M_chord_id(*$1, $3);
146                 delete $1;
147         }
148         | declarable_identifier '=' symtables {
149                 $$ = new Lookup_id(*$1, $3);
150                 delete $1;
151         }
152         | declarable_identifier '=' notename_tab {
153                 $$ = new Notetab_id(*$1, $3);
154                 delete $1;
155         }
156         ;
157
158 notename_tab:
159         NOTENAMES '{' notename_tab_body '}'     { $$ = $3; }
160         ;
161
162 notename_tab_body:                              {
163                 $$ = new Notename_tab;
164         }
165         | IDENTIFIER                            {
166                 $$ = $1->notename_tab(true);
167         }
168         | notename_tab_body STRING int int                      {
169                 $$->set($3, $4, *$2);
170                 delete $2;
171         }
172         ;
173
174 /*
175         SCORE
176 */
177 score_block: SCORE '{' score_body '}'   { $$ = $3;
178                 if (!$$->paper_)
179                         $$->paper_ = default_paper();
180         }
181         ;
182
183 score_body:             { $$ = new Input_score; }
184         | score_body staff_block        { $$->add($2); }
185         | score_body score_commands_block       {
186                 $$->add(*$2);
187                 delete $2;
188         }
189         | score_body paper_block                { $$->set($2);  }
190         ;
191 /*
192         COMMANDS
193 */
194 score_commands_block:
195         COMMANDS '{' score_commands_body '}' { $$ =$3;}
196         ;
197
198 score_commands_body:                    { $$ = new svec<Input_command*>; }
199         | score_commands_body score_command             {
200                 $$->add($2);
201         }
202         ;
203
204 staff_commands_block: COMMANDS '{' staff_commands_body '}'      {
205                 $$ = $3; }
206         ;
207
208 staff_commands_body:
209         /* empty */                     { $$ = new svec<Input_command*>; }
210         | staff_commands_body staff_command     {
211                 $$->add($2);
212         }
213         ;
214
215 staff_command:
216         skipcommand
217         | KEY pitch_list        {/*UGH*/
218                 $$ = get_key_interpret_command(*$2);
219                 delete $2;
220         }
221         | CLEF clef_id                  {
222                 $$ = get_clef_interpret_command(*$2);
223                 delete $2;
224         }
225         ;
226
227 duration_length:        
228          duration               {
229                 $$ = wholes($1[0], $1[1]);
230         }
231         ;
232
233 skipcommand:
234         SKIP int ':' duration_length            {
235                 $$ = get_skip_command($2, $4);
236         }
237
238 score_command:
239         skipcommand
240         | METER  int int                {
241                 $$ = get_meterchange_command($2, $3);
242         }
243         | PARTIAL duration_length               {
244                 $$ = get_partial_command($2);
245         }
246         | GROUPING int_list             {
247                 $$ = get_grouping_command(*$2);
248                 delete $2;
249         }
250         ;
251
252
253
254 /*
255         PAPER
256 */
257 paper_block:
258         PAPER '{' paper_body '}'        { $$ = $3; }
259         ;
260
261 paper_body:
262         /* empty */                     {
263                 $$ = default_paper();
264         }
265         | paper_body WIDTH dim          { $$->linewidth = $3;}
266         | paper_body OUTPUT STRING      { $$->outfile = *$3;
267                 delete $3;
268         }
269         | paper_body symtables          { $$->set($2); }
270         | paper_body UNITSPACE dim      { $$->whole_width = $3; }
271         | paper_body GEOMETRIC REAL     { $$->geometric_ = $3; }
272         ;
273
274 /*
275         STAFFs
276 */
277 staff_block:
278         STAFF '{' staff_body '}'        { $$ = $3; }
279         ;
280
281
282
283 staff_init:
284         IDENTIFIER              { $$ = $1->staff(true); }
285         | RHYTHMIC              {
286                 $$ = new Input_staff("rhythmic");
287         }
288         | MELODIC               {
289                 $$ = new Input_staff( "melodic");
290         }
291         ;
292
293 staff_body:
294         staff_init
295         | staff_body music      {
296                 $$->add($2);
297         }
298         | staff_body staff_commands_block {
299                 $$->add(*$2);
300                 delete $2;
301         }
302         ;
303
304 /*
305         MUSIC
306 */
307 music:
308         music_voice     { $$ = $1; }
309         | music_chord   { $$ = $1; }
310         ;
311
312 music_voice:  MUSIC '{' music_voice_body '}'    { $$ = $3; }
313         ;
314
315 music_voice_body:                       {
316                 $$ = new Music_voice;
317         }
318         | music_voice_body IDENTIFIER {
319                 $$->concatenate($2->mvoice());
320         }
321         | music_voice_body full_element {
322                 $$->add_elt($2);
323         }
324         | music_voice_body voice_command {
325         }
326         | music_voice_body music        {
327                 $$->add($2);
328         }
329         ;
330
331
332 music_chord:  '{' music_chord_body '}'  { $$ = $2; }
333         ;
334
335 music_chord_body:               {
336                 $$ = new Music_general_chord;
337         }
338         | music_chord_body IDENTIFIER {
339                 $$->concatenate($2->mchord());
340         }
341         | music_chord_body music {
342                 $$ -> add($2);
343         }
344         | music_chord_body full_element {
345                 $$ ->add_elt($2);
346         }
347         ;
348
349
350
351 /*
352         VOICE ELEMENTS
353 */
354 full_element:   pre_requests voice_elt post_requests {
355                 add_requests($2, pre_reqs);
356                 add_requests($2, post_reqs);
357                 $$ = $2;
358         }
359         ;
360
361 post_requests:
362         {
363                 assert(post_reqs.empty());
364         }
365         | post_requests post_request {
366                 post_reqs.add($2);
367         }
368         ;
369
370 post_request:
371         CLOSE_REQUEST_PARENS            { $$ = get_request($1); }
372         ;
373
374 pre_requests:
375         | pre_requests pre_request {
376                 pre_reqs.add($2);
377         }
378         ;
379
380 pre_request: 
381         OPEN_REQUEST_PARENS             { $$ = get_request($1); }
382         ;
383
384
385
386 voice_command:
387         DURATIONCOMMAND '{' duration '}'        {
388                 set_default_duration($3);
389         }
390         | OCTAVECOMMAND '{' pitchmod '}'        {
391                 set_default_octave(*$3);
392                 delete $3;
393         }
394         ;
395
396 duration:               {
397                 get_default_duration($$);
398         }
399         | int           {
400                 get_default_duration($$);
401                 $$[0] = $1;
402         }
403         | int DOTS      {
404                 $$[0] = $1;
405                 $$[1] = $2;
406         }
407         ;
408
409 pitchmod:               { $$ = new String; }
410         |PITCHMOD       
411         ;
412
413 voice_elt:      
414         pitchmod NOTENAME duration                      {
415                 $$ = get_note_element(*$1, $2, $3);
416                 delete $1;
417         }
418         | RESTNAME duration             {
419                 $$ = get_rest_element(*$1, $2);
420                 delete $1;
421
422         }
423         ;
424
425 /*
426         UTILITIES
427 */
428 pitch_list:                     {
429                 $$ = new svec<int>;
430         }
431         | pitch_list NOTENAME   {
432                 $$->add($2[0]);
433                 $$->add($2[1]);         
434         }
435         ;
436
437 int:
438         REAL                    {
439                 $$ = int($1);
440                 if (ABS($1-Real(int($$))) > 1e-8)
441                         error("expecting integer number");
442         }
443         | INT
444         ;
445
446 int_list:
447         /* */           {
448                 $$ = new svec<int>;
449         }
450         | int_list int          {
451                 $$->add($2);
452         }
453         ;
454
455 dim:
456         REAL unit       { $$ = convert_dimen($1,$2); }
457         ;
458
459
460 unit:   CM              { $$ = "cm"; }
461         |IN             { $$ = "in"; }
462         |MM             { $$ = "mm"; }
463         |PT             { $$ = "pt"; }
464         ;
465         
466 clef_id:
467         VIOLIN          { $$ = new String("violin"); }
468         | BASS          { $$ = new String("bass"); }
469         ;
470 /*
471         symbol tables
472 */
473 symtables:
474         SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
475         ;
476
477 symtables_body:
478                         {
479                 $$ = new Lookup;
480         }
481         | IDENTIFIER            {
482                 $$ = new Lookup(*$1->lookup(true));
483         }
484         | symtables_body TEXID STRING           {
485                 $$->texsetting = *$3;
486                 delete $3;
487         }
488         | symtables_body STRING '=' symtable            {
489                 $$->add(*$2, $4);
490                 delete $2;
491         }
492         ;
493
494 symtable:
495         TABLE '{' symtable_body '}' { $$ = $3; }
496         ;
497
498 symtable_body:
499                                 { $$ = new Symtable; }
500         | symtable_body STRING  symboldef {
501                 $$->add(*$2, *$3);
502                 delete $2;
503                 delete $3;
504         }
505         ;
506
507 symboldef:
508         STRING  box             {
509                 $$ = new Symbol(*$1, *$2);
510                 delete $1;
511                 delete $2;
512         }
513         | STRING {
514                 Box b;
515                 $$ = new Symbol(*$1, b);
516                 delete $1;
517         }
518         ;
519
520 box:
521         dinterval dinterval     {
522                 $$ = new Box(*$1, *$2);
523                 delete $1;
524                 delete $2;
525         }
526         ;
527
528 dinterval: dim  dim             {
529                 $$ = new Interval($1, $2);      
530         }
531         ;
532
533 %%
534
535 void
536 parse_file(String s)
537 {
538    *mlog << "Parsing ... ";
539
540 #ifdef YYDEBUG
541    yydebug = !monitor.silence("Parser") && check_debug;
542 #endif
543
544    set_lexer();
545    lexer->new_input("symbol.ini");
546    yyparse();
547    lexer->new_input(s);
548    yyparse();
549    kill_lexer();
550 }
551
552 Paperdef*
553 default_paper()
554 {
555         return new Paperdef(lexer->lookup_identifier("default_table")->lookup(true));
556 }