]> git.donarmstrong.com Git - lilypond.git/blob - src/parser.y
release: 0.0.13
[lilypond.git] / src / parser.y
1 %{ // -*-Fundamental-*-
2 #include <iostream.h>
3
4 #include "lexer.hh"
5 #include "paper.hh"
6 #include "staff.hh"
7 #include "score.hh"
8 #include "main.hh"
9 #include "keyword.hh"
10 #include "getcommand.hh"
11 #include "debug.hh"
12 #include "parseconstruct.hh"
13 #include "dimen.hh"
14 #include "identifier.hh"
15 #include "inputmusic.hh"
16
17 #ifndef NDEBUG
18 #define YYDEBUG 1
19 #endif
20
21 svec<Request*> pre_reqs, post_reqs;
22 %}
23
24
25 %union {    
26     Real real;
27     Command *command;
28     Identifier *id;    
29     Voice *voice;    
30     Voice_element *el;  
31     Staff *staff;    
32     String *string;
33     Score *score;
34     const char *consstr;
35     Paperdef *paper;
36     Request* request;
37     Horizontal_music *horizontal;
38     Vertical_music *vertical;
39     Music_general_chord *chord;
40     Music_voice *mvoice; 
41     int i;
42     char c;
43
44     svec<String> * strvec;
45     svec<Command*> *commandvec;
46     Voice_list *voicelist;
47 }
48
49 %token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
50 %token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
51 %token MELODICSTAFF GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
52 %token KEY CLEF VIOLIN BASS MULTI TABLE CHORD VOICES
53 %token PARTIAL
54
55 %token <id>  IDENTIFIER
56 %token <string> NEWIDENTIFIER 
57 %token <string> PITCH DURATION RESTNAME
58 %token <real> REAL
59 %token <string> STRING
60 %token <i> OPEN_REQUEST_PARENS CLOSE_REQUEST_PARENS
61
62
63 %type <consstr> unit
64
65 %type <id> declaration 
66 %type <paper> paper_block paper_body
67 %type <real> dim
68
69 %type <el> voice_elt full_element
70 %type <command> score_command staff_command skipcommand
71 %type <score> score_block score_body
72 %type <staff> staff_block  rhythmstaff_block rhythmstaff_body
73 %type <staff> melodicstaff_block melodicstaff_body staffdecl
74 %type <i> int
75 %type <commandvec> score_commands_block score_commands_body
76 %type <commandvec> staff_commands_block staff_commands_body
77 %type <request> post_request pre_request
78 %type <strvec> pitch_list
79 %type <string> clef_id
80 %type <vertical> vertical_music  
81 %type <chord> music_chord music_chord_body
82 %type <horizontal>  horizontal_music
83 %type <mvoice>  music_voice_body music_voice
84 %type <voicelist> voices
85
86 %%
87
88 mudela: /* empty */
89         | mudela score_block { 
90                 add_score($2);
91         }
92         | mudela add_declaration {      }
93         ;
94 /*
95         DECLARATIONS
96 */
97 add_declaration: declaration    {
98                 add_identifier($1);
99         }
100         ;
101
102 declaration:
103         NEWIDENTIFIER '=' staff_block  {
104                 $$ = new Staff_id(*$1, $3);
105                 delete $1; // this sux
106         }
107         | NEWIDENTIFIER '=' voices {
108                 $$ = new Voices_id(*$1, $3);
109                 delete $1;
110         }
111         ;
112
113
114 /*
115         SCORE
116 */
117 score_block: SCORE '{' score_body '}'   { $$ = $3; }
118         ;
119
120 score_body:             { $$ = new Score; } 
121         | score_body staff_block        { $$->add($2); }
122         | score_body score_commands_block       {
123                 $$->add(*$2);
124                 delete $2;
125         }
126         | score_body paper_block                { $$->set($2);  }
127         ;
128 /*
129         COMMANDS
130 */
131 score_commands_block:
132         COMMANDS '{' score_commands_body '}' { $$ =$3;}
133         ;
134
135 score_commands_body:                    { $$ = new svec<Command*>; }
136         | score_commands_body score_command             {
137                 $$->add($2);
138         }
139         ;
140
141 staff_commands_block: COMMANDS '{' staff_commands_body '}'      {
142                 $$ = $3; }
143         ;
144
145 staff_commands_body:
146         /* empty */                     { $$ = new svec<Command*>; }
147         | staff_commands_body staff_command     {
148                 $$->add($2);
149         }
150         ;
151
152 staff_command:
153         skipcommand
154         | KEY '$' pitch_list '$'        {/*UGH*/
155                 $$ = get_key_interpret_command(*$3);
156                 delete $3;
157         }
158         | CLEF clef_id                  {
159                 $$ = get_clef_interpret_command(*$2);
160                 delete $2;
161         }
162         ;
163
164 skipcommand:
165         SKIP int ':' REAL               {
166                 $$ = get_skip_command($2, $4);
167         }
168
169 score_command:
170         skipcommand
171         | METER  int int                {
172                 $$ = get_meterchange_command($2, $3);
173         }
174         | PARTIAL REAL                  {
175                 $$ = get_partial_command($2);
176         }
177         ;
178         
179
180 /*
181         PAPER
182 */
183 paper_block:
184         PAPER '{' paper_body '}'        { $$ = $3; }
185         ;
186
187 paper_body:
188         /* empty */                     { $$ = new Paperdef; }
189         | paper_body WIDTH dim          { $$->linewidth = $3;}
190         | paper_body OUTPUT STRING      { $$->outfile = *$3;
191                 delete $3;
192         }
193         | paper_body UNITSPACE dim      { $$->whole_width = $3; }
194         | paper_body GEOMETRIC REAL     { $$->geometric_ = $3; }
195         ;
196 /*
197         STAFFs
198 */
199 staff_block:
200         staffdecl
201         | rhythmstaff_block
202         | melodicstaff_block
203         ;
204
205 staffdecl: STAFF '{' IDENTIFIER '}' { $$ = $3->staff()->clone(); }
206         ;
207
208 rhythmstaff_block:
209         RHYTHMSTAFF '{' rhythmstaff_body '}'    { $$ = $3; }
210         ;
211
212 rhythmstaff_body:
213         /* empty */                     { $$ = get_new_rhythmstaff(); }
214         | rhythmstaff_body voices       { $$->add(*$2);
215                 delete $2;
216         }
217         | rhythmstaff_body staff_commands_block {
218                 $$->add(*$2);
219                 delete $2;
220         }
221         ;
222
223 melodicstaff_block:
224         MELODICSTAFF '{' melodicstaff_body '}'  { $$ = $3; }
225         ;
226
227 melodicstaff_body:
228         /* empty */                     { $$ = get_new_melodicstaff(); }
229         | melodicstaff_body voices      {
230                 $$->add(*$2);
231                 delete $2;
232         }       
233         | melodicstaff_body staff_commands_block {
234                 $$->input_commands_.add(get_reset_command());
235                 $$->add(*$2);
236                 delete $2;
237         }       
238         ;
239
240 voices:
241         '$' music_voice_body '$'  {
242                 $$ = new Voice_list($2->convert());
243         }
244         | VOICES '{' IDENTIFIER '}'     {
245                 $$ = new Voice_list(*$3->voices());
246         }
247         ;
248
249
250 horizontal_music:
251         music_voice     { $$ = $1; }
252         ;
253
254 vertical_music:
255         music_chord     { $$ = $1; }
256         ;
257
258 music_voice: VOICE '{' music_voice_body '}'     { $$ = $3; }
259         ;
260
261 music_voice_body:                       {
262                 $$ = new Music_voice;
263         }
264         | music_voice_body full_element {
265                 $$->add($2);
266         }
267         | music_voice_body voice_command {
268         }
269         | music_voice_body vertical_music       {
270                 $$->add($2);
271         }
272         ;
273
274
275 music_chord: CHORD '{' music_chord_body '}'     { $$ = $3; }
276         ;
277
278 music_chord_body:               {
279                 $$ = new Music_general_chord;
280         }
281         | music_chord_body horizontal_music {
282                 $$ -> add($2);
283         }
284         ;
285
286
287
288 /*
289         VOICE ELEMENTS
290 */
291 full_element:   pre_requests voice_elt post_requests {
292                 add_requests($2, pre_reqs);
293                 add_requests($2, post_reqs);
294                 $$ = $2;
295         }
296         ;
297
298 post_requests:
299         {
300                 assert(post_reqs.empty());
301         }
302         | post_requests post_request {
303                 post_reqs.add($2);
304         }
305         ;
306
307 post_request:
308         CLOSE_REQUEST_PARENS            { $$ = get_request($1); }
309         ;
310
311 pre_requests:    
312         | pre_requests pre_request {
313                 pre_reqs.add($2);
314         }
315         ;
316
317 pre_request: 
318         OPEN_REQUEST_PARENS             { $$ = get_request($1); }
319         ;
320
321 voice_command:
322         DURATIONCOMMAND '{' DURATION '}'        {
323                 set_default_duration(*$3);
324                 delete $3;
325         }
326         | OCTAVECOMMAND '{' PITCH '}'   {
327                 set_default_pitch(*$3);
328                 delete $3;
329         }
330         ;
331
332 voice_elt:
333         PITCH DURATION                  {
334                 $$ = get_note_element(*$1, *$2);
335                 delete $1;
336                 delete $2;
337         }
338         |  RESTNAME DURATION            {
339                 $$ = get_rest_element(*$1, *$2);
340                 delete $1;
341                 delete $2;
342         }
343         | PITCH                         { $$ = get_note_element(*$1, "");
344                 delete $1;
345         }
346         |  RESTNAME             { $$ = get_rest_element(*$1, "");
347                 delete $1;
348         }
349         ;
350 /*
351         UTILITIES
352 */
353 pitch_list:                     {
354                 $$ = new svec<String>;
355         }
356         | pitch_list PITCH      {
357                 $$->add(*$2);
358                 delete $2;              
359         }
360
361 int:
362         REAL                    {
363                 $$ = int($1);
364                 if (ABS($1-Real(int($$))) > 1e-8)
365                         yyerror("expecting integer number");
366                 
367         }
368         ;
369
370
371 dim:
372         REAL unit       { $$ = convert_dimen($1,$2); }
373         ;
374
375
376 unit:   CM              { $$ = "cm"; }
377         |IN             { $$ = "in"; }
378         |MM             { $$ = "mm"; }
379         |PT             { $$ = "pt"; }
380         ;
381         
382 clef_id:
383         VIOLIN          { $$ = new String("violin"); }
384         | BASS          { $$ = new String("bass"); }
385         ;
386 %%
387
388 void
389 parse_file(String s)
390 {
391    *mlog << "Parsing ... ";
392
393 #ifdef YYDEBUG
394    yydebug = !monitor.silence("Parser") & check_debug;
395 #endif
396
397    new_input(s);
398    yyparse();
399    delete_identifiers();
400    kill_lexer();
401    *mlog << "\n";
402 }
403