lilypond-0.1.14
[lilypond.git] / src / parser.y
blob08ea828119f561caeef6e0c0943468f8623ba86a
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
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
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
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);
150 delete $1;
152 | declarable_identifier '=' music_voice {
153 $$ = new M_voice_id(*$1, $3);
154 delete $1;
156 | declarable_identifier '=' script_definition {
157 $$ = new Script_id(*$1, $3);
158 delete $1;
160 | declarable_identifier '=' music_chord {
161 $$ = new M_chord_id(*$1, $3);
162 delete $1;
164 | declarable_identifier '=' symtables {
165 $$ = new Lookup_id(*$1, $3);
166 delete $1;
168 | declarable_identifier '=' notename_tab {
169 $$ = new Notetab_id(*$1, $3);
170 delete $1;
172 | declarable_identifier '=' real {
173 $$ = new Real_id(*$1, new Real($3));
174 delete $1;
176 | declarable_identifier error '}' {
181 notename_tab:
182 NOTENAMES '{' notename_tab_body '}' { $$ = $3; }
185 notename_tab_body: {
186 $$ = new Notename_tab;
188 | IDENTIFIER {
189 $$ = $1->notename_tab(true);
191 | notename_tab_body STRING int int {
192 $$->set($3, $4, *$2);
193 delete $2;
198 SCORE
200 score_block:
201 SCORE { define_spots.push(lexer->here_ch_c_l()); }
202 /*cont*/ '{' score_body '}' {
203 $$ = $4;
204 $$->defined_ch_c_l_ = define_spots.pop();
205 if (!$$->paper_p_ && ! $$->midi_p_)
206 $$->paper_p_ = default_paper();
208 /* handle error levels. */
209 $$->errorlevel_i_ = lexer->errorlevel_i_;
210 lexer->errorlevel_i_ = 0;
214 score_body: {
215 $$ = new Input_score;
217 | score_body staff_block { $$->add($2); }
218 | score_body COMMANDS '{' music_voice_body '}' {
219 $$->set($4);
221 | score_body paper_block { $$->set($2); }
222 | score_body midi_block { $$->set($2); }
223 | score_body error {
228 intastint_list:
229 /* */ { $$ =new Array<int>; }
230 | intastint_list int '*' int {
231 $$->push($2); $$->push($4);
237 PAPER
239 paper_block:
240 PAPER
242 '{' paper_body '}' { $$ = $3; }
245 paper_body:
246 /* empty */ {
247 $$ = default_paper();
249 | paper_body WIDTH dim { $$->linewidth = $3;}
250 | paper_body OUTPUT STRING { $$->outfile = *$3;
251 delete $3;
253 | paper_body symtables { $$->set($2); }
254 | paper_body UNITSPACE dim { $$->whole_width = $3; }
255 | paper_body GEOMETRIC REAL { $$->geometric_ = $3; }
256 | paper_body error {
262 MIDI
264 midi_block:
265 MIDI
267 '{' midi_body '}' { $$ = $3; }
270 midi_body: {
271 $$ = new Midi_def;
273 | midi_body OUTPUT STRING {
274 $$->outfile_str_ = *$3;
275 delete $3;
277 | midi_body TEMPO mudela_duration ':' int {
278 $$->set_tempo( wholes( $3[0], $3[1] ), $5 );
280 | midi_body error {
286 STAFFs
288 staff_block:
289 STAFF { define_spots.push(lexer->here_ch_c_l()); }
290 /*cont*/ '{' staff_body '}' {
291 $$ = $4;
292 $$-> defined_ch_c_l_ = define_spots.pop();
298 staff_init:
299 IDENTIFIER { $$ = $1->staff(true); }
300 | STRING {
301 $$ = new Input_staff(*$1);
302 delete $1;
306 staff_body:
307 staff_init
308 | staff_body COMMANDS '{' music_voice_body '}' {
309 $$->set_score_wide($4);
311 | staff_body music {
312 $2->set_default_group( "staff_music" + String($$->music_.size()));
313 $$->add($2);
315 | staff_body error {
320 MUSIC
322 music:
323 music_voice { $$ = $1; }
324 | music_chord { $$ = $1; }
327 music_voice: MUSIC '{' music_voice_body '}' { $$ = $3; }
330 music_voice_body:
331 /* */ {
332 $$ = new Music_voice;
334 | music_voice_body IDENTIFIER {
335 $$->concatenate($2->mvoice(true));
337 | music_voice_body full_element {
338 $$->add_elt($2);
340 | music_voice_body voice_command {
342 | music_voice_body music {
343 $$->add($2);
345 | music_voice_body error {
349 music_chord: '{' music_chord_body '}' { $$ = $2; }
352 music_chord_body:
353 /* */ {
354 $$ = new Voice_group_chord;
356 | MULTIVOICE {
357 $$ = new Multi_voice_chord;
359 | music_chord_body IDENTIFIER {
360 $$->concatenate($2->mchord(true));
362 | music_chord_body music {
363 $$->add($2);
365 | music_chord_body full_element {
366 $$ ->add_elt($2);
368 | music_chord_body error {
374 VOICE ELEMENTS
376 full_element: pre_requests voice_elt post_requests {
377 add_requests($2, pre_reqs);
378 add_requests($2, post_reqs);
379 $$ = $2;
381 | pre_requests lyrics_elt post_requests {
382 add_requests($2, pre_reqs);
383 add_requests($2, post_reqs);
384 $$ = $2;
386 | command_elt
389 command_elt:
390 /* empty */ {
391 $$ = new Voice_element;
392 $$-> defined_ch_c_l_ = lexer->here_ch_c_l();
394 /* cont: */
395 command_req {
396 $2-> defined_ch_c_l_ = $$->defined_ch_c_l_;
397 $$->add($2);
402 command_req:
403 '|' {
404 $$ = new Barcheck_req;
406 | BAR STRING {
407 $$ = new Bar_req(*$2);
408 delete $2;
410 | METER '{' int '*' int '}' {
411 Meter_change_req *m = new Meter_change_req;
412 m->set($3,$5);
413 $$ = m;
415 | SKIP '{' duration_length '}' {
416 Skip_req * skip_p = new Skip_req;
417 skip_p->duration_ = *$3;
418 delete $3;
419 $$ = skip_p;
421 | CADENZA '{' int '}' {
422 $$ = new Cadenza_req($3);
424 | PARTIAL '{' duration_length '}' {
425 $$ = new Partial_measure_req(*$3);
426 delete $3;
428 | STEM '{' int '}' {
429 $$ = get_stemdir_req($3);
431 | CLEF STRING {
432 $$ = new Clef_change_req(*$2);
433 delete $2;
435 | KEY '{' pitch_list '}' {
436 Key_change_req *key_p= new Key_change_req;
437 key_p->melodic_p_arr_ = *$3;
438 $$ = key_p;
439 delete $3;
441 | GROUPING '{' intastint_list '}' {
442 $$ = get_grouping_req(*$3); delete $3;
446 post_requests:
448 assert(post_reqs.empty());
450 | post_requests post_request {
451 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
452 post_reqs.push($2);
454 | post_requests close_plet_parens INT '/' INT {
455 post_reqs.push( get_request($2) );
456 req_defined_ch_c_l = lexer->here_ch_c_l();
457 post_reqs.push( get_plet_request( $2, $3, $5 ) );
461 post_request:
462 close_request_parens {
463 $$ = get_request($1);
465 | script_req
466 | textscript_req
469 close_plet_parens:
470 ']' {
471 req_defined_ch_c_l = lexer->here_ch_c_l();
472 $$ = ']';
476 close_request_parens:
477 '(' {
478 $$='(';
480 | ']' {
481 $$ = ']';
485 open_request_parens:
486 ')' {
487 $$=')';
489 | '[' {
490 $$='[';
494 script_definition:
495 SCRIPT '{' script_body '}' { $$ = $3; }
498 script_body:
499 STRING int int int {
500 $$ = new Script_def(*$1,$2, $3,$4);
501 delete $1;
505 textscript_req:
506 script_dir mudela_text { $$ = get_text_req($1,$2); }
509 mudela_text:
510 STRING {
511 defined_ch_c_l = lexer->here_ch_c_l();
512 $$ = get_text(*$1);
513 delete $1;
517 script_req:
518 script_dir mudela_script {
519 $$ = get_script_req($1, $2);
523 mudela_script:
524 IDENTIFIER { $$ = $1->script(true); }
525 | script_definition { $$ = $1; }
526 | '^' { $$ = get_scriptdef('^'); }
527 | '+' { $$ = get_scriptdef('+'); }
528 | '-' { $$ = get_scriptdef('-'); }
529 | '|' { $$ = get_scriptdef('|'); }
530 | 'o' { $$ = get_scriptdef('o'); }
531 | '>' { $$ = get_scriptdef('>'); }
532 | '.' { $$ = get_scriptdef('.'); }
533 | DOTS {
534 if ( $1 > 1 )
535 warning( "too many staccato dots", lexer->here_ch_c_l() );
536 $$ = get_scriptdef('.');
538 | error {
539 $$ = get_scriptdef('.');
540 yyerrok;
544 script_dir:
545 '_' { $$ = -1; }
546 |'^' { $$ = 1; }
547 |'-' { $$ = 0; }
550 pre_requests:
551 | pre_requests pre_request {
552 pre_reqs.push($2);
553 $2->defined_ch_c_l_ = lexer->here_ch_c_l();
557 pre_request:
558 open_request_parens {
559 defined_ch_c_l = lexer->here_ch_c_l();
560 $$ = get_request($1);
564 voice_command:
565 PLET '{' INT '/' INT '}' {
566 set_plet($3,$5);
568 | DURATIONCOMMAND '{' STRING '}' {
569 set_duration_mode(*$3);
570 delete $3;
572 | DURATIONCOMMAND '{' notemode_duration '}' {
573 set_default_duration($3);
575 | OCTAVECOMMAND '{' pitchmod '}' {
576 set_default_octave(*$3);
577 delete $3;
579 | TEXTSTYLE STRING {
580 set_text_style(*$2);
581 delete $2;
585 duration_length:
586 mudela_duration {
587 $$ = new Moment(wholes($1[0], $1[1]));
589 |int '*' mudela_duration {
590 $$ = new Moment(Rational($1) * wholes($3[0], $3[1]));
594 notemode_duration:
595 explicit_duration
596 | default_duration
599 mudela_duration:
600 int {
601 $$[0] = $1;
602 $$[1] = 0;
604 | int DOTS {
605 $$[0] = $1;
606 $$[1] = $2;
611 explicit_duration:
612 INT {
613 last_duration($1);
614 $$[0] = $1;
615 $$[1] = 0;
617 | INT DOTS {
618 last_duration($1);
619 $$[0] = $1;
620 $$[1] = $2;
622 | DOTS {
623 get_default_duration($$);
624 $$[1] = $1;
626 | INT '*' INT '/' INT {
627 // ugh, must use Duration
628 set_plet( $3, $5 );
629 $$[ 0 ] = $1;
630 $$[ 1 ] = 0;
631 set_plet( 1, 1 );
635 default_duration:
637 get_default_duration($$);
641 pitchmod: {
642 defined_ch_c_l = lexer->here_ch_c_l();
643 $$ = new String;
645 | PITCHMOD {
646 defined_ch_c_l = lexer->here_ch_c_l();
647 $$ = $1;
651 notename:
652 NOTENAME
655 voice_elt:
656 pitchmod notename notemode_duration {
657 $$ = get_note_element(*$1, $2, $3);
658 delete $1;
660 | RESTNAME notemode_duration {
661 $$ = get_rest_element(*$1, $2);
662 delete $1;
667 lyrics_elt:
668 mudela_text notemode_duration {
669 $$ = get_word_element($1, $2);
673 UTILITIES
675 pitch_list: {
676 $$ = new Array<Melodic_req*>;
678 | pitch_list NOTENAME {
679 Melodic_req *m_p = new Melodic_req;
680 m_p->notename_i_ = $2[0];
681 m_p->accidental_i_ = $2[1];
682 $$->push(m_p);
686 int:
687 real {
688 $$ = int($1);
689 if ( distance($1,Real(int($$)) ) > 1e-8)
690 error( "integer expected", lexer->here_ch_c_l() );
694 real:
695 INT {
696 $$ = Real($1);
698 | REAL {
699 $$ = $1;
701 | IDENTIFIER {
702 $$ = * $1->real(0);
708 dim:
709 real unit { $$ = $1*$2; }
713 unit: CM_T { $$ = 1 CM; }
714 |IN_T { $$ = 1 INCH; }
715 |MM_T { $$ = 1 MM; }
716 |PT_T { $$ = 1 PT; }
720 symbol tables
722 symtables:
723 SYMBOLTABLES '{' symtables_body '}' { $$ = $3; }
726 symtables_body:
728 $$ = new Lookup;
730 | IDENTIFIER {
731 $$ = new Lookup(*$1->lookup(true));
733 | symtables_body TEXID STRING {
734 $$->texsetting = *$3;
735 delete $3;
737 | symtables_body STRING '=' symtable {
738 $$->add(*$2, $4);
739 delete $2;
743 symtable:
744 TABLE '{' symtable_body '}' { $$ = $3; }
747 symtable_body:
748 { $$ = new Symtable; }
749 | symtable_body STRING symboldef {
750 $$->add(*$2, *$3);
751 delete $2;
752 delete $3;
756 symboldef:
757 STRING box {
758 $$ = new Symbol(*$1, *$2);
759 delete $1;
760 delete $2;
762 | STRING {
763 Box b;
764 $$ = new Symbol(*$1, b);
765 delete $1;
769 box:
770 dinterval dinterval {
771 $$ = new Box(*$1, *$2);
772 delete $1;
773 delete $2;
777 dinterval: dim dim {
778 $$ = new Interval($1, $2);
784 void
785 yyerror(const char *s)
787 lexer->LexerError(s);
789 if ( fatal_error_i )
790 exit( fatal_error_i );
793 void
794 parse_file(String init, String s)
796 *mlog << "Parsing ... ";
797 lexer = new My_flex_lexer;
799 #ifndef NDEBUG
800 yydebug = !monitor->silence("InitParser") && check_debug;
801 lexer->set_debug( !monitor->silence("InitLexer") && check_debug);
802 #endif
804 lexer->new_input(init);
806 yyparse();
808 #ifndef NDEBUG
809 if (check_debug && !monitor->silence("InitDeclarations"))
810 lexer->print_declarations();
812 yydebug = !monitor->silence("Parser") && check_debug;
813 lexer->set_debug( !monitor->silence("Lexer") && check_debug);
814 #endif
816 lexer->new_input(s);
817 yyparse();
818 delete lexer;
819 lexer = 0;
821 if(!define_spots.empty())
822 warning("Braces don't match.",0);
825 Paper_def*
826 default_paper()
828 return new Paper_def(
829 lexer->lookup_identifier("default_table")->lookup(true));