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