]> git.donarmstrong.com Git - lilypond.git/blob - lily/parser.yy
patch::: 1.3.96.jcn7
[lilypond.git] / lily / parser.yy
1 %{ // -*-Fundamental-*-
2
3 /*
4   parser.yy -- Bison/C++ parser for mudela
5
6   source file of the GNU LilyPond music typesetter
7
8   (c)  1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9            Jan Nieuwenhuizen <janneke@gnu.org>
10 */
11
12 #include <iostream.h>
13 #include "translator-def.hh"
14 #include "lily-guile.hh"
15
16 #include "lookup.hh"
17 #include "misc.hh"
18 #include "my-lily-lexer.hh"
19 #include "paper-def.hh"
20 #include "midi-def.hh"
21 #include "main.hh"
22 #include "file-path.hh"
23 #include "debug.hh"
24 #include "dimensions.hh"
25 #include "identifier.hh"
26 #include "command-request.hh"
27 #include "musical-request.hh"
28 #include "my-lily-parser.hh"
29 #include "context-specced-music.hh"
30 #include "score.hh"
31 #include "music-list.hh"
32
33 #include "file-results.hh"
34 #include "input.hh"
35 #include "scope.hh"
36 #include "relative-music.hh"
37 #include "lyric-combine-music.hh"
38 #include "transposed-music.hh"
39 #include "time-scaled-music.hh"
40 #include "repeated-music.hh"
41 #include "mudela-version.hh"
42 #include "grace-music.hh"
43 #include "auto-change-music.hh"
44 #include "part-combine-music.hh"
45
46 #include "chord.hh"
47
48 bool
49 is_duration_b (int t)
50 {
51   return t && t == 1 << intlog2(t);
52 }
53
54
55 // mmm JUNKME ?
56 Mudela_version oldest_version ("1.3.59");
57
58 void
59 print_mudela_versions (ostream &os)
60 {
61   os << _f ("Oldest supported input version: %s", oldest_version.str ()) 
62     << endl;
63 }
64
65
66 // needed for bison.simple's malloc() and free()
67 #include <malloc.h>
68
69 #ifndef NDEBUG
70 #define YYDEBUG 1
71 #endif
72
73 #define YYERROR_VERBOSE 1
74
75 #define YYPARSE_PARAM my_lily_parser_l
76 #define YYLEX_PARAM my_lily_parser_l
77 #define THIS ((My_lily_parser *) my_lily_parser_l)
78
79 #define yyerror THIS->parser_error
80 #define ARRAY_SIZE(a,s)   if (a.size () != s) THIS->parser_error (_f ("Expecting %d arguments", s))
81
82 %}
83
84
85 %union {
86     Array<Musical_pitch> *pitch_arr;
87     Link_array<Request> *reqvec;
88     Duration *duration;
89     Identifier *id;
90     String * string;
91     Music *music;
92     Score *score;
93     Scope *scope;
94
95     Musical_req* musreq;
96     Music_output_def * outputdef;
97     Musical_pitch * pitch;
98     Midi_def* midi;
99     Real real;
100     Request * request;
101
102     /* We use SCMs to do strings, because it saves us the trouble of
103 deleting them.  Let's hope that a stack overflow doesnt trigger a move
104 of the parse stack onto the heap. */
105
106     SCM scm;
107
108     Tempo_req *tempo;
109     int i;
110 }
111 %{
112
113 int
114 yylex (YYSTYPE *s,  void * v_l)
115 {
116         My_lily_parser   *pars_l = (My_lily_parser*) v_l;
117         My_lily_lexer * lex_l = pars_l->lexer_p_;
118
119         lex_l->lexval_l = (void*) s;
120         return lex_l->yylex ();
121 }
122
123
124 %}
125
126 %pure_parser
127
128 /* tokens which are not keywords */
129 %token AUTOCHANGE
130 %token ARPEGGIO
131 %token DYNAMICSCRIPT
132 %token TEXTSCRIPT
133 %token ACCEPTS
134 %token ALTERNATIVE
135 %token BAR
136 %token BREATHE
137 %token CHORDMODIFIERS
138 %token CHORDS
139 %token CHAR_T
140 %token CLEF
141 %token CM_T
142 %token CONSISTS
143 %token SEQUENTIAL
144 %token SIMULTANEOUS
145 %token CONSISTSEND
146 %token DENIES
147 %token DURATION
148 %token EXTENDER
149 %token FONT
150 %token GRACE
151 %token HEADER
152 %token HYPHEN
153 %token IN_T
154 %token INVALID
155 %token KEY
156 %token LYRICS
157 %token MARK
158 %token MEASURES
159 %token MIDI
160 %token MM_T
161 %token MUSICAL_PITCH
162 %token NAME
163 %token NOTENAMES
164 %token NOTES
165 %token PAPER
166 %token PARTIAL
167 %token PENALTY
168 %token PROPERTY
169 %token PUSH POP 
170 %token PT_T
171 %token RELATIVE
172 %token REMOVE
173 %token REPEAT
174 %token ADDLYRICS
175 %token PARTCOMBINE
176 %token SCM_T
177 %token SCORE
178 %token SCRIPT
179 %token SKIP
180 %token SPANREQUEST
181 %token COMMANDSPANREQUEST
182 %token TEMPO
183 %token OUTPUTPROPERTY
184 %token TIME_T
185 %token TIMES
186 %token TRANSLATOR
187 %token TRANSPOSE
188 %token TYPE
189 %token CONTEXT
190
191 /* escaped */
192 %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER 
193 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET 
194
195 %type <i>       exclamations questions
196 %token <i>      DIGIT
197 %token <pitch>  NOTENAME_PITCH
198 %token <pitch>  TONICNAME_PITCH
199 %token <pitch>  CHORDMODIFIER_PITCH
200 %token <id>     DURATION_IDENTIFIER
201 %token <id>     IDENTIFIER
202
203
204 %token <id>     SCORE_IDENTIFIER
205 %token <id>     MUSIC_OUTPUT_DEF_IDENTIFIER
206
207 %token <scm>    NUMBER_IDENTIFIER
208 %token <scm>    REQUEST_IDENTIFIER
209 %token <scm>    MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
210 %token <scm>    STRING_IDENTIFIER SCM_IDENTIFIER 
211 %token <scm>    DURATION RESTNAME
212 %token <scm>    STRING 
213 %token <scm>    SCM_T
214 %token <i>      UNSIGNED
215 %token <real>   REAL
216
217 %type <outputdef> output_def
218 %type <scope>   mudela_header mudela_header_body
219 %type <request> open_request_parens close_request_parens open_request close_request
220 %type <request> request_with_dir request_that_take_dir verbose_request
221 %type <i>       sub_quotes sup_quotes
222 %type <music>   simple_element  request_chord command_element Simple_music  Composite_music 
223 %type <music>   Alternative_music Repeated_music
224 %type <i>       tremolo_type
225 %type <i>       bare_int  bare_unsigned
226 %type <i>       script_dir
227
228 %type <scm>     identifier_init 
229
230 %type <duration> steno_duration optional_notemode_duration
231 %type <duration> entered_notemode_duration explicit_duration
232         
233 %type <reqvec>  pre_requests post_requests
234 %type <request> gen_text_def
235 %type <pitch>   steno_musical_pitch musical_pitch absolute_musical_pitch
236 %type <pitch>   steno_tonic_pitch
237
238 %type <pitch_arr>       chord_additions chord_subtractions chord_notes chord_step
239 %type <music>   chord
240 %type <pitch>   chord_note chord_inversion chord_bass
241 %type <duration>        duration_length
242
243 %type <scm>  embedded_scm scalar
244 %type <music>   Music Sequential_music Simultaneous_music Music_sequence
245 %type <music>   relative_music re_rhythmed_music part_combined_music
246 %type <music>   property_def translator_change
247 %type <scm> Music_list
248 %type <outputdef>  music_output_def_body
249 %type <request> shorthand_command_req
250 %type <request> post_request 
251 %type <request> command_req verbose_command_req
252 %type <request> extender_req
253 %type <request> hyphen_req
254 %type <scm>     string bare_number number_expression
255 %type <score>   score_block score_body
256
257 %type <scm>     translator_spec_block translator_spec_body
258 %type <tempo>   tempo_request
259 %type <scm> notenames_body notenames_block chordmodifiers_block
260 %type <scm>     script_abbreviation
261
262
263
264 %left '-' '+'
265 %left '*' '/'
266 %left UNARY_MINUS
267
268 %%
269
270 mudela: /* empty */
271         | mudela toplevel_expression {}
272         | mudela assignment  { }
273         | mudela error {
274                 THIS->error_level_i_  = 1;
275                 //THIS->parser_error (_ ("ly invalid"));
276         }
277         | mudela INVALID        {
278                 THIS->error_level_i_  = 1;
279                 //THIS->parser_error (_ ("ly invalid"));
280         }
281         ;
282
283 toplevel_expression:
284         notenames_block                 {
285                 THIS->lexer_p_->pitchname_tab_ =  $1;
286         }
287         | chordmodifiers_block                  {
288                 THIS->lexer_p_->chordmodifier_tab_  = $1;
289         }
290         | mudela_header {
291                 delete header_global_p;
292                 header_global_p = $1;
293         }
294         | score_block {
295                 score_global_array.push ($1);
296         }
297         | output_def {
298                 Identifier * id = new
299                         Music_output_def_identifier ($1, MUSIC_OUTPUT_DEF_IDENTIFIER);
300                 if (dynamic_cast<Paper_def*> ($1))
301                         THIS->lexer_p_->set_identifier ("$defaultpaper", id->self_scm ());
302                 else if (dynamic_cast<Midi_def*> ($1))
303                         THIS->lexer_p_->set_identifier ("$defaultmidi", id->self_scm ());
304         }
305         | embedded_scm {
306                 // junk value
307         }       
308         ;
309
310 embedded_scm:
311         SCM_T
312         | SCM_IDENTIFIER 
313         ;
314
315
316 chordmodifiers_block:
317         CHORDMODIFIERS notenames_body   {  $$ = $2; }
318         ;
319
320
321 notenames_block:
322         NOTENAMES notenames_body   {  $$ = $2; }
323         ;
324
325
326
327 notenames_body:
328         embedded_scm    {
329           int i = scm_ilength ($1);
330
331           SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL);
332           for (SCM s = $1; s != SCM_EOL; s = gh_cdr (s)) {
333                 SCM pt = gh_cdar (s);
334                 if (scm_ilength (pt) != 3)
335                         THIS->parser_error ("Need three args");
336                 scm_hashq_set_x (tab, gh_caar(s), pt);
337           }
338
339           $$ = tab;
340         }
341         ;
342
343 mudela_header_body:
344         {
345                 $$ = new Scope;
346                 THIS->lexer_p_-> scope_l_arr_.push ($$);
347         }
348         | mudela_header_body assignment semicolon { 
349
350         }
351         ;
352
353 mudela_header:
354         HEADER '{' mudela_header_body '}'       {
355                 $$ = $3;
356                 THIS->lexer_p_-> scope_l_arr_.pop ();           
357         }
358         ;
359
360
361 /*
362         DECLARATIONS
363 */
364 assignment:
365         STRING {
366                 THIS->remember_spot ();
367         }
368         /* cont */ '=' identifier_init  {
369                 THIS->lexer_p_->set_identifier (ly_scm2string ($1), $4);
370
371 /*
372  TODO: devise standard for protection in parser.
373
374   The parser stack lives on the C-stack, which means that
375 all objects can be unprotected as soon as they're here.
376
377 */
378                 Identifier * id =unsmob_identifier ($4);
379                 Input spot = THIS->pop_spot ();
380                 if (id) id->set_spot (spot);
381         }
382         ;
383
384
385
386 identifier_init:
387         score_block {
388                 $$ = (new Score_identifier ($1, SCORE_IDENTIFIER))->self_scm();
389         }
390         | output_def {
391                 $$ = (new Music_output_def_identifier ($1, MUSIC_OUTPUT_DEF_IDENTIFIER))->self_scm();
392         }
393         | translator_spec_block {
394                 $$ = $1;
395         }
396         | Music  {
397                 $$ = $1->self_scm ();
398                 scm_unprotect_object ($$);
399         }
400         | post_request {
401                 $$ = $1->self_scm ();
402                 scm_unprotect_object ($$);
403         }
404         | explicit_duration {
405                 $$ = (new Duration_identifier ($1, DURATION_IDENTIFIER))->self_scm ();
406         }
407         | number_expression {
408                 $$ = $1;
409         }
410         | string {
411                 $$ = $1;
412         }
413         | embedded_scm  {
414                 $$ = $1;
415         }
416         ;
417
418 translator_spec_block:
419         TRANSLATOR '{' translator_spec_body '}'
420                 {
421                 $$ = $3;
422         }
423         ;
424
425 translator_spec_body:
426         TRANSLATOR_IDENTIFIER   {
427                 $$ = unsmob_translator_def ($1)->clone_scm ();
428                 unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
429         }
430         | TYPE STRING semicolon {
431                 $$ = Translator_def::make_scm ();
432                 Translator_def*td =  unsmob_translator_def ($$);
433                 td->translator_group_type_ = $2;
434                 td->set_spot (THIS->here_input ());
435         }
436         | translator_spec_body STRING '=' embedded_scm                  {
437                 unsmob_translator_def ($$)->add_property_assign ($2, $4);
438         }
439         | translator_spec_body STRING PUSH embedded_scm '=' embedded_scm {
440                 unsmob_translator_def ($$)
441                         ->add_push_property (scm_string_to_symbol ($2), $4, $6);
442         }
443         | translator_spec_body STRING POP embedded_scm  {
444           unsmob_translator_def($$)->add_pop_property (
445                 scm_string_to_symbol ($2), $4);
446         }
447         | translator_spec_body STRING '=' identifier_init semicolon     { 
448                 SCM v = gh_int2scm (0);
449                 if (gh_string_p ($4) || gh_number_p ($4) || gh_boolean_p ($4))
450                         v = $4;
451                 else 
452                         THIS->parser_error (_("Wrong type for property value"));
453
454                 /* ugh*/
455                 unsmob_translator_def($$)->add_property_assign ($2, v);
456         }
457         | translator_spec_body NAME STRING semicolon {
458                 unsmob_translator_def ($$)->type_name_ = $3;
459         }
460         | translator_spec_body CONSISTS STRING semicolon {
461                 unsmob_translator_def ($$)->add_element ($3);
462         }
463         | translator_spec_body CONSISTSEND STRING semicolon {
464                 unsmob_translator_def ($$)->add_last_element ( $3);
465         }
466         | translator_spec_body ACCEPTS STRING semicolon {
467                 unsmob_translator_def ($$)->set_acceptor ($3,true);
468         }
469         | translator_spec_body DENIES STRING semicolon {
470                 unsmob_translator_def ($$)->set_acceptor ($3,false);
471         }
472         | translator_spec_body REMOVE STRING semicolon {
473                 unsmob_translator_def ($$)->remove_element ($3);
474         }
475         ;
476
477 /*
478         SCORE
479 */
480 score_block:
481         SCORE { 
482                 THIS->remember_spot ();
483         }
484         /*cont*/ '{' score_body '}'     {
485                 THIS->pop_spot ();
486                 $$ = $4;
487                 if (!$$->def_p_arr_.size ())
488                 {
489                   Identifier *id =
490                         unsmob_identifier (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
491                   $$->add_output (id ? id->access_content_Music_output_def (true) : new Paper_def );
492                 }
493         }
494 /*
495         | SCORE '{' score_body error {
496                 $$ = $3
497                 $$->set_spot (THIS->here_input ());
498                 // THIS->here_input ().error ("SCORE INVALID");
499                 $$->error ("SCORE INVALID");
500                 THIS->parser_error (_f ("SCORE ERROR"));
501         }
502 */
503         ;
504
505 score_body:
506         Music   {
507                 $$ = new Score;
508
509                 $$->set_spot (THIS->here_input ());
510                 SCM m = $1->self_scm ();
511                 scm_unprotect_object (m);
512                 $$->music_ = m;
513         }
514         | SCORE_IDENTIFIER {
515                 $$ = $1->access_content_Score (true);
516         }
517         | score_body mudela_header      {
518                 $$->header_p_ = $2;
519         }
520         | score_body output_def {
521                 $$->add_output ($2);
522         }
523         | score_body error {
524
525         }
526         ;
527
528
529 /*
530         MIDI
531 */
532 output_def:
533         music_output_def_body '}' {
534                 $$ = $1;
535                 THIS-> lexer_p_-> scope_l_arr_.pop();
536         }
537         ;
538
539 music_output_def_body:
540         MIDI '{'    {
541          Identifier *id = unsmob_identifier (THIS->lexer_p_->lookup_identifier ("$defaultmidi"));
542
543                 
544          Midi_def* p =0;
545         if (id)
546                 p = dynamic_cast<Midi_def*> (id->access_content_Music_output_def (true));
547         else
548                 p = new Midi_def;
549
550          $$ = p;
551          THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
552         }
553         | PAPER '{'     {
554                   Identifier *id = unsmob_identifier (THIS->lexer_p_->lookup_identifier ("$defaultpaper"));
555                   Paper_def *p = 0;
556                 if (id)
557                         p = dynamic_cast<Paper_def*> (id->access_content_Music_output_def (true));
558                 else
559                         p = new Paper_def;
560                 THIS-> lexer_p_-> scope_l_arr_.push (p->scope_p_);
561                 $$ = p;
562         }
563         | PAPER '{' MUSIC_OUTPUT_DEF_IDENTIFIER         {
564                 Music_output_def *p = $3->access_content_Music_output_def (true);
565                 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
566                 $$ = p;
567         }
568         | MIDI '{' MUSIC_OUTPUT_DEF_IDENTIFIER  {
569                 Music_output_def *p = $3->access_content_Music_output_def (true);
570                 THIS->lexer_p_->scope_l_arr_.push (p->scope_p_);
571                 $$ = p;
572         }
573         | music_output_def_body assignment semicolon {
574
575         }
576         | music_output_def_body translator_spec_block   {
577                 $$->assign_translator ($2);
578         }
579         | music_output_def_body tempo_request semicolon {
580                 /*
581                         junk this ? there already is tempo stuff in
582                         music.
583                 */
584                 dynamic_cast<Midi_def*> ($$)->set_tempo ($2->dur_.length_mom (), $2->metronome_i_);
585         }
586         | music_output_def_body bare_int '=' FONT STRING                { // ugh, what a syntax
587                 SCM sl = Lookup::make_lookup();
588                 Lookup * l =unsmob_lookup (sl);
589                 l->font_name_ = ly_scm2string ($5);
590                 dynamic_cast<Paper_def*> ($$)->set_lookup ($2, sl);
591         }
592         | music_output_def_body error {
593
594         }
595         ;
596
597 tempo_request:
598         TEMPO steno_duration '=' bare_unsigned  {
599                 $$ = new Tempo_req;
600                 $$->dur_ = *$2;
601                 delete $2;
602                 $$-> metronome_i_ = $4;
603         }
604         ;
605
606 Music_list: /* empty */ {
607                 $$ = gh_cons (SCM_EOL, SCM_EOL);
608         }
609         | Music_list Music {
610                 SCM s = $$;
611                 SCM c = gh_cons ($2->self_scm (), SCM_EOL);
612                 scm_unprotect_object ($2->self_scm ()); /* UGH */
613
614         
615                 if (gh_pair_p (gh_cdr (s)))
616                         gh_set_cdr_x (gh_cdr (s), c); /* append */
617                 else
618                         gh_set_car_x (s, c); /* set first cons */
619                 gh_set_cdr_x (s, c) ;  /* remember last cell */ 
620         }
621         | Music_list error {
622         }
623         ;
624
625
626 Music:
627         Simple_music
628         | Composite_music
629         ;
630
631 Alternative_music:
632         /* empty */ {
633                 $$ = 0;
634         }
635         | ALTERNATIVE Music_sequence {
636                 $$ = $2;
637                 $2->set_spot (THIS->here_input ());
638         }
639         ;
640
641
642
643
644 Repeated_music:
645         REPEAT STRING bare_unsigned Music Alternative_music
646         {
647                 Music_sequence* m = dynamic_cast <Music_sequence*> ($5);
648                 if (m && $3 < m->length_i ())
649                         $5->origin ()->warning (_ ("More alternatives than repeats.  Junking excess alternatives."));
650
651                 Repeated_music * r = new Repeated_music ($4, $3 >? 1, m);
652                 $$ = r;
653                 r->type_ = ly_scm2string ($2);
654                 r->fold_b_ = (r->type_ == "fold");
655                 r->volta_fold_b_ =  (r->type_ == "volta");
656                 r->set_spot (*$4->origin ());
657         }
658         ;
659
660 Music_sequence: '{' Music_list '}'      {
661                 $$ = new Music_sequence (gh_car ($2));
662         }
663         ;
664
665 Sequential_music:
666         SEQUENTIAL '{' Music_list '}'           {
667                 $$ = new Sequential_music (gh_car ($3));
668         }
669         | '{' Music_list '}'            {
670                 $$ = new Sequential_music (gh_car ($2));
671         }
672         ;
673
674 Simultaneous_music:
675         SIMULTANEOUS '{' Music_list '}'{
676                 $$ = new Simultaneous_music (gh_car ($3));
677         }
678         | '<' Music_list '>'    {
679                 $$ = new Simultaneous_music (gh_car ($2));
680         }
681         ;
682
683 Simple_music:
684         request_chord           { $$ = $1; }
685         | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm     {
686                 SCM pred = $2;
687                 if (!gh_symbol_p ($3))
688                 {
689                         THIS->parser_error (_("Second argument must be a symbol")); 
690                 }
691                 /*hould check # args */
692                 if (!gh_procedure_p (pred))
693                 {
694                         THIS->parser_error (_("First argument must be a procedure taking 1 argument"));
695                 }
696
697           Music *m = new Music;
698           m->set_mus_property ("predicate", pred);
699           m->set_mus_property ("symbol", $3);
700           m->set_mus_property ("value",  $5);
701           m->set_mus_property ("type", ly_symbol2scm ("output-property"));
702
703                 $$ = m;
704         }
705         | MUSIC_IDENTIFIER {
706                 $$ = unsmob_music ($1)->clone ();
707         }
708         | property_def
709         | translator_change
710         | Simple_music '*' bare_unsigned '/' bare_unsigned      {
711                 $$ = $1;
712                 $$->compress (Moment($3, $5 ));
713         }
714         | Simple_music '*' bare_unsigned                 {
715                 $$ = $1;
716                 $$->compress (Moment ($3, 1));
717         }
718         ;
719
720
721 Composite_music:
722         CONTEXT STRING Music    {
723                 Context_specced_music *csm =  new Context_specced_music ($3);
724
725                 csm->translator_type_str_ = ly_scm2string ($2);
726                 csm->translator_id_str_ = "";
727
728
729                 $$ = csm;
730         }
731         | AUTOCHANGE STRING Music       {
732                 Auto_change_music * chm = new Auto_change_music ($3);
733                 chm->set_mus_property ("what", $2); 
734
735                 $$ = chm;
736                 chm->set_spot (*$3->origin ());
737         }
738         | GRACE Music {
739                 $$ = new Grace_music ($2);
740         }
741         | CONTEXT STRING '=' STRING Music {
742                 Context_specced_music *csm =  new Context_specced_music ($5);
743
744                 csm->translator_type_str_ = ly_scm2string ($2);
745                 csm->translator_id_str_ = ly_scm2string ($4);
746
747                 $$ = csm;
748         }
749         | TIMES {
750                 THIS->remember_spot ();
751         }
752         /* CONTINUED */ 
753                 bare_unsigned '/' bare_unsigned Music   
754
755         {
756                 $$ = new Time_scaled_music ($3, $5, $6);
757                 $$->set_spot (THIS->pop_spot ());
758         }
759         | Repeated_music                { $$ = $1; }
760         | Simultaneous_music            { $$ = $1; }
761         | Sequential_music              { $$ = $1; }
762         | TRANSPOSE musical_pitch Music {
763                 $$ = new Transposed_music ($3, *$2);
764                 delete $2; // ugh
765         }
766         | TRANSPOSE steno_tonic_pitch Music {
767                 $$ = new Transposed_music ($3, *$2);
768                 delete $2; // ugh
769         }
770         | NOTES
771                 { THIS->lexer_p_->push_note_state (); }
772         Music
773                 { $$ = $3;
774                   THIS->lexer_p_->pop_state ();
775                 }
776         | CHORDS
777                 { THIS->lexer_p_->push_chord_state (); }
778         Music
779                 {
780                   $$ = $3;
781                   THIS->lexer_p_->pop_state ();
782         }
783         | LYRICS
784                 { THIS->lexer_p_->push_lyric_state (); }
785         Music
786                 {
787                   $$ = $3;
788                   THIS->lexer_p_->pop_state ();
789         }
790         | relative_music        { $$ = $1; }
791         | re_rhythmed_music     { $$ = $1; } 
792         | part_combined_music   { $$ = $1; } 
793         ;
794
795 relative_music:
796         RELATIVE absolute_musical_pitch Music {
797                 $$ = new Relative_octave_music ($3, *$2);
798                 delete $2; // ugh
799         }
800         ;
801
802 re_rhythmed_music:
803         ADDLYRICS Music Music {
804                 Lyric_combine_music * l = new Lyric_combine_music ($2, $3);
805                 $$ = l;
806         }
807         ;
808
809 part_combined_music:
810         PARTCOMBINE STRING Music Music {
811                 Part_combine_music * p = new Part_combine_music (ly_scm2string ($2), $3, $4);
812                 $$ = p;
813         }
814         ;
815
816 translator_change:
817         TRANSLATOR STRING '=' STRING  {
818                 Music * t = new Music;
819                 t->set_mus_property ("type",
820                         ly_symbol2scm ("change-translator"));
821                 t-> set_mus_property ("change-to-type", $2);
822                 t-> set_mus_property ("change-to-id", $4);
823
824                 $$ = t;
825                 $$->set_spot (THIS->here_input ());
826         }
827         ;
828
829 property_def:
830         PROPERTY STRING '.' STRING '='  scalar {
831                 Music *t = new Music;
832
833                 t->set_mus_property ("type", ly_symbol2scm ("property-set"));
834                 t->set_mus_property ("symbol", scm_string_to_symbol ($4));
835                 t->set_mus_property ("value", $6);
836
837                 Context_specced_music *csm = new Context_specced_music (t);
838                 $$ = csm;
839                 $$->set_spot (THIS->here_input ());
840
841                 csm-> translator_type_str_ = ly_scm2string ($2);
842         }
843         | PROPERTY STRING '.' STRING PUSH embedded_scm '=' embedded_scm {
844                 Music *t = new Music;
845                 t->set_mus_property ("type", ly_symbol2scm ("property-push"));
846                 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
847                 t->set_mus_property ("element-property", $6);
848                 t->set_mus_property ("element-value", $8);
849                 Context_specced_music *csm = new Context_specced_music (t);
850                 $$ = csm;
851                 $$->set_spot (THIS->here_input ());
852
853                 csm-> translator_type_str_ = ly_scm2string ($2);
854         }
855         | PROPERTY STRING '.' STRING POP embedded_scm {
856                 Music *t = new Music;
857                 t->set_mus_property ("type", ly_symbol2scm ("property-pop"));
858                 t->set_mus_property ("symbols", scm_string_to_symbol ($4));
859                 t->set_mus_property ("element-property", $6);
860
861                 Context_specced_music *csm = new Context_specced_music (t);
862                 $$ = csm;
863                 $$->set_spot (THIS->here_input ());
864
865                 csm-> translator_type_str_ = ly_scm2string ($2);
866         }
867         ;
868
869 scalar:
870         string          { $$ = $1; }
871         | bare_int      { $$ = gh_int2scm ($1); }
872         | embedded_scm  { $$ = $1; }
873         ;
874
875
876 request_chord:
877         pre_requests simple_element post_requests       {
878                 Music_sequence *l = dynamic_cast<Music_sequence*>($2);
879                 if (l) {
880                         for (int i=0; i < $1->size(); i++)
881                                 l->append_music ($1->elem(i));
882                         for (int i=0; i < $3->size(); i++)
883                                 l->append_music ($3->elem(i));
884                         }
885                 else
886                         programming_error ("Need Sequence to add music to");
887                 $$ = $2;
888                 
889         }
890         | command_element
891         ;
892
893 command_element:
894         command_req {
895                 $$ = new Request_chord (gh_cons ($1->self_scm (), SCM_EOL));
896                 $$-> set_spot (THIS->here_input ());
897                 $1-> set_spot (THIS->here_input ());
898         }
899         | PARTIAL duration_length ';'   {
900                 Music * p = new Music;
901                 p->set_mus_property ("symbol", ly_symbol2scm ( "measurePosition"));
902                 p->set_mus_property ("type", ly_symbol2scm ("property-set"));
903
904                 Moment m = - $2->length_mom ();
905                 p->set_mus_property ("value", m.make_scm());
906                 delete $2; // ugh
907                 Context_specced_music * sp = new Context_specced_music (p);
908                 $$ =sp ;
909                 sp-> translator_type_str_ = "Score";
910         }
911         ;
912
913 command_req:
914         shorthand_command_req
915         | verbose_command_req semicolon { $$ = $1; }
916         ;
917
918 shorthand_command_req:
919         extender_req {
920                 $$ = $1;
921         }
922         | hyphen_req {
923                 $$ = $1;
924         }
925         | '|'                           {
926                 $$ = new Barcheck_req;
927         }
928         | '~'   {
929                 $$ = new Tie_req;
930         }
931         | '['           {
932                 Span_req*b= new Span_req;
933                 b->span_dir_ = START;
934                 b->span_type_str_ = "beam";
935                 $$ =b;
936         }
937         | ']'           {
938              Span_req*b= new Span_req;
939              b->span_dir_ = STOP;
940              b->span_type_str_ = "beam";
941              $$ = b;
942         }
943         | BREATHE {
944                 $$ = new Breathing_sign_req;
945         }
946         ;
947
948
949 verbose_command_req:
950         
951         BAR STRING                      {
952                 $$ = new Bar_req (ly_scm2string ($2));
953         }
954         | COMMANDSPANREQUEST bare_int STRING {
955                 Span_req * sp_p = new Span_req;
956                 sp_p-> span_dir_  = Direction($2);
957                 sp_p->span_type_str_ = ly_scm2string ($3);
958                 sp_p->set_spot (THIS->here_input ());
959                 $$ = sp_p;
960         }
961         | MARK  {
962                 Mark_req * m = new Mark_req;
963                 $$ = m;
964         }
965         | MARK STRING {
966                 Mark_req *m = new Mark_req;
967                 m->set_mus_property ("label", $2);
968                 $$ = m;
969
970         }
971         | MARK bare_unsigned {
972                 Mark_req *m = new Mark_req;
973                 m->set_mus_property ("label",  gh_int2scm ($2));
974                 $$ = m;
975         }
976
977         | TIME_T bare_unsigned '/' bare_unsigned        {
978                 Time_signature_change_req *m = new Time_signature_change_req;
979                 m->beats_i_ = $2;
980                 m->one_beat_i_=$4;
981                 $$ = m;
982         }
983         | PENALTY bare_int      {
984                 Break_req * b = new Break_req;
985                 b->penalty_f_ = $2 / 100.0;
986                 b->set_spot (THIS->here_input ());
987                 $$ = b;
988         }
989         | SKIP duration_length {
990                 Skip_req * skip_p = new Skip_req;
991                 skip_p->duration_ = *$2;
992                 delete $2; // ugh
993                 $$ = skip_p;
994         }
995         | tempo_request {
996                 $$ = $1;
997         }
998         | CLEF STRING {
999                 $$ = new Clef_change_req (ly_scm2string ($2));
1000
1001         }
1002         | KEY {
1003                 Key_change_req *key_p= new Key_change_req;
1004                 $$ = key_p;
1005         }
1006         | KEY NOTENAME_PITCH SCM_IDENTIFIER     {
1007                 Key_change_req *key_p= new Key_change_req;
1008                 
1009                 key_p->set_mus_property ("pitch-alist", $3);
1010                 ((Music* )key_p)->transpose (* $2);
1011                 $$ = key_p; 
1012         }
1013         ;
1014
1015 post_requests:
1016         {
1017                 $$ = new Link_array<Request>;
1018         }
1019         | post_requests post_request {
1020                 $2->set_spot (THIS->here_input ());
1021                 $$->push ($2);
1022         }
1023         ;
1024
1025 post_request:
1026         verbose_request
1027         | request_with_dir
1028         | close_request
1029         ;
1030
1031
1032 request_that_take_dir:
1033         gen_text_def
1034         | verbose_request
1035         | script_abbreviation {
1036                 SCM s = THIS->lexer_p_->lookup_identifier ("dash-" + ly_scm2string ($1));
1037                 Articulation_req *a = new Articulation_req;
1038                 if (gh_string_p (s))
1039                         a->articulation_str_ = ly_scm2string (s);
1040                 else THIS->parser_error (_ ("Expecting string as script definition"));
1041                 $$ = a;
1042         }
1043         ;
1044
1045 request_with_dir:
1046         script_dir request_that_take_dir        {
1047                 if (Script_req * gs = dynamic_cast<Script_req*> ($2))
1048                         gs->dir_ = Direction ($1);
1049                 else if ($1)
1050                         $2->origin ()->warning (_ ("Can't specify direction for this request"));
1051                 $$ = $2;
1052         }
1053         ;
1054         
1055 verbose_request:
1056         REQUEST_IDENTIFIER      {
1057                 $$ = dynamic_cast<Request*> (unsmob_music ($1)->clone ());
1058                 $$->set_spot (THIS->here_input ());
1059         }
1060         | DYNAMICSCRIPT embedded_scm {
1061                 Dynamic_script_req *d = new Dynamic_script_req;
1062                 d->text_ = $2;
1063                 d->set_spot (THIS->here_input ());
1064                 $$ = d;
1065         }
1066         | TEXTSCRIPT embedded_scm {
1067                 Text_script_req *t = new Text_script_req;
1068                 t->text_ = $2;
1069                 t->set_spot (THIS->here_input ());
1070                 $$ = t;
1071         }
1072         | SPANREQUEST bare_int STRING {
1073                 Span_req * sp_p = new Span_req;
1074                 sp_p->span_dir_  = Direction($2);
1075                 sp_p->span_type_str_ = ly_scm2string ($3);
1076                 sp_p->set_spot (THIS->here_input ());
1077                 $$ = sp_p;
1078         }
1079         | tremolo_type  {
1080                 Tremolo_req* a = new Tremolo_req;
1081                 a->set_spot (THIS->here_input ());
1082                 a->type_i_ = $1;
1083                 $$ = a;
1084         }
1085         | SCRIPT STRING         { 
1086                 Articulation_req * a = new Articulation_req;
1087                 a->articulation_str_ = ly_scm2string ($2);
1088                 a->set_spot (THIS->here_input ());
1089                 $$ = a;
1090         }
1091         | ARPEGGIO {
1092                 Arpeggio_req *a = new Arpeggio_req;
1093                 a->set_spot (THIS->here_input ());
1094                 $$ = a;
1095         }
1096         ;
1097
1098 sup_quotes:
1099         '\'' {
1100                 $$ = 1;
1101         }
1102         | sup_quotes '\'' {
1103                 $$ ++;
1104         }
1105         ;
1106
1107 sub_quotes:
1108         ',' {
1109                 $$ = 1;
1110         }
1111         | sub_quotes ',' {
1112                 $$ ++ ;
1113         }
1114         ;
1115
1116 steno_musical_pitch:
1117         NOTENAME_PITCH  {
1118                 $$ = $1;
1119         }
1120         | NOTENAME_PITCH sup_quotes     {
1121                 $$ = $1;
1122                 $$->octave_i_ +=  $2;
1123         }
1124         | NOTENAME_PITCH sub_quotes      {
1125                 $$ = $1;
1126                 $$->octave_i_ += - $2;
1127         }
1128         ;
1129
1130 steno_tonic_pitch:
1131         TONICNAME_PITCH {
1132                 $$ = $1;
1133         }
1134         | TONICNAME_PITCH sup_quotes    {
1135                 $$ = $1;
1136                 $$->octave_i_ +=  $2;
1137         }
1138         | TONICNAME_PITCH sub_quotes     {
1139                 $$ = $1;
1140                 $$->octave_i_ += - $2;
1141         }
1142         ;
1143
1144 musical_pitch:
1145         steno_musical_pitch {
1146                 $$ = $1;
1147         }
1148         | MUSICAL_PITCH embedded_scm {
1149                 int sz = scm_ilength ($2);
1150                 if (sz != 3) {
1151                         THIS->parser_error (_f ("Expecting %d arguments", 3));
1152                         $2 = gh_list (gh_int2scm (0), gh_int2scm (0), gh_int2scm (0), SCM_UNDEFINED);
1153                 }
1154                 $$ = new Musical_pitch ($2);
1155         }
1156         ;
1157
1158 explicit_duration:
1159         DURATION embedded_scm   {
1160                 $$ = new Duration;
1161                 if (scm_ilength ($2) == 2)
1162                         {
1163                         $$-> durlog_i_ = gh_scm2int (gh_car($2));
1164                         $$-> dots_i_ = gh_scm2int (gh_cadr($2));
1165                         }
1166                 else
1167                         THIS->parser_error (_("Must have 2 arguments for duration"));
1168         }
1169         ;
1170
1171 extender_req:
1172         EXTENDER {
1173                 if (!THIS->lexer_p_->lyric_state_b ())
1174                         THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1175                 $$ = new Extender_req;
1176         }
1177         ;
1178
1179 hyphen_req:
1180         HYPHEN {
1181                 if (!THIS->lexer_p_->lyric_state_b ())
1182                         THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
1183                 $$ = new Hyphen_req;
1184         }
1185         ;
1186
1187 close_request:
1188         close_request_parens {
1189                 $$ = $1;
1190                 dynamic_cast<Span_req*> ($$)->span_dir_ = START;
1191         }
1192         
1193 close_request_parens:
1194         '('     {
1195                 Span_req* s= new Span_req;
1196                 $$ = s;
1197                 s->span_type_str_ = "slur";
1198         }
1199         | E_SMALLER {
1200                 Span_req*s =new Span_req;
1201                 $$ = s;
1202                 s->span_type_str_ = "crescendo";
1203         }
1204         | E_BIGGER {
1205                 Span_req*s =new Span_req;
1206                 $$ = s;
1207                 s->span_type_str_ = "decrescendo";
1208         }
1209         ;
1210
1211
1212 open_request:
1213         open_request_parens {
1214                 $$ = $1;
1215                 dynamic_cast<Span_req*> ($$)->span_dir_ = STOP;
1216         }
1217         ;
1218
1219 open_request_parens:
1220         E_EXCLAMATION   {
1221                 Span_req *s =  new Span_req;
1222                 s->span_type_str_ = "crescendo";
1223                 $$ = s;
1224         }
1225         | ')'   {
1226                 Span_req* s= new Span_req;
1227                 $$ = s;
1228                 s->span_type_str_ = "slur";
1229         }
1230         ;
1231
1232 gen_text_def:
1233         embedded_scm {
1234                 Text_script_req *t = new Text_script_req;
1235                 t->text_ = $1;  
1236                 t->set_spot (THIS->here_input ());
1237                 $$ = t;
1238         }
1239         | string {
1240                 Text_script_req *t = new Text_script_req;
1241                 t->text_ = $1;
1242                 t->set_spot (THIS->here_input ());
1243                 $$ = t;
1244         }
1245         | DIGIT {
1246                 /*
1247                   Maybe use Finger_script_request?
1248                 */
1249                 Text_script_req* t = new Text_script_req;
1250                 t->text_ = gh_cons (ly_symbol2scm ("finger"),
1251                         ly_str02scm (to_str ($1).ch_C ()));
1252                 t->set_spot (THIS->here_input ());
1253                 $$ = t;
1254         }
1255         ;
1256
1257 script_abbreviation:
1258         '^'             {
1259                 $$ = gh_str02scm  ("hat");
1260         }
1261         | '+'           {
1262                 $$ = gh_str02scm("plus");
1263         }
1264         | '-'           {
1265                 $$ = gh_str02scm ("dash");
1266         }
1267         | '|'           {
1268                 $$ = gh_str02scm ("bar");
1269         }
1270         | '>'           {
1271                 $$ = gh_str02scm ("larger");
1272         }
1273         | '.'           {
1274                 $$ = gh_str02scm ("dot");
1275         }
1276         ;
1277
1278
1279 script_dir:
1280         '_'     { $$ = DOWN; }
1281         | '^'   { $$ = UP; }
1282         | '-'   { $$ = CENTER; }
1283         ;
1284
1285 pre_requests:
1286         {
1287                 $$ = new Link_array<Request>;
1288         }
1289         | pre_requests open_request {
1290                 $$->push ($2);
1291         }
1292         ;
1293
1294 absolute_musical_pitch:
1295         steno_musical_pitch     {
1296                 $$ = $1;
1297         }
1298         ;
1299
1300 duration_length:
1301         steno_duration {
1302                 $$ = $1;
1303         }
1304         | duration_length '*' bare_unsigned {
1305                 $$->tuplet_iso_i_ *= $3;
1306         }
1307         | duration_length '/' bare_unsigned {
1308                 $$->tuplet_type_i_ *= $3;
1309         }
1310         ;
1311
1312 entered_notemode_duration:
1313         steno_duration  {
1314                 THIS->set_last_duration ($1);
1315         }
1316         ;
1317
1318 optional_notemode_duration:
1319         {
1320                 $$ = new Duration (THIS->default_duration_);
1321         }
1322         | entered_notemode_duration {
1323                 $$ = $1;
1324         }
1325         ;
1326
1327 steno_duration:
1328         bare_unsigned           {
1329                 $$ = new Duration;
1330                 if (!is_duration_b ($1))
1331                         THIS->parser_error (_f ("not a duration: %d", $1));
1332                 else {
1333                         $$->durlog_i_ = intlog2 ($1);
1334                      }
1335         }
1336         | DURATION_IDENTIFIER   {
1337                 $$ = $1->access_content_Duration (true);
1338         }
1339         | steno_duration '.'    {
1340                 $$->dots_i_ ++;
1341         }
1342         ;
1343
1344
1345 tremolo_type: 
1346         ':'     {
1347                 $$ =0;
1348         }
1349         | ':' bare_unsigned {
1350                 if (!is_duration_b ($2))
1351                         THIS->parser_error (_f ("not a duration: %d", $2));
1352                 $$ = $2;
1353         }
1354         ;
1355
1356
1357 simple_element:
1358         musical_pitch exclamations questions optional_notemode_duration {
1359                 if (!THIS->lexer_p_->note_state_b ())
1360                         THIS->parser_error (_ ("Have to be in Note mode for notes"));
1361
1362
1363                 Note_req *n = new Note_req;
1364                 
1365                 n->pitch_ = *$1;
1366                 n->duration_ = *$4;
1367
1368                 n->cautionary_b_ = $3 % 2;
1369                 n->forceacc_b_ = $2 % 2 || n->cautionary_b_;
1370
1371
1372                 Simultaneous_music*v = new Request_chord (gh_list (n->self_scm (), SCM_UNDEFINED));
1373                 v->set_spot ($1->spot ());
1374                 n->set_spot ($1->spot ());
1375                 $$ = v;
1376
1377                 delete $1;
1378                 delete $4;
1379         }
1380         | RESTNAME optional_notemode_duration           {
1381
1382                 SCM e = SCM_UNDEFINED;
1383                   if (ly_scm2string ($1) =="s")
1384                     { /* Space */
1385                       Skip_req * skip_p = new Skip_req;
1386                       skip_p->duration_ = *$2;
1387
1388                       skip_p->set_spot (THIS->here_input());
1389                         e = skip_p->self_scm ();
1390                     }
1391                   else
1392                     {
1393                       Rest_req * rest_req_p = new Rest_req;
1394                       rest_req_p->duration_ = *$2;
1395                       rest_req_p->set_spot (THIS->here_input());
1396                         e = rest_req_p->self_scm ();
1397                     }
1398                   Simultaneous_music* velt_p = new Request_chord (gh_list (e,SCM_UNDEFINED));
1399                   velt_p->set_spot (THIS->here_input());
1400
1401                   delete $2; // ugh
1402                   $$ = velt_p;
1403         }
1404         | MEASURES optional_notemode_duration   {
1405                 Skip_req * sk = new Skip_req;
1406                 sk->duration_ = *$2;
1407                 
1408
1409                 Span_req *sp1 = new Span_req;
1410                 Span_req *sp2 = new Span_req;
1411                 sp1-> span_dir_ = START;
1412                 sp2-> span_dir_ = STOP;
1413                 sp1->span_type_str_ = sp2->span_type_str_ = "rest";
1414
1415                 Request_chord * rqc1 = new Request_chord (gh_list (sp1->self_scm (), SCM_UNDEFINED));
1416                 Request_chord * rqc2 = new Request_chord (gh_list (sk->self_scm (), SCM_UNDEFINED));;
1417                 Request_chord * rqc3 = new Request_chord(gh_list (sp2->self_scm (), SCM_UNDEFINED));;
1418
1419                 SCM ms = gh_list (rqc1->self_scm (), rqc2->self_scm (), rqc3->self_scm (), SCM_UNDEFINED);
1420
1421                 $$ = new Sequential_music (ms);
1422         }
1423         | STRING { 
1424                 THIS->remember_spot ();
1425         } 
1426         /* cont */
1427         optional_notemode_duration      {
1428                 if (!THIS->lexer_p_->lyric_state_b ()) {
1429                         THIS->pop_spot ().error (_ ("Have to be in Lyric mode for lyrics"));
1430                         THIS->error_level_i_  = 1;
1431                         THIS->parser_error (_ ("Giving up"));
1432                 } 
1433                 else
1434                         THIS->pop_spot ();
1435                 Lyric_req* lreq_p = new Lyric_req;
1436                 lreq_p ->text_ = $1;
1437                 lreq_p->duration_ = *$3;
1438                 lreq_p->set_spot (THIS->here_input());
1439                 Simultaneous_music* velt_p = new Request_chord (gh_list (lreq_p->self_scm (), SCM_UNDEFINED));
1440
1441                 delete  $3; // ugh
1442                 $$= velt_p;
1443
1444         }
1445         | chord {
1446                 if (!THIS->lexer_p_->chord_state_b ())
1447                         THIS->parser_error (_ ("Have to be in Chord mode for chords"));
1448                 $$ = $1;
1449         }
1450         ;
1451
1452
1453 chord:
1454         steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
1455                 $$ = get_chord (*$1, $3, $4, $5, $6, *$2);
1456                 $$->set_spot (THIS->here_input ());
1457         };
1458
1459 chord_additions: 
1460         {
1461                 $$ = new Array<Musical_pitch>;
1462         } 
1463         | CHORD_COLON chord_notes {
1464                 $$ = $2;
1465         }
1466         ;
1467
1468 chord_notes:
1469         chord_step {
1470                 $$ = $1
1471         }
1472         | chord_notes '.' chord_step {
1473                 $$ = $1;
1474                 $$->concat (*$3);
1475         }
1476         ;
1477
1478 chord_subtractions: 
1479         {
1480                 $$ = new Array<Musical_pitch>;
1481         } 
1482         | CHORD_CARET chord_notes {
1483                 $$ = $2;
1484         }
1485         ;
1486
1487
1488 chord_inversion:
1489         {
1490                 $$ = 0;
1491         }
1492         | '/' steno_tonic_pitch {
1493                 $$ = $2;
1494                 $$->set_spot (THIS->here_input ());
1495         }
1496         ;
1497
1498 chord_bass:
1499         {
1500                 $$ = 0;
1501         }
1502         | CHORD_BASS steno_tonic_pitch {
1503                 $$ = $2;
1504                 $$->set_spot (THIS->here_input ());
1505         }
1506         ;
1507
1508 chord_step:
1509         chord_note {
1510                 $$ = new Array<Musical_pitch>;
1511                 $$->push (*$1);
1512         }
1513         | CHORDMODIFIER_PITCH {
1514                 $$ = new Array<Musical_pitch>;
1515                 $$->push (*$1);
1516         }
1517         | CHORDMODIFIER_PITCH chord_note { /* Ugh. */
1518                 $$ = new Array<Musical_pitch>;
1519                 $$->push (*$1);
1520                 $$->push (*$2);
1521         }
1522         ;
1523
1524 chord_note:
1525         bare_unsigned {
1526                 $$ = new Musical_pitch;
1527                 $$->notename_i_ = ($1 - 1) % 7;
1528                 $$->octave_i_ = $1 > 7 ? 1 : 0;
1529                 $$->accidental_i_ = 0;
1530         } 
1531         | bare_unsigned '+' {
1532                 $$ = new Musical_pitch;
1533                 $$->notename_i_ = ($1 - 1) % 7;
1534                 $$->octave_i_ = $1 > 7 ? 1 : 0;
1535                 $$->accidental_i_ = 1;
1536         }
1537         | bare_unsigned CHORD_MINUS {
1538                 $$ = new Musical_pitch;
1539                 $$->notename_i_ = ($1 - 1) % 7;
1540                 $$->octave_i_ = $1 > 7 ? 1 : 0;
1541                 $$->accidental_i_ = -1;
1542         }
1543         ;
1544
1545 /*
1546         UTILITIES
1547  */
1548 number_expression:
1549         bare_number {
1550                 $$ = $1;
1551         }
1552         | '-'  number_expression %prec UNARY_MINUS {
1553                 $$ = scm_difference ($2, SCM_UNDEFINED);
1554         }
1555         | number_expression '*' number_expression {
1556                 $$ = scm_product ($1, $3);
1557         }
1558         | number_expression '/' number_expression {
1559                 $$ = scm_divide ($1, $3);
1560         }
1561         | number_expression '+' number_expression {
1562                 $$ = scm_sum ($1, $3);
1563         }
1564         | number_expression '-' number_expression {
1565                 $$ = scm_difference ($1, $3);
1566         }
1567         | '(' number_expression ')'     {
1568                 $$ = $2;
1569         }
1570         ;
1571
1572 bare_number:
1573         UNSIGNED        {
1574                 $$ = gh_int2scm ($1);
1575         }
1576         | DIGIT         {
1577                 $$ = gh_int2scm ($1);
1578         }
1579         | REAL          {
1580                 $$ = gh_double2scm ($1);
1581         }
1582         | NUMBER_IDENTIFIER             {
1583                 $$ = $1;
1584         }
1585         | REAL CM_T     {
1586                 $$ = gh_double2scm ($1 CM);
1587         }
1588         | REAL PT_T     {
1589                 $$ = gh_double2scm ($1 PT);
1590         }
1591         | REAL IN_T     {
1592                 $$ = gh_double2scm ($1 INCH);
1593         }
1594         | REAL MM_T     {
1595                 $$ = gh_double2scm ($1 MM);
1596         }
1597         | REAL CHAR_T   {
1598                 $$ = gh_double2scm ($1 CHAR);
1599         }
1600         ;
1601
1602
1603 bare_unsigned:
1604         bare_number {
1605                 if (scm_integer_p ($1) == SCM_BOOL_T) {
1606                         $$ = gh_scm2int ($1);
1607
1608                 } else {
1609                         THIS->parser_error (_("need integer number arg"));
1610                         $$ = 0;
1611                 }
1612                 if ($$ < 0) {
1613                         THIS->parser_error (_("Must be positive integer"));
1614                         $$ = -$$;
1615                         }
1616
1617         }
1618         ;
1619 bare_int:
1620         bare_number {
1621                 if (scm_integer_p ($1) == SCM_BOOL_T)
1622                 {
1623                         int k = gh_scm2int ($1);
1624                         $$ = k;
1625                 } else
1626                 {
1627                         THIS->parser_error (_("need integer number arg"));
1628                         $$ = 0;
1629                 }
1630         }
1631         | '-' bare_int {
1632                 $$ = -$2;
1633         }
1634         ;
1635
1636
1637 string:
1638         STRING          {
1639                 $$ = $1;
1640         }
1641         | STRING_IDENTIFIER     {
1642                 $$ = $1;
1643         }
1644         | string '+' string {
1645                 $$ = scm_string_append (scm_listify ($1, $3, SCM_UNDEFINED));
1646         }
1647         ;
1648
1649
1650 exclamations:
1651                 { $$ = 0; }
1652         | exclamations '!'      { $$ ++; }
1653         ;
1654
1655 questions:
1656                 { $$ = 0; }
1657         | questions '?' { $$ ++; }
1658         ;
1659
1660
1661 semicolon:
1662         ';'
1663         ;
1664
1665 %%
1666
1667 void
1668 My_lily_parser::set_yydebug (bool b)
1669 {
1670 #ifdef YYDEBUG
1671         yydebug = b;
1672 #endif
1673 }
1674 void
1675 My_lily_parser::do_yyparse ()
1676 {
1677         yyparse ((void*)this);
1678 }
1679
1680