1 %
{ // -*-Fundamental-*-
4 parser.y -- YACC parser for mudela
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.5"
18 #include "translation-property.hh"
19 #include "script-def.hh"
20 #include "symtable.hh"
23 #include "my-lily-lexer.hh"
24 #include "paper-def.hh"
25 #include "midi-def.hh"
29 #include "parseconstruct.hh"
31 #include "identifier.hh"
32 #include "command-request.hh"
33 #include "musical-request.hh"
34 #include "my-lily-parser.hh"
35 #include "text-def.hh"
36 #include "translator-group.hh"
38 #include "music-list.hh"
40 #include "duration-convert.hh"
46 #define YYERROR_VERBOSE 1
48 #define YYPARSE_PARAM my_lily_parser_l
49 #define YYLEX_PARAM my_lily_parser_l
50 #define THIS ((My_lily_parser *) my_lily_parser_l)
52 #define yyerror THIS->parser_error
58 Array
<Melodic_req
*> *melreqvec
;/* should clean up naming */
59 Array
<String
> * strvec
;
67 Music_list
*musiclist
;
74 Music_output_def
* outputdef
;
81 General_script_def
* script
;
86 Symtables
* symtables
;
97 yylex (YYSTYPE *s
, void * v_l
)
99 My_lily_parser
*pars_l
= (My_lily_parser
*) v_l
;
100 My_lily_lexer
* lex_l
= pars_l
->lexer_p_
;
102 lex_l
->lexval_l
= (void*) s
;
103 return lex_l
->yylex ();
111 /* tokens which are not keywords */
133 %token MELODIC_REQUEST
162 %token E_EXCLAMATION E_SMALLER E_BIGGER E_CHAR
166 %token
<melreq
> NOTENAME_ID
167 %token
<id
> DURATION_IDENTIFIER
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
> COMMAND_IDENTIFIER
175 %token
<id
> REAL_IDENTIFIER
176 %token
<id
> TRANS_IDENTIFIER
177 %token
<id
> INT_IDENTIFIER
178 %token
<id
> SCORE_IDENTIFIER
179 %token
<id
> MIDI_IDENTIFIER
180 %token
<id
> PAPER_IDENTIFIER
181 %token
<id
> REQUEST_IDENTIFIER
183 %token
<string> DURATION RESTNAME
184 %token
<string> STRING
185 %token
<string> FIELDNAME RECORDLINE
186 %token
<i
> POST_QUOTES
187 %token
<i
> PRE_QUOTES
189 %type
<outputdef
> output_def
190 %type
<header
> mudela_header mudela_header_body
192 %type
<c
> open_request_parens close_request_parens
193 %type
<c
> open_abbrev_parens
194 %type
<c
> open_plet_parens close_plet_parens
195 %type
<music
> simple_element music_elt full_element lyrics_elt command_elt
196 %type
<i
> abbrev_type
199 %type
<id
> identifier_init
200 %type
<duration
> explicit_steno_duration notemode_duration
201 %type
<duration
> entered_notemode_duration explicit_duration
202 %type
<interval
> dinterval
203 %type
<intvec
> intastint_list
204 %type
<lookup
> symtables symtables_body
205 %type
<melreq
> melodic_request steno_melodic_req
206 %type
<notereq
> steno_note_req
207 %type
<melreqvec
> pitch_list
208 %type
<midi
> midi_block midi_body
209 %type
<moment
> duration_length
211 %type
<scalar
> scalar
212 %type
<music
> Music transposed_music
213 %type
<music
> propertydef
214 %type
<musiclist
> Voice Voice_body
215 %type
<chord
> Chord Chord_body
216 %type
<paper
> paper_block paper_body
217 %type
<real
> dim real
219 %type
<request
> abbrev_command_req
220 %type
<request
> post_request pre_request command_req verbose_command_req
221 %type
<request
> script_req dynamic_req
222 %type
<score
> score_block score_body
223 %type
<script
> script_definition script_body mudela_script gen_script_def
224 %type
<textdef
> text_def
225 %type
<string> script_abbreviation
226 %type
<symbol
> symboldef
227 %type
<symtable
> symtable symtable_body
228 %type
<trans
> translator_spec translator_spec_body
229 %type
<tempo
> tempo_request
230 %type
<string> header_record
238 | mudela mudela_header
{
239 delete THIS
->default_header_p_
;
240 THIS
->default_header_p_
= $2;
242 | mudela score_block
{
245 | mudela add_declaration
{ }
247 | mudela check_version
{ }
248 | mudela add_notenames
{ }
253 if
(String
(*$2) != MUDELA_VERSION
) {
254 if
(THIS
->ignore_version_b_
) {
255 THIS
->here_input
().
error ("Incorrect mudela version");
257 THIS
->fatal_error_i_
= 1;
258 THIS
->parser_error
("Incorrect mudela version");
265 NOTENAMES
'{' notenames_body
'}'
270 | notenames_body CLEAR
{
271 THIS
->clear_notenames
();
273 | notenames_body STRING
'=' melodic_request
{
274 THIS
->add_notename
(*$2, $4);
283 | mudela_header_body FIELDNAME header_record
{
292 THIS
->lexer_p_
->push_header_state
();
295 '{' mudela_header_body
'}' {
297 THIS
->lexer_p_
->pop_state
();
306 | header_record RECORDLINE
{
318 THIS
->remember_spot
();
320 /* cont */ '=' identifier_init
{
321 THIS
->lexer_p_
->set_identifier
(*$1, $4);
322 $4->init_b_
= THIS
->init_parse_b_
;
323 $4->set_spot
(THIS
->pop_spot
());
328 $$
= new Score_id
($1, SCORE_IDENTIFIER
);
332 $$
= new Paper_def_id
($1, PAPER_IDENTIFIER
);
336 $$
= new Midi_def_id
($1, MIDI_IDENTIFIER
);
339 | script_definition
{
340 $$
= new Script_id
($1, SCRIPT_IDENTIFIER
);
344 $$
= new Music_id
($1, MUSIC_IDENTIFIER
);
348 $$
= new Lookup_id
($1, IDENTIFIER
);
352 $$
= new Real_id
(new Real
($1), REAL_IDENTIFIER
);
356 $$
= new Int_id
(new
int ($1), INT_IDENTIFIER
);
360 $$
= new Request_id
($1, POST_REQUEST_IDENTIFIER
);
364 $$
= new Request_id
($1, MELODIC_REQUEST_IDENTIFIER
);
368 $$
= new Translator_id
($1, TRANS_IDENTIFIER
);
370 | explicit_duration
{
371 $$
= new Duration_id
($1, DURATION_IDENTIFIER
);
378 TRANSLATOR
'{' translator_spec_body
'}'
382 translator_spec_body:
384 $$
= $1->translator
();
385 $$
-> set_spot
(THIS
->here_input
());
388 $$
= get_translator_l
(*$2)->clone
();
389 $$
->set_spot
(THIS
->here_input
());
392 | translator_spec_body STRING
'=' scalar
';' {
393 $$
-> set_property
(*$2, *$4);
397 | translator_spec_body CONSISTS STRING
';' {
398 $$
->group_l
()->consists_str_arr_.push
(*$3);
401 | translator_spec_body ACCEPTS STRING
';' {
402 $$
->group_l
()->accepts_str_arr_.push
(*$3);
411 SCORE
{ THIS
->remember_spot
();
412 THIS
->error_level_i_
=0;
414 /*cont*/ '{' score_body
'}' {
416 $$
->set_spot
(THIS
->pop_spot
());
417 if
(!$$
->def_p_arr_.size
())
418 $$
->add
(THIS
->default_paper
());
420 /* handle error levels. */
421 $$
->errorlevel_i_
= THIS
->error_level_i_
;
422 THIS
->error_level_i_
= 0;
423 if
(!$$
->header_p_
&& THIS
->default_header_p_
)
424 $$
->header_p_
= new Header
(*THIS
->default_header_p_
);
434 | score_body mudela_header
{
440 | score_body output_def
{
458 /* */ { $$
=new Array
<int>; }
459 | intastint_list
int '*' int {
460 $$
->push
($2); $$
->push
($4);
470 '{' paper_body
'}' { $$
= $3; }
475 $$
= THIS
->default_paper
(); // paper / video / engrave
478 $$
= $1->paperdef
();
480 | paper_body OUTPUT STRING
';' {
481 $$
->outfile_str_
= *$3;
484 | paper_body symtables
{ $$
->set
($2); }
485 | paper_body STRING
'=' dim
';' {
486 $$
->set_var
(*$2, $4);
488 | paper_body STRING
'=' real
';' {
489 $$
->set_var
(*$2, $4);
491 | paper_body STRING
'=' translator_spec
{
492 $$
-> assign_translator
(*$2, $4);
506 '{' midi_body
'}' { $$
= $3; }
509 midi_body: /* empty */ {
510 $$
= THIS
->default_midi
();
512 | midi_body STRING
'=' translator_spec
{
513 $$
-> assign_translator
(*$2, $4);
516 | midi_body OUTPUT STRING
';' {
517 $$
->outfile_str_
= *$3;
520 | midi_body tempo_request
';' {
521 $$
->set_tempo
($2->dur_.length
(), $2->metronome_i_
);
530 TEMPO entered_notemode_duration
'=' int {
534 $$
-> metronome_i_
= $4;
558 full_element
{ $$
= $1; }
559 | TYPE STRING Music
{
561 $$
->translator_type_str_
= *$2;
564 | TYPE STRING
'=' STRING Music
{
566 $$
->translator_type_str_
= *$2;
567 $$
->translator_id_str_
= *$4;
573 | transposed_music
{ $$
= $1; }
574 | MUSIC_IDENTIFIER
{ $$
= $1->music
(); }
576 { THIS
->lexer_p_
->push_note_state
(); }
578 { $$
=$3; THIS
->lexer_p_
->pop_state
(); }
581 { THIS
->lexer_p_
->push_lyric_state
(); }
583 { $$
= $3; THIS
->lexer_p_
->pop_state
(); }
588 TRANSLATOR STRING
'=' STRING
{
589 /* kluge. Could use Music just as well */
590 Translation_property
* t
= new Translation_property
;
591 t
-> translator_type_str_
= *$2;
592 t
-> translator_id_str_
= *$4;
597 | PROPERTY STRING
'.' STRING
'=' scalar
{
598 Translation_property
*t
= new Translation_property
;
599 t
-> translator_type_str_
= *$2;
610 STRING
{ $$
= new Scalar
(*$1); delete
$1; }
611 |
int { $$
= new Scalar
($1); }
616 '<' Chord_body
'>' { $$
= $2; }
622 $$
-> multi_level_i_
= 1;
624 | Chord_body MULTI INT
';' {
625 $$
->multi_level_i_
=$3;
633 TRANSPOSE steno_melodic_req Music
{
635 $$
-> transpose
($2);
645 pre_requests simple_element post_requests
{
646 THIS
->add_requests
((Chord
*)$2);//ugh
650 | voice_command
';' { $$
= 0; }
660 $$
= new Request_chord
;
661 $$
-> set_spot
(THIS
->here_input
());
662 $1-> set_spot
(THIS
->here_input
());
663 ((Chord
*)$$
) ->add
($1);//ugh
670 | verbose_command_req
';' { $$
= $1; }
675 $$
= new Barcheck_req
;
677 | COMMAND_IDENTIFIER
{
684 $$
= new Bar_req
(*$2);
687 | METER
int '/' int {
688 Meter_change_req
*m
= new Meter_change_req
;
692 | SKIP duration_length
{
693 Skip_req
* skip_p
= new Skip_req
;
694 skip_p
->duration_.set_plet
($2->numerator
().as_long
(),
695 $2->denominator
().as_long
());
704 $$
= new Cadenza_req
($2);
706 | PARTIAL duration_length
{
707 $$
= new Partial_measure_req
(*$2);
711 $$
= new Clef_change_req
(*$2);
715 Key_change_req
*key_p
= new Key_change_req
;
716 key_p
->melodic_p_arr_
= *$2;
720 | GROUPING intastint_list
{
721 $$
= get_grouping_req
(*$2); delete
$2;
727 assert
(THIS
->post_reqs.empty
());
729 | post_requests post_request
{
730 $2->set_spot
(THIS
->here_input
());
731 THIS
->post_reqs.push
($2);
737 POST_REQUEST_IDENTIFIER
{
738 $$
= (Request
*)$1->request
();
740 |close_request_parens
{
741 $$
= THIS
->get_parens_request
($1);
746 Abbreviation_req
* a
= new Abbreviation_req
;
759 $$
= $1->clone
()->musical
()->melodic
();
760 $$
->octave_i_
+= THIS
->default_octave_i_
;
762 | steno_melodic_req POST_QUOTES
{
763 $$
-> octave_i_
+= $2;
765 | PRE_QUOTES steno_melodic_req
{
767 $2-> octave_i_
-= $1;
774 * (Melodic_req
*) $$
= *$1;
777 | steno_note_req
'!' {
778 $$
->forceacc_b_
= ! $$
->forceacc_b_
;
780 /* have to duration here. */
784 MELODIC_REQUEST
'{' int int int '}' {/* ugh */
785 $$
= new Melodic_req
;
787 $$
->notename_i_
= $4;
788 $$
->accidental_i_
= $5;
793 DURATION
'{' int int '}' {
801 ABSDYNAMIC
'{' int '}' {
802 Absolute_dynamic_req
*ad_p
= new Absolute_dynamic_req
;
803 ad_p
->loudness_
= (Dynamic_req
::Loudness
)$3;
806 | SPANDYNAMIC
'{' int int '}' {
807 Span_dynamic_req
* sp_p
= new Span_dynamic_req
;
809 sp_p
-> dynamic_dir_
= $3;
817 THIS
->plet_.type_i_
= $4;
818 THIS
->plet_.iso_i_
= $2;
822 close_request_parens:
832 | close_plet_parens
{
846 if
(!Duration
::duration_type_b
($3))
847 THIS
->parser_error
("Not a duration");
849 THIS
->parser_error
("Can't abbreviate");
851 THIS
->set_abbrev_beam
($3);
858 THIS
->plet_.type_i_
= $4;
859 THIS
->plet_.iso_i_
= $2;
873 | open_abbrev_parens
{
882 SCRIPT
'{' script_body
'}' { $$
= $3; }
886 STRING
int int int int int {
887 Script_def
*s
= new Script_def
;
888 s
->set_from_input
(*$1,$2, $3,$4,$5, $6);
895 script_dir gen_script_def
{
896 Musical_script_req
*m
= new Musical_script_req
;
898 m
-> scriptdef_p_
= $2;
899 m
-> set_spot
(THIS
->here_input
());
905 text_def
{ $$
= $1; }
906 | mudela_script
{ $$
= $1;
907 $$
-> set_spot
(THIS
->here_input
());
913 Text_def
*t
= new Text_def
;
917 t
->style_str_
= THIS
->textstyle_str_
;
918 $$
->set_spot
(THIS
->here_input
());
923 '^' { $$
= get_scriptdef
('^'); }
924 |
'+' { $$
= get_scriptdef
('+'); }
925 |
'-' { $$
= get_scriptdef
('-'); }
926 |
'|' { $$
= get_scriptdef
('|'); }
927 |
'o' { $$
= get_scriptdef
('o'); }
928 |
'>' { $$
= get_scriptdef
('>'); }
930 $$
= get_scriptdef
('.');
935 SCRIPT_IDENTIFIER
{ $$
= $1->script
(); }
936 | script_definition
{ $$
= $1; }
937 | script_abbreviation
{
938 $$
= THIS
->lexer_p_
->lookup_identifier
(*$1)->script
();
950 | pre_requests pre_request
{
951 THIS
->pre_reqs.push
($2);
952 $2->set_spot
(THIS
->here_input
());
957 open_request_parens
{
958 $$
= THIS
->get_parens_request
($1);
964 THIS
->default_duration_.set_plet
($2,$4);
967 THIS
->set_duration_mode
(*$2);
970 | DURATION entered_notemode_duration
{
971 THIS
->set_default_duration
($2);
976 This is weird, but default_octave_i_
977 is used in steno_note_req too
979 c' -> default_octave_i_ == 1
981 /* why can't we have \oct{0} iso \oct{c'}*/
982 THIS
->default_octave_i_
= 1; }
985 THIS
->default_octave_i_
= $3->octave_i_
;
989 THIS
->textstyle_str_
= *$2;
996 $$
= new Moment
(0,1);
998 | duration_length explicit_steno_duration
{
999 *$$
+= $2->length
();
1005 | dots
'.' { $$
++; }
1008 entered_notemode_duration:
1010 $$
= new Duration
(THIS
->default_duration_
);
1013 $$
= new Duration
(THIS
->default_duration_
);
1016 | explicit_steno_duration
{
1017 THIS
->set_last_duration
($1);
1023 entered_notemode_duration
{
1025 $$
->plet_.type_i_
*= THIS
->plet_.type_i_
;
1026 $$
->plet_.iso_i_
*= THIS
->plet_.iso_i_
;
1030 explicit_steno_duration:
1033 if
(!Duration
::duration_type_b
($1))
1034 THIS
->parser_error
("Not a duration");
1036 $$
->durlog_i_
= Duration_convert
::i2_type
($1);
1039 | DURATION_IDENTIFIER
{
1040 $$
= $1->duration
();
1042 | explicit_steno_duration
'.' {
1045 | explicit_steno_duration
'*' int {
1046 $$
->plet_.iso_i_
*= $3;
1048 | explicit_steno_duration
'/' int {
1049 $$
->plet_.type_i_
*= $3;
1056 if
(!Duration
::duration_type_b
($2))
1057 THIS
->parser_error
("Not a duration");
1059 THIS
->parser_error
("Can't abbreviate");
1061 THIS
->set_last_abbrev
($2);
1062 $$
= THIS
->default_abbrev_type_i_
;
1067 steno_note_req notemode_duration
{
1068 if
(!THIS
->lexer_p_
->note_state_b
())
1069 THIS
->parser_error
("have to be in Note mode for notes");
1070 $1->set_duration
(*$2);
1071 int durlog_i
= $2->durlog_i_
;
1072 $$
= THIS
->get_note_element
($1, $2);
1074 | RESTNAME notemode_duration
{
1075 $$
= THIS
->get_rest_element
(*$1, $2);
1081 text_def notemode_duration
{
1082 /* this sux! text-def should be feature of lyric-engraver. */
1083 if
(!THIS
->lexer_p_
->lyric_state_b
())
1084 THIS
->parser_error
("Have to be in Lyric mode for lyrics");
1085 $$
= THIS
->get_word_element
($1, $2);
1093 $$
= new Array
<Melodic_req
*>;
1095 | pitch_list NOTENAME_ID
{
1096 $$
->push
($2->clone
()->musical
()->melodic
());
1105 int *i_p
= $1->intid
();
1117 Real
*r_p
= $1->real
();
1126 real unit
{ $$
= $1*$2; }
1130 unit: CM_T
{ $$
= 1 CM
; }
1131 |IN_T
{ $$
= 1 INCH
; }
1132 |MM_T
{ $$
= 1 MM
; }
1133 |PT_T
{ $$
= 1 PT
; }
1140 SYMBOLTABLES
'{' symtables_body
'}' { $$
= $3; }
1150 | symtables_body TEXID STRING
{
1151 $$
->texsetting
= *$3;
1154 | symtables_body STRING
'=' symtable
{
1161 TABLE
'{' symtable_body
'}' { $$
= $3; }
1165 { $$
= new Symtable
; }
1166 | symtable_body STRING symboldef
{
1175 $$
= new Symbol
(*$1, *$2);
1180 Box b
(Interval
(0,0), Interval
(0,0));
1181 $$
= new Symbol
(*$1, b
);
1187 dinterval dinterval
{
1188 $$
= new Box
(*$1, *$2);
1194 dinterval: dim dim
{
1195 $$
= new Interval
($1, $2);
1202 My_lily_parser::set_yydebug
(bool b
)
1209 My_lily_parser::do_yyparse
()
1211 yyparse ((void*)this
);
1215 My_lily_parser::default_paper
()
1217 Identifier
*id
= lexer_p_
->lookup_identifier
("default_paper");
1218 return id ? id
->paperdef
() : new Paper_def
;
1222 My_lily_parser::default_midi
()
1224 Identifier
*id
= lexer_p_
->lookup_identifier
("default_midi");
1225 return id ? id
->mididef
() : new Midi_def
;