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.0.61"
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-engraver.hh"
35 #include "input-performer.hh"
37 #include "music-list.hh"
43 #define YYERROR_VERBOSE 1
45 #define YYPARSE_PARAM my_lily_parser_l
46 #define YYLEX_PARAM my_lily_parser_l
47 #define THIS ((My_lily_parser *) my_lily_parser_l)
49 #define yyerror THIS->parser_error
55 Array<Melodic_req*> *melreqvec;/* should clean up naming */
56 Array<String> * strvec;
62 Input_engraver * igravs;
63 Input_performer * iperfs;
65 Music_list *musiclist;
76 General_script_def * script;
80 Symtables * symtables;
90 yylex(YYSTYPE *s, void * v_l)
92 My_lily_parser *pars_l = (My_lily_parser*) v_l;
93 My_lily_lexer * lex_l = pars_l->lexer_p_;
95 lex_l->lexval_l = (void*) s;
96 return lex_l->yylex();
104 /* tokens which are not keywords */
116 %token DURATIONCOMMAND
122 %token REQUESTENGRAVER
123 %token REQUESTPERFORMER
131 %token MELODIC_REQUEST
163 %token E_EXCLAMATION E_SMALLER E_BIGGER E_CHAR
167 %token <melreq> NOTENAME_ID
168 %token <id> IDENTIFIER
169 %token <id> MELODIC_REQUEST_IDENTIFIER
170 %token <id> MUSIC_IDENTIFIER
171 %token <id> VOICE_IDENTIFIER
172 %token <id> POST_REQUEST_IDENTIFIER
173 %token <id> SCRIPT_IDENTIFIER
174 %token <id> STAFF_IDENTIFIER
175 %token <id> REAL_IDENTIFIER
176 %token <id> INT_IDENTIFIER
177 %token <id> SCORE_IDENTIFIER
178 %token <id> MIDI_IDENTIFIER
179 %token <id> PAPER_IDENTIFIER
180 %token <id> REQUEST_IDENTIFIER
182 %token <string> DURATION RESTNAME
183 %token <string> STRING
184 %token <i> POST_QUOTES
185 %token <i> PRE_QUOTES
189 %type <c> open_request_parens close_request_parens
190 %type <c> open_plet_parens close_plet_parens
191 %type <music> simple_element music_elt full_element lyrics_elt command_elt
194 %type <id> declaration
195 %type <duration> explicit_duration notemode_duration
196 %type <interval> dinterval
197 %type <intvec> intastint_list
198 %type <lookup> symtables symtables_body
199 %type <melreq> melodic_request steno_melodic_req
200 %type <notereq> steno_note_req
201 %type <melreqvec> pitch_list
202 %type <midi> midi_block midi_body
203 %type <moment> duration_length
205 %type <music> Music transposed_music
206 %type <musiclist> Voice Voice_body
207 %type <chord> Chord Chord_body
208 %type <paper> paper_block paper_body
209 %type <real> dim real
211 %type <request> post_request pre_request command_req verbose_command_req abbrev_command_req
212 %type <request> script_req dynamic_req
213 %type <score> score_block score_body
214 %type <script> script_definition script_body mudela_script gen_script_def
215 %type <textdef> text_def
216 %type <string> declarable_identifier
217 %type <string> script_abbreviation
218 %type <id> old_identifier
219 %type <symbol> symboldef
220 %type <symtable> symtable symtable_body
221 %type <igravs> input_engraver_spec input_engraver_spec_body
222 %type <iperfs> input_performer_spec input_performer_spec_body
229 | mudela score_block {
232 | mudela add_declaration { }
234 | mudela check_version { }
235 | mudela add_notenames { }
240 if (*$2 != MUDELA_VERSION) {
241 if (THIS->ignore_version_b_) {
242 THIS->here_input().error("Incorrect mudela version");
244 THIS->fatal_error_i_ = 1;
245 THIS->parser_error("Incorrect mudela version");
252 NOTENAMES '{' notenames_body '}'
257 | notenames_body CLEAR {
258 THIS->clear_notenames();
260 | notenames_body STRING '=' melodic_request {
261 THIS->add_notename(*$2, $4);
268 add_declaration: declaration {
269 THIS->lexer_p_->add_identifier($1);
270 $1->init_b_ = THIS->init_parse_b_;
271 $1->set_spot(THIS->pop_spot());
275 declarable_identifier:
277 THIS->remember_spot();
281 THIS->remember_spot();
282 $$ = new String($1->name_str_);
283 THIS->here_input().warning("redeclaration of `" + *$$ + "'");
290 | MELODIC_REQUEST_IDENTIFIER
291 | POST_REQUEST_IDENTIFIER
299 declarable_identifier '=' score_block {
300 $$ = new Score_id(*$1, $3, SCORE_IDENTIFIER);
303 | declarable_identifier '=' paper_block {
304 $$ = new Paper_def_id(*$1, $3, PAPER_IDENTIFIER);
307 | declarable_identifier '=' midi_block {
308 $$ = new Midi_def_id(*$1, $3, MIDI_IDENTIFIER);
311 | declarable_identifier '=' script_definition {
312 $$ = new Script_id(*$1, $3, SCRIPT_IDENTIFIER);
315 | declarable_identifier '=' Music {
316 $$ = new Music_id(*$1, $3, MUSIC_IDENTIFIER);
319 | declarable_identifier '=' symtables {
320 $$ = new Lookup_id(*$1, $3, IDENTIFIER);
323 | declarable_identifier '=' real {
324 $$ = new Real_id(*$1, new Real($3), REAL_IDENTIFIER);
327 | declarable_identifier '=' int {
328 $$ = new Int_id(*$1, new int($3), INT_IDENTIFIER);
331 | declarable_identifier '=' post_request {
332 $$ = new Request_id(*$1, $3, POST_REQUEST_IDENTIFIER);
335 | declarable_identifier '=' melodic_request {
336 $$ = new Request_id(*$1, $3, MELODIC_REQUEST_IDENTIFIER);
344 REQUESTENGRAVER '{' input_engraver_spec_body '}'
348 input_engraver_spec_body:
350 $$ = new Input_engraver;
352 $$->set_spot ( THIS->here_input() );
355 | input_engraver_spec_body ALIAS STRING ';' {
356 $$-> alias_str_arr_.push(*$3);
359 | input_engraver_spec_body CONSISTS STRING ';' {
360 $$-> consists_str_arr_.push(*$3);
363 | input_engraver_spec_body CONTAINS input_engraver_spec {
368 input_performer_spec:
369 REQUESTPERFORMER '{' input_performer_spec_body '}'
373 input_performer_spec_body:
375 $$ = new Input_performer;
377 $$->set_spot ( THIS->here_input() );
380 | input_performer_spec_body ALIAS STRING ';' {
381 $$-> alias_str_arr_.push(*$3);
384 | input_performer_spec_body CONSISTS STRING ';' {
385 $$-> consists_str_arr_.push(*$3);
388 | input_performer_spec_body CONTAINS input_performer_spec {
397 SCORE { THIS->remember_spot(); }
398 /*cont*/ '{' score_body '}' {
400 $$->set_spot(THIS->pop_spot());
401 if (!$$->paper_p_ && ! $$->midi_p_)
402 $$->paper_p_ = THIS->default_paper();
404 /* handle error levels. */
405 $$->errorlevel_i_ = THIS->error_level_i_;
406 THIS->error_level_i_ = 0;
414 $$ = $1->score(true);
419 | score_body paper_block {
422 | score_body midi_block {
431 /* */ { $$ =new Array<int>; }
432 | intastint_list int '*' int {
433 $$->push($2); $$->push($4);
443 '{' paper_body '}' { $$ = $3; }
448 $$ = THIS->default_paper(); // paper / video / engrave
450 | paper_body OUTPUT STRING ';' { $$->outfile_str_ = *$3;
453 | paper_body symtables { $$->set($2); }
454 | paper_body STRING '=' dim ';' {
455 $$->set_var(*$2, $4);
457 | paper_body STRING '=' REAL ';' {
458 $$->set_var(*$2, $4);
460 | paper_body input_engraver_spec {
474 '{' midi_body '}' { $$ = $3; }
477 midi_body: /* empty */ {
478 $$ = THIS->default_midi(); // midi / audio / perform
480 | midi_body OUTPUT STRING ';' {
481 $$->outfile_str_ = *$3;
484 | midi_body TEMPO notemode_duration ':' int ';' {
485 $$->set_tempo( $3->length(), $5 );
487 | midi_body input_performer_spec {
509 | Voice_body ID STRING STRING ';' {
522 full_element { $$ = $1; }
525 | transposed_music { $$ = $1; }
526 | MUSIC_IDENTIFIER { $$ = $1->music(true); }
528 { THIS->lexer_p_->push_note_state(); }
530 { $$=$3; THIS->lexer_p_->pop_state(); }
533 { THIS->lexer_p_->push_lyric_state(); }
535 { $$ = $3; THIS->lexer_p_->pop_state(); }
539 '<' Chord_body '>' { $$ = $2; }
545 $$-> multi_level_i_ = 1;
547 | Chord_body MULTI INT ';' {
548 $$->multi_level_i_=$3;
550 | Chord_body ID STRING STRING ';' {
562 TRANSPOSE steno_melodic_req Music {
574 pre_requests simple_element post_requests {
575 THIS->add_requests((Chord*)$2);//ugh
578 | voice_command ';' { $$ = 0; }
589 $$ = new Voice_element;
590 $$-> set_spot( THIS->here_input());
594 $2-> set_spot( THIS->here_input());
595 ((Chord*)$$) ->add($2);//ugh
598 | GROUP STRING ';' { // ugh ugh ugh
599 Change_reg *chr_p = new Change_reg;
601 chr_p-> type_str_ = "Voice_group_engravers"; //ugh
602 chr_p-> id_str_ = *$2;
609 | verbose_command_req ';' { $$ = $1; }
614 $$ = new Barcheck_req;
620 $$ = new Bar_req(*$2);
623 | METER int '/' int {
624 Meter_change_req *m = new Meter_change_req;
626 // sorry hw, i need meter at output of track,
627 // but don-t know where to get it... statics should go.
628 // HW : default: 4/4, meterchange reqs may change it.
630 Midi_def::num_i_s = $2;
631 Midi_def::den_i_s = $4;
634 | SKIP duration_length {
635 Skip_req * skip_p = new Skip_req;
636 skip_p->duration_ = Duration(1,0);
637 skip_p->duration_.set_plet($2->numerator().as_long(),
638 $2->denominator().as_long());
644 $$ = new Cadenza_req($2);
646 | PARTIAL duration_length {
647 $$ = new Partial_measure_req(*$2);
651 $$ = get_stemdir_req($2);
654 $$ = get_hshift_req($2);
657 $$ = new Clef_change_req(*$2);
661 Key_change_req *key_p= new Key_change_req;
662 key_p->melodic_p_arr_ = *$2;
666 | GROUPING intastint_list {
667 $$ = get_grouping_req(*$2); delete $2;
674 assert(THIS->post_reqs.empty());
676 | post_requests post_request {
677 $2->set_spot( THIS->here_input());
678 THIS->post_reqs.push($2);
684 POST_REQUEST_IDENTIFIER {
685 $$ = (Request*)$1->request(true);
687 |close_request_parens {
688 $$ = THIS->get_parens_request($1);
701 $$ = $1->clone()->musical()->melodic();
702 $$->octave_i_ += THIS->default_octave_i_;
704 | steno_melodic_req POST_QUOTES {
705 $$-> octave_i_ += $2;
707 | PRE_QUOTES steno_melodic_req {
709 $2-> octave_i_ -= $1;
716 * (Melodic_req *) $$ = *$1;
719 | steno_note_req '!' {
720 $$->forceacc_b_ = ! $$->forceacc_b_;
722 /* have to duration here. */
726 MELODIC_REQUEST '{' int int int '}' {/* ugh */
727 $$ = new Melodic_req;
729 $$->notename_i_ = $4;
730 $$->accidental_i_ = $5;
735 ABSDYNAMIC '{' int '}' {
736 Absolute_dynamic_req *ad_p = new Absolute_dynamic_req;
737 ad_p ->loudness_ = (Dynamic_req::Loudness)$3;
740 | SPANDYNAMIC '{' int int '}' {
741 Span_dynamic_req * sp_p = new Span_dynamic_req;
743 sp_p-> dynamic_dir_i_ = $3;
751 THIS->default_duration_.set_plet($2,$4);
755 close_request_parens:
765 | close_plet_parens {
779 THIS->default_duration_.set_plet($2,$4);
800 SCRIPT '{' script_body '}' { $$ = $3; }
804 STRING int int int int int {
805 Script_def *s = new Script_def;
806 s->set_from_input(*$1,$2, $3,$4,$5, $6);
813 script_dir gen_script_def {
814 Musical_script_req *m = new Musical_script_req;
816 m-> scriptdef_p_ = $2;
817 m-> set_spot ( THIS->here_input() );
823 text_def { $$ = $1; }
824 | mudela_script { $$ = $1;
825 $$-> set_spot( THIS->here_input() );
831 Text_def *t = new Text_def;
835 t->style_str_ = THIS->textstyle_str_;
836 $$->set_spot( THIS->here_input() );
841 '^' { $$ = get_scriptdef('^'); }
842 | '+' { $$ = get_scriptdef('+'); }
843 | '-' { $$ = get_scriptdef('-'); }
844 | '|' { $$ = get_scriptdef('|'); }
845 | 'o' { $$ = get_scriptdef('o'); }
846 | '>' { $$ = get_scriptdef('>'); }
848 $$ = get_scriptdef('.');
853 SCRIPT_IDENTIFIER { $$ = $1->script(true); }
854 | script_definition { $$ = $1; }
855 | script_abbreviation {
856 $$ = THIS->lexer_p_->lookup_identifier(*$1)->script(true);
868 | pre_requests pre_request {
869 THIS->pre_reqs.push($2);
870 $2->set_spot( THIS->here_input());
875 open_request_parens {
876 $$ = THIS->get_parens_request($1);
882 THIS->default_duration_.set_plet($2,$4);
884 | DURATIONCOMMAND STRING {
885 THIS->set_duration_mode(*$2);
888 | DURATIONCOMMAND notemode_duration {
889 THIS->set_default_duration($2);
894 This is weird, but default_octave_i_
895 is used in steno_note_req too
897 c' -> default_octave_i_ == 1
899 /* why can't we have \oct{0} iso \oct{c'}*/
900 THIS->default_octave_i_ = 1; }
903 THIS->default_octave_i_ = $3->octave_i_;
907 THIS->textstyle_str_ = *$2;
914 $$ = new Moment(0,1);
916 | duration_length explicit_duration {
923 | dots '.' { $$ ++; }
928 $$ = new Duration(THIS->default_duration_);
931 $$ = new Duration(THIS->default_duration_);
934 | explicit_duration {
935 THIS->set_last_duration($1);
943 if ( !Duration::duration_type_b($1) )
944 THIS->parser_error("Not a duration");
947 $$->set_plet(THIS->default_duration_);
950 | explicit_duration '.' {
953 | explicit_duration '*' int {
954 $$->plet_.iso_i_ *= $3;
956 | explicit_duration '/' int {
957 $$->plet_.type_i_ *= $3;
963 steno_note_req notemode_duration {
964 if (!THIS->lexer_p_->note_state_b())
965 THIS->parser_error("have to be in Note mode for notes");
966 $1->set_duration (*$2);
967 $$ = THIS->get_note_element($1, $2);
969 | RESTNAME notemode_duration {
970 $$ = THIS->get_rest_element(*$1, $2);
976 text_def notemode_duration {
977 if (!THIS->lexer_p_->lyric_state_b())
978 THIS->parser_error("Have to be in Lyric mode for lyrics");
979 $$ = THIS->get_word_element($1, $2);
987 $$ = new Array<Melodic_req*>;
989 | pitch_list NOTENAME_ID {
990 $$->push($2->clone()->musical()->melodic());
1016 real unit { $$ = $1*$2; }
1020 unit: CM_T { $$ = 1 CM; }
1021 |IN_T { $$ = 1 INCH; }
1022 |MM_T { $$ = 1 MM; }
1023 |PT_T { $$ = 1 PT; }
1030 SYMBOLTABLES '{' symtables_body '}' { $$ = $3; }
1038 $$ = $1->lookup(true);
1040 | symtables_body TEXID STRING {
1041 $$->texsetting = *$3;
1044 | symtables_body STRING '=' symtable {
1051 TABLE '{' symtable_body '}' { $$ = $3; }
1055 { $$ = new Symtable; }
1056 | symtable_body STRING symboldef {
1065 $$ = new Symbol(*$1, *$2);
1070 Box b(Interval(0,0), Interval(0,0));
1071 $$ = new Symbol(*$1, b);
1077 dinterval dinterval {
1078 $$ = new Box(*$1, *$2);
1084 dinterval: dim dim {
1085 $$ = new Interval($1, $2);
1092 My_lily_parser::set_yydebug(bool b )
1099 My_lily_parser::do_yyparse()
1101 yyparse((void*)this);
1105 My_lily_parser::default_paper()
1107 Identifier *id = lexer_p_->lookup_identifier( "default_paper" );
1108 return id ? id->paperdef(true) : new Paper_def ;
1112 My_lily_parser::default_midi()
1114 Identifier *id = lexer_p_->lookup_identifier( "default_midi" );
1115 return id ? id->mididef(true) : new Midi_def ;