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