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