1 %{ // -*-Fundamental-*-
4 parser.y -- lily parser
6 source file of the GNU LilyPond music typesetter
8 (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
9 Jan Nieuwenhuizen <jan@digicash.com>
15 #define MUDELA_VERSION "0.1.1"
17 #include "script-def.hh"
18 #include "symtable.hh"
21 #include "my-lily-lexer.hh"
22 #include "paper-def.hh"
23 #include "midi-def.hh"
27 #include "parseconstruct.hh"
29 #include "identifier.hh"
30 #include "command-request.hh"
31 #include "musical-request.hh"
32 #include "my-lily-parser.hh"
33 #include "text-def.hh"
34 #include "input-translator.hh"
36 #include "music-list.hh"
42 #define YYERROR_VERBOSE 1
44 #define YYPARSE_PARAM my_lily_parser_l
45 #define YYLEX_PARAM my_lily_parser_l
46 #define THIS ((My_lily_parser *) my_lily_parser_l)
48 #define yyerror THIS->parser_error
54 Array<Melodic_req*> *melreqvec;/* should clean up naming */
55 Array<String> * strvec;
61 Input_translator* itrans;
63 Music_list *musiclist;
74 General_script_def * script;
78 Symtables * symtables;
89 yylex(YYSTYPE *s, void * v_l)
91 My_lily_parser *pars_l = (My_lily_parser*) v_l;
92 My_lily_lexer * lex_l = pars_l->lexer_p_;
94 lex_l->lexval_l = (void*) s;
95 return lex_l->yylex();
103 /* tokens which are not keywords */
114 %token DURATIONCOMMAND
119 %token REQUESTTRANSLATOR
127 %token MELODIC_REQUEST
155 %token E_EXCLAMATION E_SMALLER E_BIGGER E_CHAR
159 %token <melreq> NOTENAME_ID
160 %token <id> IDENTIFIER
161 %token <id> MELODIC_REQUEST_IDENTIFIER
162 %token <id> MUSIC_IDENTIFIER
163 %token <id> VOICE_IDENTIFIER
164 %token <id> POST_REQUEST_IDENTIFIER
165 %token <id> SCRIPT_IDENTIFIER
166 %token <id> COMMAND_IDENTIFIER
167 %token <id> REAL_IDENTIFIER
168 %token <id> INPUT_TRANS_IDENTIFIER
169 %token <id> INT_IDENTIFIER
170 %token <id> SCORE_IDENTIFIER
171 %token <id> MIDI_IDENTIFIER
172 %token <id> PAPER_IDENTIFIER
173 %token <id> REQUEST_IDENTIFIER
175 %token <string> DURATION RESTNAME
176 %token <string> STRING
177 %token <i> POST_QUOTES
178 %token <i> PRE_QUOTES
182 %type <c> open_request_parens close_request_parens
183 %type <c> open_plet_parens close_plet_parens
184 %type <music> simple_element music_elt full_element lyrics_elt command_elt
187 %type <id> declaration
188 %type <duration> explicit_duration notemode_duration entered_notemode_duration
189 %type <interval> dinterval
190 %type <intvec> intastint_list
191 %type <lookup> symtables symtables_body
192 %type <melreq> melodic_request steno_melodic_req
193 %type <notereq> steno_note_req
194 %type <melreqvec> pitch_list
195 %type <midi> midi_block midi_body
196 %type <moment> duration_length
198 %type <music> Music transposed_music
199 %type <musiclist> Voice Voice_body
200 %type <chord> Chord Chord_body
201 %type <paper> paper_block paper_body
202 %type <real> dim real
204 %type <request> post_request pre_request command_req verbose_command_req abbrev_command_req
205 %type <request> script_req dynamic_req
206 %type <score> score_block score_body
207 %type <script> script_definition script_body mudela_script gen_script_def
208 %type <textdef> text_def
209 %type <string> declarable_identifier
210 %type <string> script_abbreviation
211 %type <id> old_identifier
212 %type <symbol> symboldef
213 %type <symtable> symtable symtable_body
214 %type <itrans> input_translator_spec input_translator_spec_body
215 %type <tempo> tempo_request
222 | mudela score_block {
225 | mudela add_declaration { }
227 | mudela check_version { }
228 | mudela add_notenames { }
233 if ( String( *$2 ) != MUDELA_VERSION) {
234 if (THIS->ignore_version_b_) {
235 THIS->here_input().error("Incorrect mudela version");
237 THIS->fatal_error_i_ = 1;
238 THIS->parser_error("Incorrect mudela version");
245 NOTENAMES '{' notenames_body '}'
250 | notenames_body CLEAR {
251 THIS->clear_notenames();
253 | notenames_body STRING '=' melodic_request {
254 THIS->add_notename(*$2, $4);
261 add_declaration: declaration {
262 THIS->lexer_p_->add_identifier($1);
263 $1->init_b_ = THIS->init_parse_b_;
264 $1->set_spot(THIS->pop_spot());
268 declarable_identifier:
270 THIS->remember_spot();
274 THIS->remember_spot();
275 $$ = new String($1->name_str_);
276 THIS->here_input().warning("redeclaration of `" + *$$ + "'");
283 | INPUT_TRANS_IDENTIFIER
284 | MELODIC_REQUEST_IDENTIFIER
285 | POST_REQUEST_IDENTIFIER
293 declarable_identifier '=' score_block {
294 $$ = new Score_id(*$1, $3, SCORE_IDENTIFIER);
297 | declarable_identifier '=' paper_block {
298 $$ = new Paper_def_id(*$1, $3, PAPER_IDENTIFIER);
301 | declarable_identifier '=' midi_block {
302 $$ = new Midi_def_id(*$1, $3, MIDI_IDENTIFIER);
305 | declarable_identifier '=' script_definition {
306 $$ = new Script_id(*$1, $3, SCRIPT_IDENTIFIER);
309 | declarable_identifier '=' Music {
310 $$ = new Music_id(*$1, $3, MUSIC_IDENTIFIER);
313 | declarable_identifier '=' symtables {
314 $$ = new Lookup_id(*$1, $3, IDENTIFIER);
317 | declarable_identifier '=' real {
318 $$ = new Real_id(*$1, new Real($3), REAL_IDENTIFIER);
321 | declarable_identifier '=' int {
322 $$ = new Int_id(*$1, new int($3), INT_IDENTIFIER);
325 | declarable_identifier '=' post_request {
326 $$ = new Request_id(*$1, $3, POST_REQUEST_IDENTIFIER);
329 | declarable_identifier '=' melodic_request {
330 $$ = new Request_id(*$1, $3, MELODIC_REQUEST_IDENTIFIER);
333 | declarable_identifier '=' input_translator_spec {
334 $$ = new Input_translator_id ( *$1, $3, INPUT_TRANS_IDENTIFIER);
341 input_translator_spec:
342 REQUESTTRANSLATOR '{' input_translator_spec_body '}'
346 input_translator_spec_body:
347 INPUT_TRANS_IDENTIFIER {
348 $$ = $1->input_translator(true);
349 $$-> set_spot( THIS->here_input() );
352 $$ = new Input_translator;
355 $$->set_spot ( THIS->here_input() );
359 | input_translator_spec_body ID STRING ';' {
360 $$-> default_id_str_ = *$3;
363 | input_translator_spec_body ALIAS STRING ';' {
364 $$-> alias_str_arr_.push(*$3);
367 | input_translator_spec_body CONSISTS STRING ';' {
368 $$-> consists_str_arr_.push(*$3);
371 | input_translator_spec_body CONTAINS input_translator_spec {
380 SCORE { THIS->remember_spot(); }
381 /*cont*/ '{' score_body '}' {
383 $$->set_spot(THIS->pop_spot());
384 if (!$$->paper_p_ && ! $$->midi_p_)
385 $$->paper_p_ = THIS->default_paper();
387 /* handle error levels. */
388 $$->errorlevel_i_ = THIS->error_level_i_;
389 THIS->error_level_i_ = 0;
397 $$ = $1->score(true);
402 | score_body paper_block {
405 | score_body midi_block {
414 /* */ { $$ =new Array<int>; }
415 | intastint_list int '*' int {
416 $$->push($2); $$->push($4);
426 '{' paper_body '}' { $$ = $3; }
431 $$ = THIS->default_paper(); // paper / video / engrave
433 | paper_body OUTPUT STRING ';' { $$->outfile_str_ = *$3;
436 | paper_body symtables { $$->set($2); }
437 | paper_body STRING '=' dim ';' {
438 $$->set_var(*$2, $4);
440 | paper_body STRING '=' real ';' {
441 $$->set_var(*$2, $4);
443 | paper_body input_translator_spec {
457 '{' midi_body '}' { $$ = $3; }
460 midi_body: /* empty */ {
461 $$ = THIS->default_midi();
463 | midi_body OUTPUT STRING ';' {
464 $$->outfile_str_ = *$3;
467 | midi_body tempo_request ';' {
468 $$->set_tempo( $2->dur_.length(), $2->metronome_i_ );
471 | midi_body input_translator_spec {
480 TEMPO entered_notemode_duration '=' int {
484 $$-> metronome_i_ = $4;
502 | Voice_body ID STRING STRING ';' {
515 full_element { $$ = $1; }
518 | transposed_music { $$ = $1; }
519 | MUSIC_IDENTIFIER { $$ = $1->music(true); }
521 { THIS->lexer_p_->push_note_state(); }
523 { $$=$3; THIS->lexer_p_->pop_state(); }
526 { THIS->lexer_p_->push_lyric_state(); }
528 { $$ = $3; THIS->lexer_p_->pop_state(); }
532 '<' Chord_body '>' { $$ = $2; }
538 $$-> multi_level_i_ = 1;
540 | Chord_body MULTI INT ';' {
541 $$->multi_level_i_=$3;
543 | Chord_body ID STRING STRING ';' {
555 TRANSPOSE steno_melodic_req Music {
567 pre_requests simple_element post_requests {
568 THIS->add_requests((Chord*)$2);//ugh
572 | voice_command ';' { $$ = 0; }
582 $$ = new Request_chord;
583 $$-> set_spot( THIS->here_input());
584 $1-> set_spot( THIS->here_input());
585 ((Chord*)$$) ->add($1);//ugh
592 | verbose_command_req ';' { $$ = $1; }
597 $$ = new Barcheck_req;
599 | COMMAND_IDENTIFIER {
600 $$ = $1->request(true);
606 $$ = new Bar_req(*$2);
609 | METER int '/' int {
610 Meter_change_req *m = new Meter_change_req;
612 // sorry hw, i need meter at output of track,
613 // but don-t know where to get it... statics should go.
614 // HW : default: 4/4, meterchange reqs may change it.
616 Midi_def::num_i_s = $2;
617 Midi_def::den_i_s = $4;
620 | SKIP duration_length {
621 Skip_req * skip_p = new Skip_req;
622 skip_p->duration_.set_plet($2->numerator().as_long(),
623 $2->denominator().as_long());
632 $$ = new Cadenza_req($2);
634 | PARTIAL duration_length {
635 $$ = new Partial_measure_req(*$2);
639 $$ = get_stemdir_req($2);
642 $$ = get_hshift_req($2);
645 $$ = new Clef_change_req(*$2);
649 Key_change_req *key_p= new Key_change_req;
650 key_p->melodic_p_arr_ = *$2;
654 | GROUPING intastint_list {
655 $$ = get_grouping_req(*$2); delete $2;
661 assert(THIS->post_reqs.empty());
663 | post_requests post_request {
664 $2->set_spot( THIS->here_input());
665 THIS->post_reqs.push($2);
671 POST_REQUEST_IDENTIFIER {
672 $$ = (Request*)$1->request(true);
674 |close_request_parens {
675 $$ = THIS->get_parens_request($1);
688 $$ = $1->clone()->musical()->melodic();
689 $$->octave_i_ += THIS->default_octave_i_;
691 | steno_melodic_req POST_QUOTES {
692 $$-> octave_i_ += $2;
694 | PRE_QUOTES steno_melodic_req {
696 $2-> octave_i_ -= $1;
703 * (Melodic_req *) $$ = *$1;
706 | steno_note_req '!' {
707 $$->forceacc_b_ = ! $$->forceacc_b_;
709 /* have to duration here. */
713 MELODIC_REQUEST '{' int int int '}' {/* ugh */
714 $$ = new Melodic_req;
716 $$->notename_i_ = $4;
717 $$->accidental_i_ = $5;
722 ABSDYNAMIC '{' int '}' {
723 Absolute_dynamic_req *ad_p = new Absolute_dynamic_req;
724 ad_p ->loudness_ = (Dynamic_req::Loudness)$3;
727 | SPANDYNAMIC '{' int int '}' {
728 Span_dynamic_req * sp_p = new Span_dynamic_req;
730 sp_p-> dynamic_dir_i_ = $3;
738 THIS->plet_.type_i_ = $4;
739 THIS->plet_.iso_i_ = $2;
743 close_request_parens:
753 | close_plet_parens {
767 THIS->plet_.type_i_ = $4;
768 THIS->plet_.iso_i_ = $2;
789 SCRIPT '{' script_body '}' { $$ = $3; }
793 STRING int int int int int {
794 Script_def *s = new Script_def;
795 s->set_from_input(*$1,$2, $3,$4,$5, $6);
802 script_dir gen_script_def {
803 Musical_script_req *m = new Musical_script_req;
805 m-> scriptdef_p_ = $2;
806 m-> set_spot ( THIS->here_input() );
812 text_def { $$ = $1; }
813 | mudela_script { $$ = $1;
814 $$-> set_spot( THIS->here_input() );
820 Text_def *t = new Text_def;
824 t->style_str_ = THIS->textstyle_str_;
825 $$->set_spot( THIS->here_input() );
830 '^' { $$ = get_scriptdef('^'); }
831 | '+' { $$ = get_scriptdef('+'); }
832 | '-' { $$ = get_scriptdef('-'); }
833 | '|' { $$ = get_scriptdef('|'); }
834 | 'o' { $$ = get_scriptdef('o'); }
835 | '>' { $$ = get_scriptdef('>'); }
837 $$ = get_scriptdef('.');
842 SCRIPT_IDENTIFIER { $$ = $1->script(true); }
843 | script_definition { $$ = $1; }
844 | script_abbreviation {
845 $$ = THIS->lexer_p_->lookup_identifier(*$1)->script(true);
857 | pre_requests pre_request {
858 THIS->pre_reqs.push($2);
859 $2->set_spot( THIS->here_input());
864 open_request_parens {
865 $$ = THIS->get_parens_request($1);
871 THIS->default_duration_.set_plet($2,$4);
873 | DURATIONCOMMAND STRING {
874 THIS->set_duration_mode(*$2);
877 | DURATIONCOMMAND entered_notemode_duration {
878 THIS->set_default_duration($2);
883 This is weird, but default_octave_i_
884 is used in steno_note_req too
886 c' -> default_octave_i_ == 1
888 /* why can't we have \oct{0} iso \oct{c'}*/
889 THIS->default_octave_i_ = 1; }
892 THIS->default_octave_i_ = $3->octave_i_;
896 THIS->textstyle_str_ = *$2;
903 $$ = new Moment(0,1);
905 | duration_length explicit_duration {
912 | dots '.' { $$ ++; }
915 entered_notemode_duration:
917 $$ = new Duration(THIS->default_duration_);
920 $$ = new Duration(THIS->default_duration_);
923 | explicit_duration {
924 THIS->set_last_duration($1);
930 entered_notemode_duration {
932 $$->plet_.type_i_ *= THIS->plet_.type_i_;
933 $$->plet_.iso_i_ *= THIS->plet_.iso_i_;
940 if ( !Duration::duration_type_b($1) )
941 THIS->parser_error("Not a duration");
946 | explicit_duration '.' {
949 | explicit_duration '*' int {
950 $$->plet_.iso_i_ *= $3;
952 | explicit_duration '/' int {
953 $$->plet_.type_i_ *= $3;
959 steno_note_req notemode_duration {
960 if (!THIS->lexer_p_->note_state_b())
961 THIS->parser_error("have to be in Note mode for notes");
962 $1->set_duration (*$2);
963 $$ = THIS->get_note_element($1, $2);
965 | RESTNAME notemode_duration {
966 $$ = THIS->get_rest_element(*$1, $2);
972 text_def notemode_duration {
973 /* this sux! text-def should be feature of lyric-engraver. */
974 if (!THIS->lexer_p_->lyric_state_b())
975 THIS->parser_error("Have to be in Lyric mode for lyrics");
976 $$ = THIS->get_word_element($1, $2);
984 $$ = new Array<Melodic_req*>;
986 | pitch_list NOTENAME_ID {
987 $$->push($2->clone()->musical()->melodic());
1013 real unit { $$ = $1*$2; }
1017 unit: CM_T { $$ = 1 CM; }
1018 |IN_T { $$ = 1 INCH; }
1019 |MM_T { $$ = 1 MM; }
1020 |PT_T { $$ = 1 PT; }
1027 SYMBOLTABLES '{' symtables_body '}' { $$ = $3; }
1035 $$ = $1->lookup(true);
1037 | symtables_body TEXID STRING {
1038 $$->texsetting = *$3;
1041 | symtables_body STRING '=' symtable {
1048 TABLE '{' symtable_body '}' { $$ = $3; }
1052 { $$ = new Symtable; }
1053 | symtable_body STRING symboldef {
1062 $$ = new Symbol(*$1, *$2);
1067 Box b(Interval(0,0), Interval(0,0));
1068 $$ = new Symbol(*$1, b);
1074 dinterval dinterval {
1075 $$ = new Box(*$1, *$2);
1081 dinterval: dim dim {
1082 $$ = new Interval($1, $2);
1089 My_lily_parser::set_yydebug(bool b )
1096 My_lily_parser::do_yyparse()
1098 yyparse((void*)this);
1102 My_lily_parser::default_paper()
1104 Identifier *id = lexer_p_->lookup_identifier( "default_paper" );
1105 return id ? id->paperdef(true) : new Paper_def ;
1109 My_lily_parser::default_midi()
1111 Identifier *id = lexer_p_->lookup_identifier( "default_midi" );
1112 return id ? id->mididef(true) : new Midi_def ;