lilypond-0.0.40
[lilypond.git] / lily / parser.y
blobebec63fbefe15feddea069cc597865d552392508
1 %{ // -*-Fundamental-*-
2 #include <iostream.h>
4 #include "lookup.hh"
5 #include "misc.hh"
6 #include "lexer.hh"
7 #include "paper-def.hh"
8 #include "midi-def.hh"
9 #include "input-score.hh"
10 #include "main.hh"
11 #include "keyword.hh"
12 #include "debug.hh"
13 #include "parseconstruct.hh"
14 #include "dimen.hh"
15 #include "identifier.hh"
16 #include "commandrequest.hh"
17 #include "musicalrequest.hh"
18 #include "voice-element.hh"
20 #ifndef NDEBUG
21 #define YYDEBUG 1
22 #endif
24 Array<Request*> pre_reqs, post_reqs;
25 Array<const char *> define_spots;
26 Paper_def*default_paper();
27 char const* defined_ch_c_l;
28 char const* req_defined_ch_c_l;
29 int fatal_error_i = 0;
34 %union {
35 Request * request;
36 Real real;
37 Identifier *id;
38 Voice *voice;
39 Voice_element *el;
40 String *string;
41 const char *consstr;
42 Paper_def *paper;
43 Midi_def* midi;
44 Input_music *music;
45 Music_general_chord *chord;
46 Music_voice *mvoice;
47 int i;
48 char c;
49 int ii[10];
50 Moment *moment;
52 Array<String> * strvec;
53 Array<int> *intvec;
54 Array<Melodic_req*> *melreqvec;
55 Input_staff *staff;
56 Input_score *score;
57 Symtables * symtables;
58 Symtable * symtable;
59 Symbol * symbol;
60 Lookup*lookup;
61 Interval *interval;
62 Box *box;
63 Notename_tab *notename_tab;
64 Script_def * script;
65 Text_def * textdef;
68 %token VOICE STAFF SCORE TITLE BAR OUTPUT MULTIVOICE DYNAMIC
69 %token CM_T IN_T PT_T MM_T PAPER WIDTH METER UNITSPACE SKIP COMMANDS COMMAND
70 %token GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
71 %token KEY CLEF TABLE VOICES STEM
72 %token PARTIAL MUSIC GROUPING CADENZA
73 %token END SYMBOLTABLES TEXID TABLE NOTENAMES SCRIPT TEXTSTYLE PLET
74 %token GOTO
75 %token MIDI TEMPO
77 %token <id> IDENTIFIER REAL_IDENTIFIER REQUEST_IDENTIFIER
78 %token <string> PITCHMOD DURATION RESTNAME
79 %token <ii> NOTENAME
80 %token <real> REAL
81 %token <string> STRING
83 %token <i> DOTS INT
84 %type <real> unit
85 %type <melreqvec> pitch_list
86 %type <c> open_request_parens close_request_parens close_plet_parens
87 %type <id> declaration
88 %type <string> declarable_identifier
89 %type <paper> paper_block paper_body
90 %type <midi> midi_block midi_body
91 %type <real> dim real
92 %type <ii> default_duration explicit_duration notemode_duration mudela_duration
93 %type <ii> notename
94 %type <moment> duration_length
95 %type <el> voice_elt full_element lyrics_elt command_elt
97 %type <score> score_block score_body
98 %type <staff> staff_block staff_init staff_body
99 %type <i> int
100 %type <intvec> intastint_list
101 %type <request> post_request pre_request command_req
102 %type <string> pitchmod
103 %type <music> music
104 %type <chord> music_chord music_chord_body
106 %type <mvoice> music_voice_body music_voice
108 %type <interval> dinterval
109 %type <box> box
110 %type <symtable> symtable symtable_body
111 %type <lookup> symtables symtables_body
112 %type <symbol> symboldef
113 %type <notename_tab> notename_tab notename_tab_body
114 %type <i> script_dir
115 %type <script> script_definition script_body mudela_script
116 %type <request> script_req textscript_req dynamic_req basic_request
117 %type <textdef> mudela_text
122 mudela: /* empty */
123 | mudela score_block {
124 add_score($2);
126 | mudela add_declaration { }
127 | mudela mudela_command {}
130 mudela_command:
131 notename_tab { lexer->set($1); }
135 DECLARATIONS
137 add_declaration: declaration {
138 lexer->add_identifier($1);
142 declarable_identifier:
143 STRING { $$ = $1; }
144 | IDENTIFIER { $$ = new String($1->name); }
147 declaration:
148 declarable_identifier '=' staff_block {
149 $$ = new Staff_id(*$1, $3, IDENTIFIER);
150 delete $1;
152 | declarable_identifier '=' music_voice {
153 $$ = new M_voice_id(*$1, $3, IDENTIFIER);
154 delete $1;
156 | declarable_identifier '=' script_definition {
157 $$ = new Script_id(*$1, $3, IDENTIFIER);
158 delete $1;
160 | declarable_identifier '=' music_chord {
161 $$ = new M_chord_id(*$1, $3, IDENTIFIER);
162 delete $1;
164 | declarable_identifier '=' symtables {
165 $$ = new Lookup_id(*$1, $3, IDENTIFIER);
166 delete $1;
168 | declarable_identifier '=' notename_tab {
169 $$ = new Notetab_id(*$1, $3, IDENTIFIER);
170 delete $1;
172 | declarable_identifier '=' real {
173 $$ = new Real_id(*$1, new Real($3), REAL_IDENTIFIER);
174 delete $1;
176 | declarable_identifier error '}' {
179 | declarable_identifier '=' basic_request {
180 $$ = new Request_id(*$1, $3, REQUEST_IDENTIFIER);
181 delete $1;
185 notename_tab:
186 NOTENAMES '{' notename_tab_body '}' { $$ = $3; }
189 notename_tab_body: {
190 $$ = new Notename_tab;
192 | IDENTIFIER {
193 $$ = $1->notename_tab(true);
195 | notename_tab_body STRING int int {
196 $$->set($3, $4, *$2);
197 delete $2;
202 SCORE
204 score_block:
205 SCORE { define_spots.push(lexer->here_ch_c_l()); }
206 /*cont*/ '{' score_body '}' {
207 $$ = $4;
208 $$->defined_ch_c_l_ = define_spots.pop();
209 if (!$$->paper_p_ && ! $$->midi_p_)
210 $$->paper_p_ = default_paper();
212 /* handle error levels. */
213 $$->errorlevel_i_ = lexer->errorlevel_i_;
214 lexer->errorlevel_i_ = 0;
218 score_body: {
219 $$ = new Input_score;
221 | score_body staff_block { $$->add($2); }
222 | score_body COMMANDS '{' music_voice_body '}' {
223 $$->set($4);
225 | score_body paper_block { $$->set($2); }
226 | score_body midi_block { $$->set($2); }
227 | score_body error {
232 intastint_list:
233 /* */ { $$ =new Array<int>; }
234 | intastint_list int '*' int {
235 $$->push($2); $$->push($4);
241 PAPER
243 paper_block:
244 PAPER
246 '{' paper_body '}' { $$ = $3; }
249 paper_body:
250 /* empty */ {
251 $$ = default_paper();
253 | paper_body WIDTH dim { $$->linewidth = $3;}
254 | paper_body OUTPUT STRING { $$->outfile = *$3;
255 delete $3;
257 | paper_body symtables { $$->set($2); }
258 | paper_body UNITSPACE dim { $$->whole_width = $3; }
259 | paper_body GEOMETRIC REAL { $$->geometric_ = $3; }
260 | paper_body error {
266 MIDI
268 midi_block:
269 MIDI
271 '{' midi_body '}' { $$ = $3; }
274 midi_body: {
275 $$ = new Midi_def;
277 | midi_body OUTPUT STRING {
278 $$->outfile_str_ = *$3;
279 delete $3;
281 | midi_body TEMPO mudela_duration ':' int {
282 $$->set_tempo( wholes( $3[0], $3[1] ), $5 );
284 | midi_body error {
290 STAFFs
292 staff_block:
293 STAFF { define_spots.push(lexer->here_ch_c_l()); }
294 /*cont*/ '{' staff_body '}' {
295 $$ = $4;
296 $$-> defined_ch_c_l_ = define_spots.pop();
302 staff_init:
303 IDENTIFIER { $$ = $1->staff(true); }
304 | STRING {
305 $$ = new Input_staff(*$1);
306 delete $1;
310 staff_body:
311 staff_init
312 | staff_body COMMANDS '{' music_voice_body '}' {
313 $$->set_score_wide($4);
315 | staff_body music {
316 $2->set_default_group( "staff_music" + String($$->music_.size()));
317 $$->add($2);
319 | staff_body error {
324 MUSIC
326 music:
327 music_voice { $$ = $1; }
328 | music_chord { $$ = $1; }
331 music_voice: MUSIC '{' music_voice_body '}' { $$ = $3; }
334 music_voice_body:
335 IDENTIFIER {
336 $$ = $1->mvoice(true);
338 | /* */ {
339 $$ = new Music_voice;
341 | music_voice_body '+' IDENTIFIER {
342 $$->concatenate($3->mvoice(true));
344 | music_voice_body full_element {
345 $$->add_elt($2);
347 | music_voice_body voice_command {
349 | music_voice_body music {
350 $$->add($2);
352 | music_voice_body error {
356 music_chord: '{' music_chord_body '}' { $$ = $2; }
359 music_chord_body:
360 IDENTIFIER {
361 $$=$1->mchord(true);
363 | /* */ {
364 $$ = new Voice_group_chord;
366 | MULTIVOICE {
367 $$ = new Multi_voice_chord;
369 | music_chord_body '+' IDENTIFIER {
370 $$->concatenate($3->mchord(true));
372 | music_chord_body music {
373 $$->add($2);
375 | music_chord_body full_element {
376 $$ ->add_elt($2);
378 | music_chord_body error {
382 basic_request:
383 command_req
384 | pre_request
385 | post_request
389 VOICE ELEMENTS
391 full_element: pre_requests voice_elt post_requests {
392 add_requests($2, pre_reqs);
393 add_requests($2, post_reqs);
394 $$ = $2;
396 | pre_requests lyrics_elt post_requests {
397 add_requests($2, pre_reqs);
398 add_requests($2, post_reqs);
399 $$ = $2;
401 | command_elt
404 command_elt:
405 /* empty */ {
406 $$ = new Voice_element;
407 $$-> defined_ch_c_l_ = lexer->here_ch_c_l();
409 /* cont: */
410 command_req {
411 $2-> defined_ch_c_l_ = $$->defined_ch_c_l_;
412 $$->add($2);
417 command_req:
418 '|' {
419 $$ = new Barcheck_req;
421 | BAR STRING {
422 $$ = new Bar_req(*$2);
423 delete $2;
425 | METER '{' int '*' int '}' {
426 Meter_change_req *m = new Meter_change_req;
427 m->set($3,$5);
428 $$ = m;
430 | SKIP '{' duration_length '}' {
431 Skip_req * skip_p = new Skip_req;
432 skip_p->duration_ = *$3;
433 delete $3;
434 $$ = skip_p;
436 | CADENZA '{' int '}' {
437 $$ = new Cadenza_req($3);
439 | PARTIAL '{' duration_length '}' {
440 $$ = new Partial_measure_req(*$3);
441 delete $3;
443 | STEM '{' int '}' {
444 $$ = get_stemdir_req($3);
446 | CLEF STRING {
447 $$ = new Clef_change_req(*$2);
448 delete $2;
450 | KEY '{' pitch_list '}' {
451 Key_change_req *key_p= new Key_change_req;
452 key_p->melodic_p_arr_ = *$3;
453 $$ = key_p;
454 delete $3;
456 | GROUPING '{' intastint_list '}' {
457 $$ = get_grouping_req(*$3); delete $3;
461 post_requests:
463 assert(post_reqs.empty());
465 | post_requests post_request {
466 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
467 post_reqs.push($2);
469 | post_requests close_plet_parens INT '/' INT {
470 post_reqs.push( get_request($2) );
471 req_defined_ch_c_l = lexer->here_ch_c_l();
472 post_reqs.push( get_plet_request( $2, $3, $5 ) );
476 post_request:
477 close_request_parens {
478 $$ = get_request($1);
480 | script_req
481 | textscript_req
482 | dynamic_req
483 | REQUEST_IDENTIFIER {
484 $$ = $1->request(false)->clone();
488 dynamic_req:
489 DYNAMIC '{' int '}' {
490 Absolute_dynamic_req *ad_p = new Absolute_dynamic_req;
491 ad_p ->loudness_ = $3;
492 $$ =ad_p;
496 close_plet_parens:
497 ']' {
498 req_defined_ch_c_l = lexer->here_ch_c_l();
499 $$ = ']';
503 close_request_parens:
504 '(' {
505 $$='(';
507 | ']' {
508 $$ = ']';
512 open_request_parens:
513 ')' {
514 $$=')';
516 | '[' {
517 $$='[';
521 script_definition:
522 SCRIPT '{' script_body '}' { $$ = $3; }
525 script_body:
526 STRING int int int {
527 $$ = new Script_def(*$1,$2, $3,$4);
528 delete $1;
532 textscript_req:
533 script_dir mudela_text { $$ = get_text_req($1,$2); }
536 mudela_text:
537 STRING {
538 defined_ch_c_l = lexer->here_ch_c_l();
539 $$ = get_text(*$1);
540 delete $1;
544 script_req:
545 script_dir mudela_script {
546 $$ = get_script_req($1, $2);
550 mudela_script:
551 IDENTIFIER { $$ = $1->script(true); }
552 | script_definition { $$ = $1; }
553 | '^' { $$ = get_scriptdef('^'); }
554 | '+' { $$ = get_scriptdef('+'); }
555 | '-' { $$ = get_scriptdef('-'); }
556 | '|' { $$ = get_scriptdef('|'); }
557 | 'o' { $$ = get_scriptdef('o'); }
558 | '>' { $$ = get_scriptdef('>'); }
559 | '.' { $$ = get_scriptdef('.'); }
560 | DOTS {
561 if ( $1 > 1 )
562 warning( "too many staccato dots", lexer->here_ch_c_l() );
563 $$ = get_scriptdef('.');
565 | error {
566 $$ = get_scriptdef('.');
567 yyerrok;
571 script_dir:
572 '_' { $$ = -1; }
573 |'^' { $$ = 1; }
574 |'-' { $$ = 0; }
577 pre_requests:
578 | pre_requests pre_request {
579 pre_reqs.push($2);
580 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
584 pre_request:
585 open_request_parens {
586 defined_ch_c_l = lexer->here_ch_c_l();
587 $$ = get_request($1);
591 voice_command:
592 PLET '{' INT '/' INT '}' {
593 set_plet($3,$5);
595 | DURATIONCOMMAND '{' STRING '}' {
596 set_duration_mode(*$3);
597 delete $3;
599 | DURATIONCOMMAND '{' notemode_duration '}' {
600 set_default_duration($3);
602 | OCTAVECOMMAND '{' pitchmod '}' {
603 set_default_octave(*$3);
604 delete $3;
606 | TEXTSTYLE STRING {
607 set_text_style(*$2);
608 delete $2;
612 duration_length:
613 mudela_duration {
614 $$ = new Moment(wholes($1[0], $1[1]));
616 |int '*' mudela_duration {
617 $$ = new Moment(Rational($1) * wholes($3[0], $3[1]));
621 notemode_duration:
622 explicit_duration
623 | default_duration
626 mudela_duration:
627 int {
628 $$[0] = $1;
629 $$[1] = 0;
631 | int DOTS {
632 $$[0] = $1;
633 $$[1] = $2;
638 explicit_duration:
639 INT {
640 last_duration($1);
641 $$[0] = $1;
642 $$[1] = 0;
644 | INT DOTS {
645 last_duration($1);
646 $$[0] = $1;
647 $$[1] = $2;
649 | DOTS {
650 get_default_duration($$);
651 $$[1] = $1;
653 | INT '*' INT '/' INT {
654 // ugh, must use Duration
655 set_plet( $3, $5 );
656 $$[ 0 ] = $1;
657 $$[ 1 ] = 0;
658 set_plet( 1, 1 );
662 default_duration:
664 get_default_duration($$);
668 pitchmod: {
669 defined_ch_c_l = lexer->here_ch_c_l();
670 $$ = new String;
672 | PITCHMOD {
673 defined_ch_c_l = lexer->here_ch_c_l();
674 $$ = $1;
678 notename:
679 NOTENAME
682 voice_elt:
683 pitchmod notename notemode_duration {
684 $$ = get_note_element(*$1, $2, $3);
685 delete $1;
687 | RESTNAME notemode_duration {
688 $$ = get_rest_element(*$1, $2);
689 delete $1;
694 lyrics_elt:
695 mudela_text notemode_duration {
696 $$ = get_word_element($1, $2);
700 UTILITIES
702 pitch_list: {
703 $$ = new Array<Melodic_req*>;
705 | pitch_list NOTENAME {
706 Melodic_req *m_p = new Melodic_req;
707 m_p->notename_i_ = $2[0];
708 m_p->accidental_i_ = $2[1];
709 $$->push(m_p);
713 int:
714 real {
715 $$ = int($1);
716 if ( distance($1,Real(int($$)) ) > 1e-8)
717 error( "integer expected", lexer->here_ch_c_l() );
721 real:
722 INT {
723 $$ = Real($1);
725 | REAL {
726 $$ = $1;
728 | REAL_IDENTIFIER {
729 $$ = * $1->real(0);
735 dim:
736 real unit { $$ = $1*$2; }
740 unit: CM_T { $$ = 1 CM; }
741 |IN_T { $$ = 1 INCH; }
742 |MM_T { $$ = 1 MM; }
743 |PT_T { $$ = 1 PT; }
747 symbol tables
749 symtables:
750 SYMBOLTABLES '{' symtables_body '}' { $$ = $3; }
753 symtables_body:
755 $$ = new Lookup;
757 | IDENTIFIER {
758 $$ = new Lookup(*$1->lookup(true));
760 | symtables_body TEXID STRING {
761 $$->texsetting = *$3;
762 delete $3;
764 | symtables_body STRING '=' symtable {
765 $$->add(*$2, $4);
766 delete $2;
770 symtable:
771 TABLE '{' symtable_body '}' { $$ = $3; }
774 symtable_body:
775 { $$ = new Symtable; }
776 | symtable_body STRING symboldef {
777 $$->add(*$2, *$3);
778 delete $2;
779 delete $3;
783 symboldef:
784 STRING box {
785 $$ = new Symbol(*$1, *$2);
786 delete $1;
787 delete $2;
789 | STRING {
790 Box b;
791 $$ = new Symbol(*$1, b);
792 delete $1;
796 box:
797 dinterval dinterval {
798 $$ = new Box(*$1, *$2);
799 delete $1;
800 delete $2;
804 dinterval: dim dim {
805 $$ = new Interval($1, $2);
811 void
812 yyerror(const char *s)
814 lexer->LexerError(s);
816 if ( fatal_error_i )
817 exit( fatal_error_i );
820 void
821 parse_file(String init, String s)
823 *mlog << "Parsing ... ";
824 lexer = new My_flex_lexer;
826 #ifdef YYDEBUG
827 yydebug = !monitor->silence("InitParser") && check_debug;
828 lexer->set_debug( !monitor->silence("InitLexer") && check_debug);
829 #endif
831 lexer->new_input(init);
832 yyparse();
834 #ifdef YYDEBUG
835 yydebug = !monitor->silence("Parser") && check_debug;
836 lexer->set_debug( !monitor->silence("Lexer") && check_debug);
837 #endif
839 lexer->new_input(s);
840 yyparse();
841 delete lexer;
842 lexer = 0;
844 if(!define_spots.empty())
845 warning("Braces don't match.",0);
848 Paper_def*
849 default_paper()
851 return new Paper_def(
852 lexer->lookup_identifier("default_table")->lookup(true));