X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fparser.yy;h=2f9d9b37c232daa0163a66877b4a4e2be722c178;hb=1753b1a73742a5b0893037116bb6f2febba277f3;hp=eb1e28bbfe5f496650ff380fee34d8d36f9f675e;hpb=6f48eb41fff67a69ca77e6803abc9b5142319cdb;p=lilypond.git diff --git a/lily/parser.yy b/lily/parser.yy index eb1e28bbfe..2f9d9b37c2 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -5,26 +5,60 @@ source file of the GNU LilyPond music typesetter - (c) 1997--2002 Han-Wen Nienhuys + (c) 1997--2003 Han-Wen Nienhuys Jan Nieuwenhuizen */ /* - Two shift/reduce problems: - - empty music-list - - empty pre-events + Four shift/reduce problems: + +1. foo = bar. + + "bar" -> String -> Lyric -> Music -> music-assignment + + "bar" -> String -> string-assignment + + +Similar problem for + + * \markup identifier. + * \markup { } + + +2. \repeat + \repeat .. \alternative + + + \repeat { \repeat .. \alternative } + +or + + \repeat { \repeat } \alternative + +) + +--hwn + */ /* -the rules for who is protecting what are very shady. TODO: uniformise -this. +TODO: + +* The rules for who is protecting what are very shady. Uniformise + this. +* There are too many lexical modes? */ #include +#include +#include +#include + +#include "scm-option.hh" #include "translator-def.hh" #include "lily-guile.hh" #include "misc.hh" @@ -42,11 +76,47 @@ this. #include "lilypond-input-version.hh" #include "scm-hash.hh" #include "auto-change-iterator.hh" -#include "chord.hh" #include "ly-modules.hh" #include "music-sequence.hh" #include "input-smob.hh" #include "event.hh" +#include "text-item.hh" +#include "music-list.hh" + + +#define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x)) + + + +#define YYERROR_VERBOSE 1 + +My_lily_parser* my_lily_parser; +#define YYPARSE_PARAM my_lily_parser +#define YYLEX_PARAM my_lily_parser +#define THIS\ + ((My_lily_parser *) my_lily_parser) + +#define yyerror THIS->parser_error + +/* + Add symbols to the TAGS field of a music object. +*/ + +void +tag_music (Music*m, SCM tag, Input ip) +{ + SCM tags = m->get_mus_property ("tags"); + if (gh_symbol_p (tag)) + tags = scm_cons (tag, tags); + else if (gh_list_p (tag)) + tags = gh_append2 (tag, tags); + else + ip.warning (_("Tag must be symbol or list of symbols.")); + + m->set_mus_property ("tags", tags); +} + + bool regular_identifier_b (SCM id) @@ -63,6 +133,15 @@ regular_identifier_b (SCM id) return v; } +SCM +make_simple_markup (SCM a) +{ + static SCM simple; + if (!simple) + simple = scm_c_eval_string ("simple-markup"); + + return scm_list_n (simple, a, SCM_UNDEFINED); +} bool @@ -80,9 +159,38 @@ set_music_properties (Music *p, SCM a) } } +SCM +make_chord_step (int step, int alter) +{ + if (step == 7) + alter--; + /* ugh: fucks up above 13 */ + Pitch m(step > 7 ? 1 : 0,(step - 1) % 7, alter); + return m.smobbed_copy (); +} -#define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x)) + +SCM +make_chord (SCM pitch, SCM dur, SCM modification_list) +{ + static SCM chord_ctor; + if (!chord_ctor) + chord_ctor= scm_c_eval_string ("construct-chord"); + SCM ch= scm_call_3 (chord_ctor, pitch, dur, modification_list); + scm_gc_protect_object (ch); + return ch; +} + +/* + Todo: actually also use apply iso. call too ... +*/ +bool +ly_input_procedure_p (SCM x) +{ + return gh_procedure_p (x) + || (gh_pair_p (x) && gh_procedure_p (gh_car (x))); +} Music* set_property_music (SCM sym, SCM value) @@ -93,24 +201,6 @@ set_property_music (SCM sym, SCM value) return p; } - -// needed for bison.simple's malloc () and free () - -// #include -#include - - - -#define YYERROR_VERBOSE 1 - -My_lily_parser* my_lily_parser; -#define YYPARSE_PARAM my_lily_parser -#define YYLEX_PARAM my_lily_parser -#define THIS\ - ((My_lily_parser *) my_lily_parser) - -#define yyerror THIS->parser_error - %} /* We use SCMs to do strings, because it saves us the trouble of @@ -119,10 +209,7 @@ of the parse stack onto the heap. */ %union { - - Link_array *reqvec; - - String *string; // needed by the lexer as temporary scratch area. + String * string; Music *music; Score *score; Music_output_def * outputdef; @@ -147,71 +234,74 @@ yylex (YYSTYPE *s, void * v) %pure_parser -/* tokens which are not keywords */ -%token AUTOCHANGE -%token ALIAS -%token APPLY + %token ACCEPTS +%token ADDLYRICS +%token ALIAS %token ALTERNATIVE +%token APPLY +%token APPLYCONTEXT +%token APPLYOUTPUT +%token AUTOCHANGE %token BAR %token BREATHE -%token CHORDMODIFIERS +%token CHORDMODIFIERS %token CHORDS -%token CHAR_T +%token LESSLESS +%token MOREMORE %token CLEF -%token CM_T +%token COMMANDSPANREQUEST %token CONSISTS -%token DURATION -%token SEQUENTIAL -%token GROBDESCRIPTIONS -%token SIMULTANEOUS %token CONSISTSEND +%token CONTEXT +%token DEFAULT %token DENIES +%token DESCRIPTION %token EXTENDER %token FIGURES FIGURE_OPEN FIGURE_CLOSE %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN %token GRACE +%token ACCIACCATURA +%token APPOGGIATURA +%token GROBDESCRIPTIONS %token HEADER %token HYPHEN -%token IN_T %token INVALID %token KEY %token LYRICS %token MARK -%token MULTI_MEASURE_REST %token MIDI -%token MM_T -%token PITCH -%token DEFAULT +%token MULTI_MEASURE_REST %token NAME -%token PITCHNAMES +%token NEWCONTEXT %token NOTES +%token OCTAVE %token ONCE +%token OVERRIDE SET REVERT %token PAPER +%token PARTCOMBINE %token PARTIAL +%token PITCHNAMES %token PROPERTY -%token OVERRIDE SET REVERT -%token PT_T %token RELATIVE %token REMOVE %token REPEAT -%token ADDLYRICS -%token PARTCOMBINE +%token REST %token SCM_T %token SCORE +%token SEQUENTIAL +%token SIMULTANEOUS %token SKIP %token SPANREQUEST -%token COMMANDSPANREQUEST +%token TAG %token TEMPO -%token OUTPUTPROPERTY -%token TIME_T %token TIMES +%token TIME_T %token TRANSLATOR %token TRANSPOSE %token TYPE %token UNSET -%token CONTEXT -%token REST + /* escaped */ %token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE @@ -222,8 +312,10 @@ yylex (YYSTYPE *s, void * v) %token FIGURE_SPACE %type exclamations questions dots optional_rest -%type bass_number bass_mod -%type br_bass_figure bass_figure figure_list figure_spec +%type bass_mod +%type grace_head +%type lyric_element +%type bass_number br_bass_figure bass_figure figure_list figure_spec %token DIGIT %token NOTENAME_PITCH %token TONICNAME_PITCH @@ -231,7 +323,9 @@ yylex (YYSTYPE *s, void * v) %token DURATION_IDENTIFIER %token FRACTION %token IDENTIFIER +%token CHORDNAMES +%token CHORD_MODIFIER %token SCORE_IDENTIFIER %token MUSIC_OUTPUT_DEF_IDENTIFIER @@ -245,10 +339,21 @@ yylex (YYSTYPE *s, void * v) %token UNSIGNED %token REAL +%token MARKUP +%token MARKUP_HEAD_MARKUP0 +%token MARKUP_HEAD_MARKUP0_MARKUP1 +%token MARKUP_HEAD_SCM0 +%token MARKUP_HEAD_SCM0_MARKUP1 +%token MARKUP_HEAD_SCM0_SCM1 +%token MARKUP_HEAD_SCM0_SCM1_SCM2 +%token MARKUP_HEAD_SCM0_SCM1_MARKUP2 + +%token MARKUP_IDENTIFIER MARKUP_HEAD_LIST0 +%type markup markup_line markup_list markup_list_body full_markup + %type output_def %type lilypond_header lilypond_header_body -%type open_event_parens close_event_parens open_event close_event -%type event_with_dir event_that_take_dir verbose_event +%type open_event close_event %type sub_quotes sup_quotes %type simple_element event_chord command_element Simple_music Composite_music %type Repeated_music @@ -258,19 +363,18 @@ yylex (YYSTYPE *s, void * v) %type script_dir %type identifier_init +%type note_chord_element chord_body chord_body_element +%type chord_body_elements %type steno_duration optional_notemode_duration multiplied_duration -%type verbose_duration -%type pre_events post_events -%type gen_text_def -%type steno_pitch pitch absolute_pitch -%type explicit_pitch steno_tonic_pitch - -%type chord_additions chord_subtractions chord_notes chord_step -%type chord -%type chord_note chord_inversion chord_bass +%type post_events +%type gen_text_def direction_less_event direction_reqd_event +%type steno_pitch pitch absolute_pitch pitch_also_in_chords +%type steno_tonic_pitch %type duration_length fraction +%type new_chord step_number chord_items chord_item chord_separator step_numbers + %type embedded_scm scalar %type Music Sequential_music Simultaneous_music %type relative_music re_rhythmed_music part_combined_music @@ -278,13 +382,12 @@ yylex (YYSTYPE *s, void * v) %type Music_list %type music_output_def_body %type shorthand_command_req -%type post_event +%type post_event tagged_post_event %type command_req verbose_command_req %type extender_req %type hyphen_req -%type string_event +%type string_number_event %type string bare_number number_expression number_term number_factor - %type score_block score_body %type translator_spec_block translator_spec_body @@ -356,12 +459,8 @@ notenames_body: SCM tab = scm_make_vector (gh_int2scm (i), SCM_EOL); for (SCM s = $1; gh_pair_p (s); s = ly_cdr (s)) { SCM pt = ly_cdar (s); - if (!unsmob_pitch (pt)) - THIS->parser_error ("Need pitch object."); - else - scm_hashq_set_x (tab, ly_caar (s), pt); + scm_hashq_set_x (tab, ly_caar (s), pt); } - $$ = tab; } ; @@ -422,6 +521,9 @@ identifier_init: $$ = $1->self_scm (); scm_gc_unprotect_object ($$); } + | full_markup { + $$ = $1; + } | output_def { $$ = $1->self_scm (); scm_gc_unprotect_object ($$); @@ -437,9 +539,6 @@ identifier_init: $$ = $1->self_scm (); scm_gc_unprotect_object ($$); } - | verbose_duration { - $$ = $1; - } | number_expression { $$ = $1; } @@ -469,6 +568,9 @@ translator_spec_body: td->translator_group_type_ = $2; td->set_spot (THIS->here_input ()); } + | translator_spec_body DESCRIPTION string { + unsmob_translator_def ($$)->description_ = $3; + } | translator_spec_body STRING '=' embedded_scm { unsmob_translator_def ($$)->add_property_assign ($2, $4); } @@ -485,14 +587,14 @@ translator_spec_body: scm_string_to_symbol ($2), $4); } | translator_spec_body NAME STRING { - unsmob_translator_def ($$)->type_name_ = $3; + unsmob_translator_def ($$)->type_name_ = scm_string_to_symbol ($3); } | translator_spec_body CONSISTS STRING { unsmob_translator_def ($$)->add_element ($3); } | translator_spec_body ALIAS STRING { Translator_def*td = unsmob_translator_def ($$); - td->type_aliases_ = scm_cons ($3, td->type_aliases_); + td->type_aliases_ = scm_cons (scm_string_to_symbol ($3), td->type_aliases_); } | translator_spec_body GROBDESCRIPTIONS embedded_scm { Translator_def*td = unsmob_translator_def($$); @@ -504,10 +606,10 @@ translator_spec_body: unsmob_translator_def ($$)->add_last_element ( $3); } | translator_spec_body ACCEPTS STRING { - unsmob_translator_def ($$)->set_acceptor ($3,true); + unsmob_translator_def ($$)->set_acceptor (scm_string_to_symbol ($3), true); } | translator_spec_body DENIES STRING { - unsmob_translator_def ($$)->set_acceptor ($3,false); + unsmob_translator_def ($$)->set_acceptor (scm_string_to_symbol ($3), false); } | translator_spec_body REMOVE STRING { unsmob_translator_def ($$)->remove_element ($3); @@ -625,7 +727,7 @@ music_output_def_body: music. */ int m = gh_scm2int ( $2->get_mus_property ("metronome-count")); - Duration *d = unsmob_duration ($2->get_mus_property ("duration")); + Duration *d = unsmob_duration ($2->get_mus_property ("tempo-unit")); Midi_def * md = dynamic_cast ($$); if (md) md->set_tempo (d->get_length (), m); @@ -637,8 +739,8 @@ music_output_def_body: tempo_event: TEMPO steno_duration '=' bare_unsigned { - $$ = MY_MAKE_MUSIC("TempoEvent"); - $$->set_mus_property ("duration", $2); + $$ = MY_MAKE_MUSIC("MetronomeChangeEvent"); + $$->set_mus_property ("tempo-unit", $2); $$->set_mus_property ("metronome-count", gh_int2scm ( $4)); } ; @@ -650,12 +752,13 @@ The representation of a list is the to have efficient append. */ -Music_list: /* empty */ { /* SR conflict */ +Music_list: + /* empty */ { $$ = scm_cons (SCM_EOL, SCM_EOL); } | Music_list Music { SCM s = $$; - SCM c = scm_cons ($2->self_scm (), SCM_EOL); + SCM c = scm_cons ($2->self_scm (), SCM_EOL); scm_gc_unprotect_object ($2->self_scm ()); /* UGH */ if (gh_pair_p (ly_cdr (s))) gh_set_cdr_x (ly_cdr (s), c); /* append */ @@ -711,17 +814,30 @@ Repeated_music: r->set_mus_property ("repeat-count", gh_int2scm (times >? 1)); r-> set_mus_property ("elements",alts); - if (gh_equal_p ($2, scm_makfrom0str ("tremolo"))) - { - /* - we can not get durations and other stuff correct down the line, so we have to - add to the duration log here. - */ - SCM func = scm_primitive_eval (ly_symbol2scm ("shift-duration-log")); - if (($3 % 3) == 0) - gh_call3 (func, r->self_scm (), gh_int2scm(-intlog2 ($3*2/3)),gh_int2scm(1)); - else - gh_call3 (func, r->self_scm (), gh_int2scm(-intlog2 ($3)), gh_int2scm(0)); + if (gh_equal_p ($2, scm_makfrom0str ("tremolo"))) { + /* + we can not get durations and other stuff correct down the line, so we have to + add to the duration log here. + */ + static SCM func; + + if (!func) + func = scm_primitive_eval (ly_symbol2scm ("shift-duration-log")); + + int dots = ($3 % 3) ? 0 : 1; + int shift = -intlog2 ((dots) ? ($3*2/3) : $3); + + Sequential_music * seq = dynamic_cast ($4); + + if (seq) { + int list_len =scm_ilength (seq->music_list ()); + if (list_len != 2) + seq->origin ()->warning ("Chord tremolo must have 2 elements."); + shift -= 1; + r->compress (Moment (Rational (1,list_len))); + } + gh_call3 (func, r->self_scm (), gh_int2scm(shift),gh_int2scm(dots)); + } r->set_spot (*$4->origin ()); @@ -749,7 +865,7 @@ Simultaneous_music: $$->set_spot(THIS->here_input()); } - | '<' Music_list '>' { + | simul_open Music_list simul_close { $$ = MY_MAKE_MUSIC("SimultaneousMusic"); $$->set_mus_property ("elements", ly_car ($2)); $$->set_spot(THIS->here_input()); @@ -758,24 +874,19 @@ Simultaneous_music: Simple_music: event_chord { $$ = $1; } - | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm { - SCM pred = $2; - if (!gh_symbol_p ($3)) - { - THIS->parser_error (_ ("Second argument must be a symbol")); - } - /* Should check # args */ - if (!gh_procedure_p (pred)) - { - THIS->parser_error (_ ("First argument must be a procedure taking one argument")); - } - - Music*m = MY_MAKE_MUSIC("OutputPropertySetMusic"); - m->set_mus_property ("predicate", pred); - m->set_mus_property ("grob-property", $3); - m->set_mus_property ("grob-value", $5); - - $$ = m; + | APPLYOUTPUT embedded_scm { + if (!ly_input_procedure_p ($2)) + THIS->parser_error (_ ("\\applycontext takes function argument")); + $$ = MY_MAKE_MUSIC ("ApplyOutputEvent"); + $$->set_mus_property ("procedure", $2); + $$->set_spot (THIS->here_input()); + } + | APPLYCONTEXT embedded_scm { + if (!ly_input_procedure_p ($2)) + THIS->parser_error (_ ("\\applycontext takes function argument")); + $$ = MY_MAKE_MUSIC ("ApplyContext"); + $$->set_mus_property ("procedure", $2); + $$->set_spot (THIS->here_input()); } | MUSIC_IDENTIFIER { $$ = unsmob_music ($1); @@ -785,6 +896,13 @@ Simple_music: ; +grace_head: + GRACE { $$ = scm_makfrom0str ("Grace"); } + | ACCIACCATURA { $$ = scm_makfrom0str ("Acciaccatura"); } + | APPOGGIATURA { $$ = scm_makfrom0str ("Appoggiatura"); } + ; + + Composite_music: CONTEXT STRING Music { Music*csm =MY_MAKE_MUSIC("ContextSpeccedMusic"); @@ -792,7 +910,7 @@ Composite_music: csm->set_mus_property ("element", $3->self_scm ()); scm_gc_unprotect_object ($3->self_scm ()); - csm->set_mus_property ("context-type",$2); + csm->set_mus_property ("context-type", scm_string_to_symbol ($2)); csm->set_mus_property ("context-id", scm_makfrom0str ("")); $$ = csm; @@ -803,20 +921,31 @@ Composite_music: chm->set_mus_property ("iterator-ctor", Auto_change_iterator::constructor_proc); scm_gc_unprotect_object ($3->self_scm ()); - chm->set_mus_property ("what", $2); + chm->set_mus_property ("what", scm_string_to_symbol ($2)); $$ = chm; chm->set_spot (*$3->origin ()); } - | GRACE Music { + | grace_head Music { #if 1 /* The other version is for easier debugging of Sequential_music_iterator in combination with grace notes. */ - SCM start = THIS->lexer_->lookup_identifier ("startGraceMusic"); - SCM stop = THIS->lexer_->lookup_identifier ("stopGraceMusic"); +/* + +TODO: should distinguish between both grace types in the +basic music objects too, since the meaning is different. + +*/ + + String start_str = "start" + ly_scm2string ($1) + "Music"; + String stop_str = "stop" + ly_scm2string ($1) + "Music"; + + SCM start = THIS->lexer_->lookup_identifier (start_str); + SCM stop = THIS->lexer_->lookup_identifier (stop_str); + Music *startm = unsmob_music (start); Music *stopm = unsmob_music (stop); @@ -854,11 +983,28 @@ Composite_music: csm->set_mus_property ("element", $5->self_scm ()); scm_gc_unprotect_object ($5->self_scm ()); - csm->set_mus_property ("context-type", $2); + csm->set_mus_property ("context-type", scm_string_to_symbol ($2)); csm->set_mus_property ("context-id", $4); $$ = csm; } + | NEWCONTEXT string Music { + static int new_context_count; + + Music * csm = MY_MAKE_MUSIC("ContextSpeccedMusic"); + + csm->set_mus_property ("element", $3->self_scm ()); + scm_gc_unprotect_object ($3->self_scm ()); + + csm->set_mus_property ("context-type", scm_string_to_symbol ($2)); + + char s[1024]; + snprintf (s, 1024, "uniqueContext%d", new_context_count ++); + + SCM new_id = scm_makfrom0str (s); + csm->set_mus_property ("context-id", new_id); + $$ = csm; + } | TIMES { THIS->push_spot (); } @@ -868,9 +1014,9 @@ Composite_music: { int n = gh_scm2int (ly_car ($3)); int d = gh_scm2int (ly_cdr ($3)); Music *mp = $4; - $$= MY_MAKE_MUSIC("TimeScaledMusic"); - $$->set_spot (THIS->pop_spot ()); + $$= MY_MAKE_MUSIC("TimeScaledMusic"); + $$->set_spot (THIS->pop_spot ()); $$->set_mus_property ("element", mp->self_scm ()); scm_gc_unprotect_object (mp->self_scm ()); @@ -882,33 +1028,32 @@ Composite_music: | Repeated_music { $$ = $1; } | Simultaneous_music { $$ = $1; } | Sequential_music { $$ = $1; } - | TRANSPOSE pitch Music { + | TRANSPOSE pitch_also_in_chords pitch_also_in_chords Music { $$ = MY_MAKE_MUSIC("TransposedMusic"); - Music *p = $3; - Pitch pit = *unsmob_pitch ($2); + Music *p = $4; + Pitch from = *unsmob_pitch ($2); + Pitch to = *unsmob_pitch ($3); - p->transpose (pit); + p->transpose (interval (from, to)); $$->set_mus_property ("element", p->self_scm ()); scm_gc_unprotect_object (p->self_scm ()); } - | TRANSPOSE steno_tonic_pitch Music { - $$ = MY_MAKE_MUSIC("TransposedMusic"); - Music *p = $3; - Pitch pit = *unsmob_pitch ($2); - - p->transpose (pit); - $$->set_mus_property ("element", p->self_scm ()); - scm_gc_unprotect_object (p->self_scm ()); - - } | APPLY embedded_scm Music { - SCM ret = gh_call1 ($2, $3->self_scm ()); - Music *m = unsmob_music (ret); - if (!m) { - THIS->parser_error ("\\apply must return a Music"); - m = MY_MAKE_MUSIC("Music"); + if (!ly_input_procedure_p ($2)) + { + THIS->parser_error (_ ("\\apply takes function argument")); + $$ = $3; + } + else + { + SCM ret = gh_call1 ($2, $3->self_scm ()); + Music *m = unsmob_music (ret); + if (!m) { + THIS->parser_error ("\\apply must return a Music"); + m = MY_MAKE_MUSIC("Music"); + } + $$ = m; } - $$ = m; } | NOTES { THIS->lexer_->push_note_state (); } @@ -947,7 +1092,11 @@ Composite_music: } | relative_music { $$ = $1; } | re_rhythmed_music { $$ = $1; } - | part_combined_music { $$ = $1; } + | part_combined_music { $$ = $1; } + | TAG embedded_scm Music { + tag_music ($3, $2, THIS->here_input ()); + $$ = $3; + } ; relative_music: @@ -959,8 +1108,10 @@ relative_music: $$->set_mus_property ("element", p->self_scm ()); scm_gc_unprotect_object (p->self_scm ()); - $$->set_mus_property ("last-pitch", p->to_relative_octave (pit).smobbed_copy ()); + Pitch retpitch = p->to_relative_octave (pit); + if (lily_1_8_relative) + $$->set_mus_property ("last-pitch", retpitch.smobbed_copy ()); } ; @@ -976,8 +1127,8 @@ re_rhythmed_music: part_combined_music: PARTCOMBINE STRING Music Music { - Music * p= MY_MAKE_MUSIC("PartCombineMusic"); - p->set_mus_property ("what", $2); + Music * p= MY_MAKE_MUSIC("PartCombineMusic"); + p->set_mus_property ("what", scm_string_to_symbol ($2)); p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED)); scm_gc_unprotect_object ($3->self_scm ()); @@ -990,7 +1141,7 @@ part_combined_music: translator_change: TRANSLATOR STRING '=' STRING { Music*t= MY_MAKE_MUSIC("TranslatorChange"); - t-> set_mus_property ("change-to-type", $2); + t-> set_mus_property ("change-to-type", scm_string_to_symbol ($2)); t-> set_mus_property ("change-to-id", $4); $$ = t; @@ -1018,7 +1169,7 @@ simple_property_def: $$ = csm; $$->set_spot (THIS->here_input ()); - csm-> set_mus_property ("context-type", $2); + csm-> set_mus_property ("context-type", scm_string_to_symbol ($2)); } | PROPERTY STRING '.' STRING UNSET { @@ -1032,7 +1183,7 @@ simple_property_def: $$ = csm; $$->set_spot (THIS->here_input ()); - csm-> set_mus_property ("context-type", $2); + csm-> set_mus_property ("context-type", scm_string_to_symbol ($2)); } | PROPERTY STRING '.' STRING SET embedded_scm '=' embedded_scm { bool autobeam @@ -1054,7 +1205,7 @@ simple_property_def: $$ = csm; $$->set_spot (THIS->here_input ()); - csm-> set_mus_property ("context-type", $2); + csm-> set_mus_property ("context-type", scm_string_to_symbol ($2)); } | PROPERTY STRING '.' STRING OVERRIDE embedded_scm '=' embedded_scm @@ -1082,7 +1233,7 @@ simple_property_def: $$ = csm; $$->set_spot (THIS->here_input ()); - csm-> set_mus_property ("context-type", $2); + csm-> set_mus_property ("context-type", scm_string_to_symbol ($2)); } | PROPERTY STRING '.' STRING REVERT embedded_scm { @@ -1105,7 +1256,7 @@ simple_property_def: $$ = csm; $$->set_spot (THIS->here_input ()); - csm-> set_mus_property ("context-type", $2); + csm-> set_mus_property ("context-type", scm_string_to_symbol ($2)); } ; @@ -1114,37 +1265,127 @@ scalar: string { $$ = $1; } | bare_int { $$ = gh_int2scm ($1); } | embedded_scm { $$ = $1; } + | full_markup { $$ = $1; } + | DIGIT { $$ = gh_int2scm ($1); } ; -event_chord: - pre_events { + +/* +This is a trick: + +Adding pre_events to the simple_element +makes the choice between + + string: STRING + +and + + simple_element: STRING + +a single shift/reduction conflict. + +nevertheless, this is not very clean, and we should find a different +solution. + +*/ +pre_events: { THIS->push_spot (); - } /*cont */ simple_element post_events { - Music_sequence *l = dynamic_cast ($3); - - $1->concat (*$4); - for (int i=0; i < $1->size (); i++) { - Music * m = $1->elem (i); - l->append_music (m); - } - $$ = $3; + } + ; + +event_chord: + pre_events simple_element post_events { + SCM elts = $2-> get_mus_property ("elements"); + + elts = gh_append2 (elts, scm_reverse_x ($3, SCM_EOL)); - delete $1; - delete $4; + $2->set_mus_property ("elements", elts); + $$ = $2; } | command_element + | note_chord_element + ; + + +note_chord_element: + chord_body optional_notemode_duration post_events + { + SCM dur = unsmob_duration ($2)->smobbed_copy(); + SCM es = $1->get_mus_property ("elements"); + SCM postevs = scm_reverse_x ($3, SCM_EOL); + + for (SCM s = es; gh_pair_p (s); s = gh_cdr (s)) + unsmob_music (gh_car(s))->set_mus_property ("duration", dur); + es = gh_append2 (es, postevs); + + $1-> set_mus_property ("elements", es); + $$ = $1; + } + ; + +chord_open: '<' + ; + +chord_close: '>' + ; + +simul_open: LESSLESS + ; + +simul_close: MOREMORE + ; + +chord_body: + chord_open chord_body_elements chord_close + { + $$ = MY_MAKE_MUSIC("EventChord"); + $$->set_mus_property ("elements", + scm_reverse_x ($2, SCM_EOL)); + } + ; + +chord_body_elements: + /* empty */ { $$ = SCM_EOL; } + | chord_body_elements chord_body_element { + $$ = gh_cons ($2->self_scm(), $1); + scm_gc_unprotect_object ($2->self_scm()); + } + ; + +chord_body_element: + pitch exclamations questions post_events + { + Music * n = MY_MAKE_MUSIC("NoteEvent"); + n->set_mus_property ("pitch", $1); + if ($3 % 2) + n->set_mus_property ("cautionary", SCM_BOOL_T); + if ($2 % 2 || $3 % 2) + n->set_mus_property ("force-accidental", SCM_BOOL_T); + + SCM arts = scm_reverse_x ($4, SCM_EOL); + n->set_mus_property ("articulations", arts); + + $$ = n; + } ; command_element: command_req { $$ = MY_MAKE_MUSIC("EventChord"); $$->set_mus_property ("elements", scm_cons ($1->self_scm (), SCM_EOL)); - scm_gc_unprotect_object ($1->self_scm()); + scm_gc_unprotect_object ($1->self_scm()); $$-> set_spot (THIS->here_input ()); $1-> set_spot (THIS->here_input ()); } + | OCTAVE { THIS->push_spot (); } + pitch { + Music *l = MY_MAKE_MUSIC("RelativeOctaveCheck"); + $$ = l; + $$->set_spot (THIS->pop_spot ()); + $$->set_mus_property ("pitch", $3); + } | E_LEFTSQUARE { Music *l = MY_MAKE_MUSIC("LigatureEvent"); l->set_mus_property ("span-direction", gh_int2scm (START)); @@ -1152,7 +1393,7 @@ command_element: $$ = MY_MAKE_MUSIC("EventChord"); $$->set_mus_property ("elements", scm_cons (l->self_scm (), SCM_EOL)); - scm_gc_unprotect_object (l->self_scm()); + scm_gc_unprotect_object (l->self_scm()); $$->set_spot (THIS->here_input ()); } | E_RIGHTSQUARE { @@ -1163,8 +1404,7 @@ command_element: $$ = MY_MAKE_MUSIC("EventChord"); $$->set_mus_property ("elements", scm_cons (l->self_scm (), SCM_EOL)); $$->set_spot (THIS->here_input ()); - scm_gc_unprotect_object (l->self_scm()); - + scm_gc_unprotect_object (l->self_scm()); } | E_BACKSLASH { $$ = MY_MAKE_MUSIC("VoiceSeparator"); @@ -1185,7 +1425,7 @@ command_element: $$ = csm; $$->set_spot (THIS->here_input ()); - csm->set_mus_property ("context-type", scm_makfrom0str ("Timing")); + csm->set_mus_property ("context-type", ly_symbol2scm ("Timing")); } | PARTIAL duration_length { Moment m = - unsmob_duration ($2)->get_length (); @@ -1196,7 +1436,7 @@ command_element: scm_gc_unprotect_object (p->self_scm ()); $$ =sp ; - sp-> set_mus_property ("context-type", scm_makfrom0str ("Timing")); + sp-> set_mus_property ("context-type", ly_symbol2scm ("Timing")); } | CLEF STRING { static SCM proc ; @@ -1208,34 +1448,13 @@ command_element: $$ = unsmob_music (result); } | TIME_T fraction { - Music * p1 = set_property_music (ly_symbol2scm ( "timeSignatureFraction"), $2); - - int l = gh_scm2int (ly_car ($2)); - int o = gh_scm2int (ly_cdr ($2)); - - Moment one_beat = Moment (1)/Moment (o); - Moment len = Moment (l) * one_beat; - - - Music *p2 = set_property_music (ly_symbol2scm ("measureLength"), len.smobbed_copy ()); - Music *p3 = set_property_music (ly_symbol2scm ("beatLength"), one_beat.smobbed_copy ()); - - SCM list = scm_list_n (p1->self_scm (), p2->self_scm (), p3->self_scm(), SCM_UNDEFINED); - Music *seq = MY_MAKE_MUSIC("SequentialMusic"); - seq->set_mus_property ("elements", list); - - - Music * sp = MY_MAKE_MUSIC("ContextSpeccedMusic"); - sp->set_mus_property ("element", seq->self_scm ()); - - scm_gc_unprotect_object (p3->self_scm ()); - scm_gc_unprotect_object (p2->self_scm ()); - scm_gc_unprotect_object (p1->self_scm ()); - scm_gc_unprotect_object (seq->self_scm ()); - - $$ = sp; + static SCM proc; + if (!proc) + proc = scm_c_eval_string ("make-time-signature-set"); - sp-> set_mus_property ("context-type", scm_makfrom0str ( "Timing")); + SCM result = scm_apply_2 (proc, gh_car ($2), gh_cdr ($2), SCM_EOL); + scm_gc_protect_object (result); + $$ = unsmob_music (result); } ; @@ -1251,28 +1470,11 @@ shorthand_command_req: | hyphen_req { $$ = $1; } - | '~' { - $$ = MY_MAKE_MUSIC("TieEvent"); - } - | '[' { - Music *b= MY_MAKE_MUSIC("BeamEvent"); - b->set_mus_property ("span-direction", gh_int2scm (START)) -; - $$ =b; - - - THIS->last_beam_start_ = b->self_scm (); - } - | ']' { - Music *b= MY_MAKE_MUSIC("BeamEvent"); - b->set_mus_property ("span-direction", gh_int2scm (STOP)); - $$ = b; - } | BREATHE { $$ = MY_MAKE_MUSIC("BreathingSignEvent"); } | E_TILDE { - $$ = MY_MAKE_MUSIC("PorrectusEvent"); + $$ = MY_MAKE_MUSIC("PesOrFlexaEvent"); } ; @@ -1300,32 +1502,63 @@ verbose_command_req: $$ = key; } | KEY NOTENAME_PITCH SCM_IDENTIFIER { + Music *key= MY_MAKE_MUSIC("KeyChangeEvent"); - - key->set_mus_property ("pitch-alist", $3); - ((Music*)key)->transpose (* unsmob_pitch ($2)); - $$ = key; + if (scm_ilength ($3) > 0) + { + key->set_mus_property ("pitch-alist", $3); + key->set_mus_property ("tonic", Pitch (0,0,0).smobbed_copy()); + ((Music*)key)->transpose (* unsmob_pitch ($2)); + } else { + THIS->parser_error (_("Second argument must be pitch list.")); + } + + $$ = key; } ; post_events: /* empty */ { - $$ = new Link_array; + $$ = SCM_EOL; } | post_events post_event { $2->set_spot (THIS->here_input ()); - $$->push ($2); + $$ = gh_cons ($2->self_scm(), $$); + scm_gc_unprotect_object ($2->self_scm()); + } + | post_events tagged_post_event { + $2 -> set_spot (THIS->here_input ()); + $$ = scm_cons ($2->self_scm(), $$); + scm_gc_unprotect_object ($2->self_scm()); + } + ; + + +tagged_post_event: + '-' TAG embedded_scm post_event { + tag_music ($4, $3, THIS->here_input ()); + $$ = $4; } ; post_event: - verbose_event - | event_with_dir - | close_event - | string_event + direction_less_event { + $$ = $1; + } + | script_dir direction_reqd_event { + if ($1) + $2->set_mus_property ("direction", gh_int2scm ($1)); + $$ = $2; + } + | script_dir direction_less_event { + if ($1) + $2->set_mus_property ("direction", gh_int2scm ($1)); + $$ = $2; + } + | string_number_event ; -string_event: +string_number_event: E_UNSIGNED { Music * s = MY_MAKE_MUSIC("StringNumberEvent"); s->set_mus_property ("string-number", gh_int2scm($1)); @@ -1335,30 +1568,44 @@ string_event: ; -event_that_take_dir: - gen_text_def - | verbose_event - | close_event - | open_event - | script_abbreviation { - SCM s = THIS->lexer_->lookup_identifier ("dash" + ly_scm2string ($1)); - Music *a = MY_MAKE_MUSIC("ArticulationEvent"); - if (gh_string_p (s)) - a->set_mus_property ("articulation-type", s); - else THIS->parser_error (_ ("Expecting string as script definition")); - $$ = a; - } - ; +direction_less_event: + '[' { -event_with_dir: - script_dir event_that_take_dir { - $2->set_mus_property ("direction", gh_int2scm ($1)); - $$ = $2; + +/* + +TODO: should take all these defs out of the parser, adn make use +configurable, i.e. + + +(set-articulation '~ "trill") + +*/ + Music * m = MY_MAKE_MUSIC ("BeamEvent"); + m->set_spot (THIS->here_input()); + m->set_mus_property ("span-direction" , gh_int2scm (START)); + $$ = m; } - ; - -verbose_event: - EVENT_IDENTIFIER { + | ']' { + Music * m = MY_MAKE_MUSIC ("BeamEvent"); + m->set_spot (THIS->here_input()); + m->set_mus_property ("span-direction" , gh_int2scm (STOP)); + $$ = m; + } + | '~' { + Music * m = MY_MAKE_MUSIC ("TieEvent"); + m->set_spot (THIS->here_input()); + $$ = m; + } + | close_event { + $$ = $1; + dynamic_cast ($$)->set_mus_property ("span-direction", gh_int2scm (START)); + } + | open_event { + $$ = $1; + dynamic_cast ($$)->set_mus_property ("span-direction", gh_int2scm (STOP)); + } + | EVENT_IDENTIFIER { $$ = unsmob_music ($1); } | tremolo_type { @@ -1367,8 +1614,22 @@ verbose_event: a->set_mus_property ("tremolo-type", gh_int2scm ($1)); $$ = a; } + ; + +direction_reqd_event: + gen_text_def { + $$ = $1; + } + | script_abbreviation { + SCM s = THIS->lexer_->lookup_identifier ("dash" + ly_scm2string ($1)); + Music *a = MY_MAKE_MUSIC("ArticulationEvent"); + if (gh_string_p (s)) + a->set_mus_property ("articulation-type", s); + else THIS->parser_error (_ ("Expecting string as script definition")); + $$ = a; + } ; - + sup_quotes: '\'' { $$ = 1; @@ -1393,15 +1654,13 @@ steno_pitch: } | NOTENAME_PITCH sup_quotes { Pitch p = *unsmob_pitch ($1); - p.octave_ += $2; + p = p.transposed (Pitch ($2,0,0)); $$ = p.smobbed_copy (); } | NOTENAME_PITCH sub_quotes { Pitch p =* unsmob_pitch ($1); - - p.octave_ += -$2; + p = p.transposed (Pitch (-$2,0,0)); $$ = p.smobbed_copy (); - } ; @@ -1415,15 +1674,14 @@ steno_tonic_pitch: } | TONICNAME_PITCH sup_quotes { Pitch p = *unsmob_pitch ($1); - p.octave_ += $2; + p = p.transposed (Pitch ($2,0,0)); $$ = p.smobbed_copy (); } | TONICNAME_PITCH sub_quotes { Pitch p =* unsmob_pitch ($1); - p.octave_ += -$2; + p = p.transposed (Pitch (-$2,0,0)); $$ = p.smobbed_copy (); - } ; @@ -1431,31 +1689,16 @@ pitch: steno_pitch { $$ = $1; } - | explicit_pitch { - $$ = $1; - } ; -explicit_pitch: - PITCH embedded_scm { - $$ = $2; - if (!unsmob_pitch ($2)) { - THIS->parser_error (_f ("Expecting musical-pitch value", 3)); - $$ = Pitch ().smobbed_copy (); - } - } +pitch_also_in_chords: + pitch + | steno_tonic_pitch ; -verbose_duration: - DURATION embedded_scm { - $$ = $2; - if (!unsmob_duration ($2)) - { - THIS->parser_error (_ ("Must have duration object")); - $$ = Duration ().smobbed_copy (); - } - } - ; + + + extender_req: EXTENDER { @@ -1474,14 +1717,6 @@ hyphen_req: ; close_event: - close_event_parens { - $$ = $1; - dynamic_cast ($$)->set_mus_property ("span-direction", gh_int2scm (START)) -; - } - ; - -close_event_parens: '(' { Music * s= MY_MAKE_MUSIC("SlurEvent"); $$ = s; @@ -1506,14 +1741,6 @@ close_event_parens: open_event: - open_event_parens { - $$ = $1; - dynamic_cast ($$)->set_mus_property ("span-direction", gh_int2scm (STOP)) -; - } - ; - -open_event_parens: E_EXCLAMATION { Music *s = MY_MAKE_MUSIC("CrescendoEvent"); s->set_spot (THIS->here_input()); @@ -1535,24 +1762,22 @@ open_event_parens: ; gen_text_def: - embedded_scm { + full_markup { Music *t = MY_MAKE_MUSIC("TextScriptEvent"); t->set_mus_property ("text", $1); t->set_spot (THIS->here_input ()); - $$ = t; + $$ = t; } | string { Music *t = MY_MAKE_MUSIC("TextScriptEvent"); - t->set_mus_property ("text", $1); + t->set_mus_property ("text", make_simple_markup ($1)); t->set_spot (THIS->here_input ()); $$ = t; + } | DIGIT { - String ds = to_string ($1); - Music * t = MY_MAKE_MUSIC("TextScriptEvent"); - SCM finger = ly_symbol2scm ("finger"); - t->set_mus_property ("text", scm_makfrom0str (ds.to_str0 ())); - t->set_mus_property ("text-type" , finger); + Music * t = MY_MAKE_MUSIC("FingerEvent"); + t->set_mus_property ("digit", gh_int2scm ($1)); t->set_spot (THIS->here_input ()); $$ = t; } @@ -1588,14 +1813,6 @@ script_dir: | '-' { $$ = CENTER; } ; -pre_events: - /* empty */ { /* SR conflict */ - $$ = new Link_array; - } - | pre_events open_event { - $$->push ($2); - } - ; absolute_pitch: steno_pitch { @@ -1607,9 +1824,6 @@ duration_length: multiplied_duration { $$ = $1; } - | verbose_duration { - $$ = $1; - } ; optional_notemode_duration: @@ -1625,10 +1839,6 @@ optional_notemode_duration: THIS->beam_check ($$); } - | verbose_duration { - $$ = $1; - THIS->default_duration_ = *unsmob_duration ($$); - } ; steno_duration: @@ -1696,9 +1906,18 @@ tremolo_type: ; + +/***************************************************************** + BASS FIGURES +*****************************************************************/ bass_number: - DIGIT - | UNSIGNED + DIGIT { + $$ = scm_number_to_string (gh_int2scm ($1), gh_int2scm (10)); + } + | UNSIGNED { + $$ = scm_number_to_string (gh_int2scm ($1), gh_int2scm (10)); + } + | STRING { $$ = $1; } ; bass_mod: @@ -1717,7 +1936,7 @@ bass_figure: Music *bfr = MY_MAKE_MUSIC("BassFigureEvent"); $$ = bfr->self_scm(); - bfr->set_mus_property ("figure", gh_int2scm ($1)); + bfr->set_mus_property ("figure", $1); scm_gc_unprotect_object ($$); } @@ -1815,7 +2034,6 @@ simple_element: | RESTNAME optional_notemode_duration { Input i = THIS->pop_spot (); - SCM e = SCM_UNDEFINED; Music * ev = 0; if (ly_scm2string ($1) =="s") { /* Space */ @@ -1845,8 +2063,11 @@ simple_element: scm_gc_protect_object (mus); $$ = unsmob_music (mus); } - | STRING optional_notemode_duration { + + | lyric_element optional_notemode_duration { Input i = THIS->pop_spot (); + if (!THIS->lexer_->lyric_state_b ()) + THIS->parser_error (_ ("Have to be in Lyric mode for lyrics")); Music * lreq = MY_MAKE_MUSIC("LyricEvent"); lreq->set_mus_property ("text", $1); @@ -1857,111 +2078,90 @@ simple_element: $$= velt; } - | chord { + | new_chord { THIS->pop_spot (); - if (!THIS->lexer_->chord_state_b ()) - THIS->parser_error (_ ("Have to be in Chord mode for chords")); - $$ = $1; + if (!THIS->lexer_->chord_state_b ()) + THIS->parser_error (_ ("Have to be in Chord mode for chords")); + $$ = unsmob_music ($1); } ; - -chord: - steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass { - $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2); - $$->set_spot (THIS->here_input ()); - }; - -chord_additions: - { - $$ = SCM_EOL; - } - | CHORD_COLON chord_notes { - $$ = $2; - } +lyric_element: + full_markup { $$ = $1; } + | STRING { $$ = $1 ; } ; -chord_notes: - chord_step { - $$ = $1; +new_chord: + steno_tonic_pitch optional_notemode_duration { + $$ = make_chord ($1, $2, SCM_EOL); } - | chord_notes '.' chord_step { - $$ = gh_append2 ($$, $3); + | steno_tonic_pitch optional_notemode_duration chord_separator chord_items { + SCM its = scm_reverse_x ($4, SCM_EOL); + $$ = make_chord ($1, $2, gh_cons ($3, its)); } ; -chord_subtractions: - { - $$ = SCM_EOL; - } - | CHORD_CARET chord_notes { - $$ = $2; +chord_items: + /**/ { + $$ = SCM_EOL; + } + | chord_items chord_item { + $$ = gh_cons ($2, $$); } ; - -chord_inversion: - { - $$ = SCM_EOL; +chord_separator: + CHORD_COLON { + $$ = ly_symbol2scm ("chord-colon"); } - | CHORD_SLASH steno_tonic_pitch { - $$ = $2; + | CHORD_CARET { + $$ = ly_symbol2scm ("chord-caret"); } - ; - -chord_bass: - { - $$ = SCM_EOL; + | CHORD_SLASH steno_tonic_pitch { + $$ = scm_list_n (ly_symbol2scm ("chord-slash"), $2, SCM_UNDEFINED); } | CHORD_BASS steno_tonic_pitch { - $$ = $2; + $$ = scm_list_n (ly_symbol2scm ("chord-bass"), $2, SCM_UNDEFINED); } ; -chord_step: - chord_note { - $$ = scm_cons ($1, SCM_EOL); +chord_item: + chord_separator { + $$ = $1; + } + | step_numbers { + $$ = scm_reverse_x ($1, SCM_EOL); } - | CHORDMODIFIER_PITCH { - $$ = scm_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL); + | CHORD_MODIFIER { + $$ = $1; } - | CHORDMODIFIER_PITCH chord_note { /* Ugh. */ - $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (), - $2, SCM_UNDEFINED); + ; + +step_numbers: + step_number { $$ = gh_cons ($1, SCM_EOL); } + | step_numbers '.' step_number { + $$ = gh_cons ($3, $$); } ; -chord_note: +step_number: bare_unsigned { - Pitch m; - m.notename_ = ($1 - 1) % 7; - m.octave_ = $1 > 7 ? 1 : 0; - m.alteration_ = 0; - - $$ = m.smobbed_copy (); + $$ = make_chord_step ($1, 0); } | bare_unsigned '+' { - Pitch m; - m.notename_ = ($1 - 1) % 7; - m.octave_ = $1 > 7 ? 1 : 0; - m.alteration_ = 1; - - - $$ = m.smobbed_copy (); + $$ = make_chord_step ($1, 1); } | bare_unsigned CHORD_MINUS { - Pitch m; - m.notename_ = ($1 - 1) % 7; - m.octave_ = $1 > 7 ? 1 : 0; - m.alteration_ = -1; - - $$ = m.smobbed_copy (); + $$ = make_chord_step ($1,-1); } - ; + ; /* UTILITIES + +TODO: should deprecate in favor of Scheme? + */ number_expression: number_expression '+' number_term { @@ -2003,20 +2203,11 @@ bare_number: | NUMBER_IDENTIFIER { $$ = $1; } - | REAL CM_T { - $$ = gh_double2scm (gh_scm2double ($1) CM ); - } - | REAL PT_T { - $$ = gh_double2scm (gh_scm2double ($1) PT); + | REAL NUMBER_IDENTIFIER { + $$ = gh_double2scm (gh_scm2double ($1) * gh_scm2double ($2)); } - | REAL IN_T { - $$ = gh_double2scm (gh_scm2double ($1) INCH); - } - | REAL MM_T { - $$ = gh_double2scm (gh_scm2double ($1) MM); - } - | REAL CHAR_T { - $$ = gh_double2scm (gh_scm2double ($1) CHAR); + | UNSIGNED NUMBER_IDENTIFIER { + $$ = gh_double2scm ($1 * gh_scm2double ($2)); } ; @@ -2072,6 +2263,79 @@ questions: ; + +full_markup: + MARKUP_IDENTIFIER { + $$ = $1; + } + | MARKUP + { THIS->lexer_->push_markup_state (); } + markup + { $$ = $3; + THIS->lexer_->pop_state (); + } + ; + + +/* +This should be done more dynamically if possible. +*/ +markup: + STRING { + $$ = make_simple_markup ($1); + } + | MARKUP_HEAD_MARKUP0 markup { + $$ = scm_list_n ($1, $2, SCM_UNDEFINED); + } + | MARKUP_HEAD_MARKUP0_MARKUP1 markup markup { + $$ = scm_list_n ($1, $2, $3, SCM_UNDEFINED); + } + | MARKUP_HEAD_SCM0_MARKUP1 SCM_T markup { + $$ = scm_list_n ($1, $2, $3, SCM_UNDEFINED); + } + | markup_line { + $$ = $1; + } + | MARKUP_HEAD_LIST0 markup_list { + $$ = scm_list_n ($1,$2, SCM_UNDEFINED); + } + | MARKUP_HEAD_SCM0 embedded_scm { + $$ = scm_list_n ($1, $2, SCM_UNDEFINED); + } + | MARKUP_HEAD_SCM0_SCM1_MARKUP2 embedded_scm embedded_scm markup { + $$ = scm_list_n ($1, $2, $3, $4, SCM_UNDEFINED); + } + | MARKUP_HEAD_SCM0_SCM1_SCM2 embedded_scm embedded_scm embedded_scm { + $$ = scm_list_n ($1, $2, $3, $4, SCM_UNDEFINED); + } + | MARKUP_IDENTIFIER { + $$ = $1; + } + + ; + +markup_list: + chord_open markup_list_body chord_close { $$ = scm_reverse_x ($2, SCM_EOL); } + ; + +markup_line: + '{' markup_list_body '}' { + static SCM line ; + if (!line) + line = scm_c_eval_string ("line-markup"); + + $$ = scm_list_n (line, scm_reverse_x ($2, SCM_EOL), SCM_UNDEFINED); + } + ; + +markup_list_body: + /**/ { $$ = SCM_EOL; } + | markup_list_body markup { + $$ = gh_cons ($2, $1) ; + } + ; + + %% void @@ -2116,8 +2380,11 @@ My_lily_parser::beam_check (SCM dur) } + + /* -It is a little strange, to have this function in this file, but + +It is a little strange to have this function in this file, but otherwise, we have to import music classes into the lexer. */ @@ -2152,6 +2419,10 @@ My_lily_lexer::try_special_identifiers (SCM * destination, SCM sid) *destination = p->self_scm(); return MUSIC_OUTPUT_DEF_IDENTIFIER; + } else if (Text_item::markup_p (sid)) { + *destination = sid; + return MARKUP_IDENTIFIER; } + return -1; }