]> git.donarmstrong.com Git - lilypond.git/blob - src/parser.y
release: 0.0.10
[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 "scommands.hh"
11 #include "debug.hh"
12 #include "parseconstruct.hh"
13 #include "dimen.hh"
14 #include "identifier.hh"
15
16 #ifndef NDEBUG
17 #define YYDEBUG 1
18 #endif
19
20 svec<Request*> pre_reqs, post_reqs;
21 %}
22
23
24 %union {    
25     Real real;
26     Command *command;
27     Identifier *id;    
28     Score_commands *scommands;
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     int i;
38     char c;
39     svec<String> * strvec;
40 }
41
42 %token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
43 %token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
44 %token MELODICSTAFF GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
45 %token KEY CLEF VIOLIN BASS
46
47 %token <id>  IDENTIFIER
48 %token <string> NEWIDENTIFIER 
49 %token <string> PITCH DURATION RESTNAME
50 %token <real> REAL
51 %token <string> STRING
52 %token <i> OPEN_REQUEST_PARENS CLOSE_REQUEST_PARENS
53
54
55 %type <consstr> unit
56
57 %type <id> declaration 
58 %type <paper> paper_block paper_body
59 %type <real> dim
60 %type <voice> voice_block voice_body voice_elts voice_elts_dollar
61 %type <el> voice_elt
62 %type <command> score_command
63 %type <score> score_block score_body
64 %type <staff> staff_block  rhythmstaff_block rhythmstaff_body
65 %type <staff> melodicstaff_block melodicstaff_body staffdecl
66 %type <i> int
67 %type <scommands> score_commands_block score_commands_body
68 %type <request> post_request pre_request
69 %type <strvec> pitch_list
70 %type <string> clef_id
71 %%
72
73 mudela: /* empty */
74         | mudela score_block { 
75                 add_score($2);
76         }
77         | mudela add_declaration {      }
78         ;
79
80 add_declaration: declaration    {
81                 add_identifier($1);
82         }
83         ;
84
85 declaration:
86         NEWIDENTIFIER '=' staff_block  {
87                 $$ = new Staff_id(*$1, $3);
88                 delete $1; // this sux
89         }
90         | NEWIDENTIFIER '=' voice_block {
91                 $$ = new Voice_id(*$1, $3);
92                 delete $1;
93         }
94         ;
95
96
97 score_block: SCORE '{' score_body '}'   { $$ = $3; }
98         ;
99
100 score_body:             { $$ = new Score; } 
101         | score_body staff_block        { $$->add($2); }
102         | score_body score_commands_block       { $$->set($2); }
103         | score_body paper_block                { $$->set($2);  }
104         ;
105 score_commands_block:
106         COMMANDS '{' score_commands_body '}' { $$ =$3;}
107         ;
108
109 score_commands_body:                    { $$ = new Score_commands; }
110         | score_commands_body score_command             {
111                 $$->parser_add($2);
112         }
113         ;
114
115 paper_block:
116         PAPER '{' paper_body '}'        { $$ = $3; }
117         ;
118
119 paper_body:
120         /* empty */                     { $$ = new Paperdef; }
121         | paper_body WIDTH dim          { $$->linewidth = $3;}
122         | paper_body OUTPUT STRING      { $$->outfile = *$3;
123                 delete $3;
124         }
125         | paper_body UNITSPACE dim      { $$->whole_width = $3; }
126         | paper_body GEOMETRIC REAL     { $$->geometric_ = $3; }
127         ;
128
129 dim:
130         REAL unit       { $$ = convert_dimen($1,$2); }
131         ;
132
133
134 unit:   CM              { $$ = "cm"; }
135         |IN             { $$ = "in"; }
136         |MM             { $$ = "mm"; }
137         |PT             { $$ = "pt"; }
138         ;
139         
140 /*
141         staff
142 */
143 staff_block:
144         staffdecl
145         | rhythmstaff_block
146         | melodicstaff_block
147         ;
148
149 staffdecl: STAFF '{' IDENTIFIER '}' { $$ = $3->staff()->clone(); }
150         ;
151
152 rhythmstaff_block:
153         RHYTHMSTAFF '{' rhythmstaff_body '}'    { $$ = $3; }
154         ;
155
156 rhythmstaff_body:
157         /* empty */                     { $$ = get_new_rhythmstaff(); }
158         | rhythmstaff_body voice_block  { $$->add_voice($2); }  
159         ;
160
161 melodicstaff_block:
162         MELODICSTAFF '{' melodicstaff_body '}'  { $$ = $3; }
163         ;
164
165 melodicstaff_body:
166         /* empty */                     { $$ = get_new_melodicstaff(); }
167         | melodicstaff_body voice_block         { $$->add_voice($2); }  
168         ;
169
170 /*
171         voice
172 */
173 voice_block:
174         VOICE '{' voice_body '}'        { $$ = $3; }
175         ;
176
177
178 voice_body:
179         IDENTIFIER              { $$ = new Voice(*$1->voice()); }
180         | voice_elts_dollar     { $$ = $1; }
181         | voice_body START_T REAL { $$->start = $3; }
182         ;
183
184
185         
186
187 voice_elts_dollar:
188         '$' voice_elts '$'  { $$ = $2; }
189         ;
190
191 voice_elts:
192         /* empty */             {
193             $$ = new Voice;
194         }
195         | voice_elts pre_requests voice_elt post_requests {
196                 add_requests($3, pre_reqs);
197                 add_requests($3, post_reqs);
198                 $$->add($3);
199         }
200
201         | voice_elts voice_command { }
202         ;
203
204 post_requests:
205         {
206                 assert(post_reqs.empty());
207         }
208         | post_requests post_request {
209                 post_reqs.add($2);
210         }
211         ;
212
213 post_request:
214         CLOSE_REQUEST_PARENS            { $$ = get_request($1); }
215         ;
216
217 pre_requests:    
218         | pre_requests pre_request {
219                 pre_reqs.add($2);
220         }
221         ;
222
223 pre_request: 
224         OPEN_REQUEST_PARENS             { $$ = get_request($1); }
225         ;
226 /*
227 */
228 voice_command:
229         DURATIONCOMMAND DURATION        {
230                 set_default_duration(*$2);
231                 delete $2;
232         }
233         | OCTAVECOMMAND PITCH   {
234                 set_default_pitch(*$2);
235                 delete $2;
236         }
237         ;
238
239 voice_elt:
240         PITCH DURATION                  {
241                 $$ = get_note_element(*$1, *$2);
242                 delete $1;
243                 delete $2;
244         }
245         |  RESTNAME DURATION            {
246                 $$ = get_rest_element(*$1, *$2);
247                 delete $1;
248                 delete $2;
249         }
250         | PITCH                         { $$ = get_note_element(*$1, "");
251                 delete $1;
252         }
253         |  RESTNAME             { $$ = get_rest_element(*$1, "");
254                 delete $1;
255         }
256         ;
257
258 pitch_list:                     {
259                 $$ = new svec<String>;
260         }
261         | pitch_list PITCH      {
262                 $$->add(*$2);
263                 delete $2;              
264         }
265
266 score_command:
267         SKIP int ':' REAL               {
268                 $$ = get_skip_command($2, $4);
269         }
270         | METER  int int                {
271                 $$ = get_meterchange_command($2, $3);
272         }
273         | KEY '$' pitch_list '$'        {/*UGH*/
274                 $$ = get_key_interpret_command(*$3);
275                 delete $3;
276         }
277         | CLEF clef_id                  {
278                 $$ = get_clef_interpret_command(*$2);
279                 delete $2;
280         }
281 /*      | PARTIALMEASURE REAL           {
282                 $$ = get_partial_command($2);
283         }*/
284         ;
285         
286 clef_id:
287         VIOLIN          { $$ = new String("violin"); }
288         | BASS          { $$ = new String("bass"); }
289         ;
290 int:
291         REAL                    {
292                 $$ = int($1);
293                 if (ABS($1-Real(int($$))) > 1e-8)
294                         yyerror("expecting integer number");
295                 
296         }
297         ;
298
299 %%
300
301 void
302 parse_file(String s)
303 {
304    *mlog << "Parsing ... ";
305 #ifdef YYDEBUG
306    yydebug = !monitor.silence("Parser");
307 #endif
308    new_input(s);
309    yyparse();
310    delete_identifiers();
311    kill_lexer();
312    *mlog << "\n";
313 }