]> git.donarmstrong.com Git - lilypond.git/blob - lily/my-lily-parser.cc
patch::: 1.1.10.jcn1: koorden
[lilypond.git] / lily / my-lily-parser.cc
1 /*
2   my-lily-parser.cc -- implement My_lily_parser
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "my-lily-parser.hh"
10 #include "my-lily-lexer.hh"
11 #include "debug.hh"
12 #include "main.hh"
13 #include "music-list.hh"
14 #include "musical-request.hh"
15 #include "command-request.hh"
16 #include "parser.hh"
17 #include "scope.hh"
18 #include "file-results.hh"
19 #include "midi-def.hh"
20 #include "paper-def.hh"
21 #include "identifier.hh"
22
23 My_lily_parser::My_lily_parser (Sources * source_l)
24 {
25   first_b_ = true;
26   source_l_ = source_l;
27   lexer_p_ = 0;
28   abbrev_beam_type_i_ = 0;
29   default_duration_.durlog_i_ = 2;
30   default_abbrev_i_ = 0;
31   error_level_i_ = 0;
32   extender_req = 0;
33   fatal_error_i_ = 0;
34   default_header_p_ =0;
35 }
36
37 My_lily_parser::~My_lily_parser()
38 {
39   delete lexer_p_;
40   delete default_header_p_;
41 }
42
43
44
45 void
46 My_lily_parser::set_version_check (bool ig)
47 {
48   ignore_version_b_ = ig;
49 }
50
51 void
52 My_lily_parser::parse_file (String init, String s)
53 {
54   lexer_p_ = new My_lily_lexer;
55   init_str_ = init;
56   lexer_p_->main_input_str_ = s;
57
58   *mlog << _ ("Parsing...");
59
60   init_parse_b_ = false;
61   set_yydebug (!monitor->silent_b ("Parser") && check_debug);
62   lexer_p_->new_input (init, source_l_);
63   do_yyparse ();
64
65   if (!define_spot_array_.empty())
66     {
67       warning (_ ("braces don't match"));
68       error_level_i_ = 1;
69     }
70
71   inclusion_global_array = lexer_p_->filename_str_arr_;
72 }
73
74 void
75 My_lily_parser::remember_spot()
76 {
77   define_spot_array_.push (here_input());
78 }
79
80 char const *
81 My_lily_parser::here_ch_C() const
82 {
83   return lexer_p_->here_ch_C();
84 }
85
86 void
87 My_lily_parser::parser_error (String s)
88 {
89   here_input().error (s);
90   if (fatal_error_i_)
91     exit (fatal_error_i_);
92   error_level_i_ = 1;
93   exit_status_i_ = 1;
94 }
95
96 void
97 My_lily_parser::set_abbrev_beam (int type_i)
98 {
99   abbrev_beam_type_i_ = type_i;
100 }
101
102
103 void
104 My_lily_parser::set_last_duration (Duration const *d)
105 {
106   default_duration_ = *d;
107
108   /* 
109      forget plet part,
110      but keep sticky plet factor within plet brackets
111     */  
112   default_duration_.plet_ = plet_;
113 }
114
115
116 Simultaneous_music*
117 My_lily_parser::get_word_element (String s, Duration * duration_p)
118 {
119   Simultaneous_music* velt_p = new Request_chord;
120
121   Lyric_req* lreq_p = new Lyric_req;
122   lreq_p ->text_str_ = s;
123   lreq_p->duration_ = *duration_p;
124   lreq_p->set_spot (here_input());
125
126   velt_p->add_music (lreq_p);
127
128   delete  duration_p;
129   return velt_p;
130 }
131
132
133 Simultaneous_music *
134 My_lily_parser::get_rest_element (String s,  Duration * duration_p)
135 {
136   Simultaneous_music* velt_p = new Request_chord;
137   velt_p->set_spot (here_input());
138
139   if (s=="s")
140     { /* Space */
141       Skip_req * skip_p = new Skip_req;
142       skip_p->duration_ = *duration_p;
143
144       skip_p->set_spot (here_input());
145       velt_p->add_music (skip_p);
146     }
147   else
148     {
149       Rest_req * rest_req_p = new Rest_req;
150       rest_req_p->duration_ = *duration_p;
151       rest_req_p->set_spot (here_input());
152
153       velt_p->add_music (rest_req_p);
154     }
155
156   delete duration_p;
157   return velt_p;
158 }
159
160 Simultaneous_music *
161 My_lily_parser::get_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Duration d)
162 {
163   Simultaneous_music*v = new Request_chord;
164   v->set_spot (here_input ());
165
166   Note_req* n = new Note_req;
167   n->pitch_ = tonic;
168   n->duration_ = d;
169   v->add_music (n);
170
171   for (int i = 0; i < add_arr_p->size (); i++)
172     {
173       Musical_pitch p = tonic;
174       p.transpose ((*add_arr_p)[i]);
175       (*add_arr_p)[i] = p;
176     }
177   add_arr_p->sort (Musical_pitch::compare);
178   for (int i = 0; i < sub_arr_p->size (); i++)
179     {
180       Musical_pitch p = tonic;
181       p.transpose ((*sub_arr_p)[i]);
182       (*sub_arr_p)[i] = p;
183     }
184   sub_arr_p->sort (Musical_pitch::compare);
185
186   Musical_pitch third;
187   third.notename_i_ = 2;
188
189   Musical_pitch mthird;
190   mthird.notename_i_ = 2;
191   mthird.accidental_i_ = -1;
192
193   Musical_pitch missing;
194   missing = tonic;
195   missing.transpose (third);
196
197   Musical_pitch p;
198   p = tonic;
199   p.transpose (third);
200   p.transpose (mthird);
201
202   /*
203    must have minimum at 5 (3 is added automatically as missing)
204    */
205   if (!add_arr_p->size () 
206     || ((add_arr_p->size () == 1) && 
207          ((add_arr_p->top ().notename_i_ != p.notename_i_)
208            || (add_arr_p->top () < p))))
209     add_arr_p->push (p);
210
211   Array<Musical_pitch> triads;
212   triads.push (third);   // c e 
213   triads.push (mthird);  // d f 
214   triads.push (mthird);  // e g 
215   triads.push (third);   // f a 
216   triads.push (third);   // g b 
217   triads.push (mthird);  // a c 
218   triads.push (mthird);  // b d 
219
220   /*
221    add missing triads
222    */
223   for (int i = 0; i < add_arr_p->size (); i++)
224     {
225       Musical_pitch p = (*add_arr_p)[i];
226       if ((p > missing) && (p.notename_i_ != missing.notename_i_))
227         while ((p > missing) && (p.notename_i_ != missing.notename_i_))
228           {
229             add_arr_p->insert (missing, i++);
230             missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 8) % 8]);
231           }
232         else
233           i++;
234     }
235
236   /*
237    add all that aren't subtracted
238    */
239   for (int i = 0; i < add_arr_p->size (); i++)
240     {
241       Musical_pitch p = (*add_arr_p)[i];
242       Note_req* n = new Note_req;
243       n->pitch_ = p;
244       n->duration_ = d;
245       for (int j = 0; j < sub_arr_p->size (); j++)
246         {
247           if (p == (*sub_arr_p)[j])
248             {
249               delete n;
250               n = 0;
251               break;
252             }
253         }
254       if (n)
255         v->add_music (n);
256     }
257
258   v->set_spot (here_input ());
259   return v;
260 }
261
262 Simultaneous_music *
263 My_lily_parser::get_note_element (Note_req *rq, Duration * duration_p)
264 {
265   Simultaneous_music*v = new Request_chord;
266   v->set_spot (here_input ());
267
268   v->add_music (rq);
269
270   // too bad parser reads (default) duration via member access,
271   // this hack will do for now..
272   if (abbrev_beam_type_i_)
273     {
274       assert (!duration_p->plet_b ());
275       duration_p->set_plet (1, 2);
276     }
277   rq->duration_ = *duration_p;
278   rq->set_spot (here_input ());
279   delete duration_p ;
280   return v;
281 }
282
283
284 /*
285   UGH.
286  */
287 Array<Request*>*
288 My_lily_parser::get_parens_request (int t)
289 {
290   Array<Request*>& reqs = *new Array<Request*>;
291   switch (t)
292     {
293     case '~':
294       reqs.push (new Tie_req);
295       break;
296     case BEAMPLET:
297     case MAEBTELP:
298       {
299         Plet_req* p = new Plet_req;
300         p->plet_i_ = plet_.type_i_;
301         reqs.push (p);
302       }
303       /* fall through */
304     case '[':
305     case ']':
306       {
307         if (!abbrev_beam_type_i_)
308           {
309             reqs.push (new Beam_req);
310           }
311         else
312           {
313             Abbreviation_beam_req* a = new Abbreviation_beam_req;
314             a->type_i_ = abbrev_beam_type_i_;
315             if (t==']')
316               abbrev_beam_type_i_ = 0;
317             reqs.push (a);
318           }
319       }
320       break;
321
322     case '>':
323     case '!':
324     case '<':
325       reqs.push (new Span_dynamic_req);
326       break;
327
328     case PLET:  
329     case TELP:
330       {
331         Plet_req* p = new Plet_req;
332         p->plet_i_ = plet_.type_i_;
333         reqs.push (p);
334       }
335       break;
336     case ')':
337     case '(':
338       {
339         reqs.push (new Slur_req);
340       }
341       break;
342     default:
343       assert (false);
344       break;
345     }
346
347   switch (t)
348     {
349     case BEAMPLET:
350       dynamic_cast<Span_req*> (reqs.top ())->spantype = Span_req::START;
351       /* fall through */
352     case '<':
353     case '>':
354     case '(':
355     case '[':
356     case PLET:
357       dynamic_cast<Span_req*> (reqs.top ())->spantype = Span_req::START;
358       break;
359     case MAEBTELP:
360       dynamic_cast<Span_req*> (reqs.top ())->spantype = Span_req::STOP;
361       /* fall through */
362     case '!':
363     case ')':
364     case ']':
365       dynamic_cast<Span_req*> (reqs[0])->spantype = Span_req::STOP;
366       break;
367
368     default:
369       break;
370     }
371
372   for (int i = 0; i < reqs.size (); i++)
373     if (dynamic_cast<Span_dynamic_req*> (reqs[i]))
374       {
375         Span_dynamic_req* s_l= dynamic_cast<Span_dynamic_req*> (reqs[i]);
376         s_l->dynamic_dir_ = (t == '<') ? UP:DOWN;
377       }
378
379   // ugh? don't we do this in the parser too?
380   reqs[0]->set_spot (here_input());
381   return &reqs;
382 }
383
384 void
385 My_lily_parser::add_requests (Simultaneous_music*v)
386 {
387   for (int i = 0; i < pre_reqs.size(); i++)
388     {
389       v->add_music (pre_reqs[i]);
390     }
391   pre_reqs.clear();
392   for (int i = 0; i <post_reqs.size(); i++)
393     {
394       v->add_music (post_reqs[i]);
395     }
396
397   post_reqs.clear();
398 }
399
400 Input
401 My_lily_parser::pop_spot()
402 {
403   return define_spot_array_.pop();
404 }
405
406 Input
407 My_lily_parser::here_input() const
408 {
409   Source_file * f_l= lexer_p_->source_file_l();
410   return Input (f_l, here_ch_C());
411 }
412
413 void
414 My_lily_parser::add_notename (String s, Musical_pitch p)
415 {
416   lexer_p_->add_notename (s, p);
417
418 }
419
420 Paper_def*
421 My_lily_parser::default_paper_p ()
422 {
423   Identifier *id = lexer_p_->lookup_identifier ("$defaultpaper");
424   return id ? id->access_content_Paper_def (true) : new Paper_def ;
425 }
426
427 Midi_def*
428 My_lily_parser::default_midi_p ()
429 {
430   Identifier *id = lexer_p_->lookup_identifier ("$defaultmidi");
431   return id ? id->access_content_Midi_def (true) : new Midi_def ;
432 }
433