]> git.donarmstrong.com Git - lilypond.git/blob - lily/my-lily-parser.cc
release: 0.1.62
[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@stack.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 "header.hh"
18 #include "file-results.hh"
19
20 My_lily_parser::My_lily_parser (Sources * source_l)
21 {
22   first_b_ = true;
23   source_l_ = source_l;
24   lexer_p_ = 0;
25   abbrev_beam_type_i_ = 0;
26   default_duration_.durlog_i_ = 2;
27   default_octave_i_ = 0;
28   textstyle_str_="roman";               // in lexer?
29   error_level_i_ = 0;
30   last_duration_mode_b_ = true;
31   fatal_error_i_ = 0;
32   default_header_p_ =0;
33
34   relative_octave_mode_b_ = false;
35
36   last_melodic_ = new Melodic_req;
37   last_melodic_->octave_i_ = 0; // -1; // huh?
38   last_melodic_->notename_i_ = 0;
39   last_melodic_->accidental_i_ = 0;
40 }
41
42 My_lily_parser::~My_lily_parser()
43 {
44   delete lexer_p_;
45   delete default_header_p_;
46 }
47
48
49 void
50 My_lily_parser::clear_notenames()
51 {
52   lexer_p_->clear_notenames();
53 }
54
55 void
56 My_lily_parser::set_version_check (bool ig)
57 {
58   ignore_version_b_ = ig;
59 }
60
61 void
62 My_lily_parser::parse_file (String init, String s)
63 {
64   lexer_p_ = new My_lily_lexer;
65   init_str_ = init;
66   lexer_p_->main_input_str_ = s;
67
68   *mlog << _("Parsing ... ");
69
70   init_parse_b_ = false;
71   set_yydebug (!monitor->silent_b ("Parser") && check_debug);
72   lexer_p_->new_input (init, source_l_);
73   do_yyparse ();
74
75
76   if (!define_spot_array_.empty())
77     {
78       warning (_("Braces don't match."));
79       error_level_i_ = 1;
80     }
81
82   inclusion_global_array = lexer_p_->filename_str_arr_;
83 }
84
85 void
86 My_lily_parser::remember_spot()
87 {
88   define_spot_array_.push (here_input());
89 }
90
91 char const *
92 My_lily_parser::here_ch_C() const
93 {
94   return lexer_p_->here_ch_C();
95 }
96
97 void
98 My_lily_parser::parser_error (String s)
99 {
100   here_input().error (s);
101   if (fatal_error_i_)
102     exit (fatal_error_i_);
103   error_level_i_ = 1;
104   exit_status_i_ = 1;
105 }
106
107 void
108 My_lily_parser::set_duration_mode (String s)
109 {
110   s = s.upper_str();
111   last_duration_mode_b_ = (s== "LAST");
112 }
113
114 void
115 My_lily_parser::set_octave_mode (String s)
116 {
117   s = s.upper_str();
118   if (s == "RELATIVE")
119     {
120       relative_octave_mode_b_ = true;
121       // must reset these
122       last_melodic_ = new Melodic_req;
123       last_melodic_->octave_i_ = 0; // -1; // huh?
124       last_melodic_->notename_i_ = 0;
125       last_melodic_->accidental_i_ = 0;
126     }
127   else
128     relative_octave_mode_b_ = false;
129 }
130
131 void
132 My_lily_parser::set_abbrev_beam (int type_i)
133 {
134   abbrev_beam_type_i_ = type_i;
135 }
136
137 void
138 My_lily_parser::set_default_duration (Duration const *d)
139 {
140   last_duration_mode_b_ = false;
141   default_duration_ = *d;
142 }
143
144
145 void
146 My_lily_parser::set_last_duration (Duration const *d)
147 {
148   if (last_duration_mode_b_)
149     {
150       default_duration_ = *d;
151       /* 
152         forget plet part,
153         sticky plet factor only within plet brackets
154        */  
155       default_duration_.set_plet (1, 1);
156     }
157 }
158
159 String
160 My_lily_parser::notename_str (Melodic_req* melodic)
161 {
162   // ugh
163   String str ((char)('a' + ((melodic->notename_i_ + 2) % 7)));
164   int i = melodic->accidental_i_;
165   while (i-- > 0) 
166     str += "is";
167   i++;
168   while (i++ < 0)
169     str += "es";
170   return str;
171 }
172
173 Melodic_req* 
174 My_lily_parser::get_melodic_req (Melodic_req* melodic, int quotes)
175 {
176   if (relative_octave_mode_b_)
177     {
178       set_nearest (melodic);
179       int d = melodic->pitch () - last_melodic_->pitch ();
180       if (quotes && (sign (d) == sign (quotes)))
181         quotes -= sign (quotes);
182       melodic->octave_i_ += quotes;
183     }
184   else
185     {
186       Melodic_req nearest (*melodic);
187       set_nearest (&nearest);
188       melodic->octave_i_ += quotes;
189
190       if (find_quarts_global_b)
191         {
192           int e = melodic->pitch () - nearest.pitch ();
193           if (e)
194             {
195               int d = melodic->pitch () - last_melodic_->pitch ();
196               String str = _("Interval bigger than quart");
197               int n = 1 + (abs (d) - 1) / 12;
198               String quote_str ('\'', n);
199 #if 0
200               str += d < 0 ? _(", prepend: ") : _(", append: ");
201               str += quote_str;
202 #else
203               str += _(", relative: ");
204               String name_str = notename_str (melodic);
205               str += d < 0 ? quote_str + name_str : name_str + quote_str;
206 #endif
207               melodic->warning (str);
208             }
209         }
210     }
211   delete last_melodic_;
212   last_melodic_ = melodic->clone ()->musical ()->melodic ();
213   return melodic;
214 }
215
216 void
217 My_lily_parser::set_nearest (Melodic_req* melodic)
218 {
219   melodic->octave_i_ = last_melodic_->octave_i_;
220   int d = melodic->pitch () - last_melodic_->pitch ();
221   if (abs (d) > 6)
222     melodic->octave_i_ -= sign (d);
223 }
224
225 Chord*
226 My_lily_parser::get_word_element (Text_def* tdef_p, Duration * duration_p)
227 {
228   Chord* velt_p = new Request_chord;
229
230   Lyric_req* lreq_p = new Lyric_req (tdef_p);
231
232   lreq_p->duration_ = *duration_p;
233   lreq_p->set_spot (here_input());
234
235   velt_p->add (lreq_p);
236
237   delete  duration_p;
238   return velt_p;
239 }
240
241
242 Chord *
243 My_lily_parser::get_rest_element (String s,  Duration * duration_p)
244 {
245   Chord* velt_p = new Request_chord;
246   velt_p->set_spot (here_input());
247
248   if (s=="s")
249     { /* Space */
250       Skip_req * skip_p = new Skip_req;
251       skip_p->duration_ = *duration_p;
252
253       skip_p->set_spot (here_input());
254       velt_p->add (skip_p);
255     }
256   else
257     {
258       Rest_req * rest_req_p = new Rest_req;
259       rest_req_p->duration_ = *duration_p;
260       rest_req_p->set_spot (here_input());
261
262       velt_p->add (rest_req_p);
263     }
264
265   delete duration_p;
266   return velt_p;
267 }
268
269 Chord *
270 My_lily_parser::get_note_element (Note_req *rq, Duration * duration_p)
271 {
272   Chord*v = new Request_chord;
273   v->set_spot (here_input ());
274
275   v->add (rq);
276
277   // too bad parser reads (default) duration via member access,
278   // this hack will do for now..
279   if (abbrev_beam_type_i_)
280     {
281       assert (!duration_p->plet_b ());
282       duration_p->set_plet (1, 2);
283     }
284   rq->set_duration (*duration_p);
285   rq->set_spot (here_input ());
286   delete duration_p ;
287   return v;
288 }
289
290 Array<Request*>*
291 My_lily_parser::get_parens_request (int t)
292 {
293   Array<Request*>& reqs = *new Array<Request*>;
294   switch (t)
295     {
296     case '~':
297       reqs.push (new Tie_req);
298       break;
299     case BEAMPLET:
300     case MAEBTELP:
301       {
302         Plet_req* p = new Plet_req;
303         p->plet_i_ = plet_.type_i_;
304         reqs.push (p);
305       }
306       /* fall through */
307     case '[':
308     case ']':
309       {
310         if (!abbrev_beam_type_i_)
311           {
312             reqs.push (new Beam_req);
313           }
314         else
315           {
316             Abbreviation_beam_req* a = new Abbreviation_beam_req;
317             a->type_i_ = abbrev_beam_type_i_;
318             if (t==']')
319               abbrev_beam_type_i_ = 0;
320             reqs.push (a);
321           }
322       }
323       break;
324
325     case '>':
326     case '!':
327     case '<':
328       reqs.push (new Span_dynamic_req);
329       break;
330
331     case PLET:  
332     case TELP:
333       {
334         Plet_req* p = new Plet_req;
335         p->plet_i_ = plet_.type_i_;
336         reqs.push (p);
337       }
338       break;
339     case ')':
340     case '(':
341       {
342         reqs.push (new Slur_req);
343       }
344       break;
345     default:
346       assert (false);
347       break;
348     }
349
350   switch (t)
351     {
352     case BEAMPLET:
353       reqs.top ()->span()->spantype = Span_req::START;
354       /* fall through */
355     case '<':
356     case '>':
357     case '(':
358     case '[':
359     case PLET:
360       reqs[0]->span ()->spantype = Span_req::START;
361       break;
362     case MAEBTELP:
363       reqs.top ()->span()->spantype = Span_req::STOP;
364       /* fall through */
365     case '!':
366     case ')':
367     case ']':
368       reqs[0]->span ()->spantype = Span_req::STOP;
369       break;
370
371     default:
372       break;
373     }
374
375   for (int i = 0; i < reqs.size (); i++)
376     if (reqs[i]->musical ()->span_dynamic ())
377       {
378         Span_dynamic_req* s_l= (reqs[i]->musical ()->span_dynamic ()) ;
379         s_l->dynamic_dir_ = (t == '<') ? UP:DOWN;
380       }
381
382   // ugh? don't we do this in the parser too?
383   reqs[0]->set_spot (here_input());
384   return &reqs;
385 }
386
387 void
388 My_lily_parser::add_requests (Chord*v)
389 {
390   for (int i = 0; i < pre_reqs.size(); i++)
391     {
392       v->add (pre_reqs[i]);
393     }
394   pre_reqs.clear();
395   for (int i = 0; i <post_reqs.size(); i++)
396     {
397       v->add (post_reqs[i]);
398     }
399   post_reqs.clear();
400 }
401
402 Input
403 My_lily_parser::pop_spot()
404 {
405   return define_spot_array_.pop();
406 }
407
408 Input
409 My_lily_parser::here_input() const
410 {
411   Source_file * f_l= lexer_p_->source_file_l();
412   return Input (f_l, here_ch_C());
413 }
414
415 void
416 My_lily_parser::add_notename (String s, Melodic_req * m_p)
417 {
418   lexer_p_->add_notename (s, m_p);
419 }
420