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