X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fparser.yy;h=e2bbcd7d4d45796518338eeb7ffcb78a6cf4b4db;hb=d929a664c85112ffecaa16c5e114d6f75cf002e2;hp=4734db7fe3f3e2b29f76e3d5d09d1ebe4f8b617b;hpb=79eed18f68000e30c5cabaf2f5d0048dda0cb080;p=lilypond.git diff --git a/lily/parser.yy b/lily/parser.yy index 4734db7fe3..e2bbcd7d4d 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -1,69 +1,15 @@ -%{ // -*-Fundamental-*- - /* parser.yy -- Bison/C++ parser for LilyPond source file of the GNU LilyPond music typesetter - (c) 1997--2005 Han-Wen Nienhuys + (c) 1997--2006 Han-Wen Nienhuys Jan Nieuwenhuizen */ -/* -FIXME: - - * The rules for who is protecting what are very shady. Uniformise - this. - - * There are too many lexical modes? -*/ - -#include "config.hh" - -#include -#include -#include -using namespace std; - -#include "book.hh" -#include "context-def.hh" -#include "dimensions.hh" -#include "music.hh" -#include "file-path.hh" -#include "input-smob.hh" -#include "input.hh" -#include "lily-guile.hh" -#include "lilypond-input-version.hh" -#include "main.hh" -#include "misc.hh" -#include "lily-lexer.hh" -#include "lily-parser.hh" -#include "paper-book.hh" -#include "output-def.hh" -#include "scm-hash.hh" -#include "program-option.hh" -#include "score.hh" -#include "text-interface.hh" -#include "warn.hh" -#include "music.hh" - -#define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x)) - -Music *property_op_to_music (SCM op); -Music *context_spec_music (SCM type, SCM id, Music *m, SCM ops); -SCM get_next_unique_context_id (); -SCM get_next_unique_lyrics_context_id (); - -#undef _ -#if !HAVE_GETTEXT -#define _(x) x -#else -#include -#define _(x) gettext (x) -#endif +%{ #define YYERROR_VERBOSE 1 - #define YYPARSE_PARAM my_lily_parser #define YYLEX_PARAM my_lily_parser #define THIS\ @@ -77,188 +23,124 @@ SCM get_next_unique_lyrics_context_id (); ((Current).set_location ((Rhs)[1], (Rhs)[N])) -/* Add symbols to the TAGS field of a music object. */ +%} -void -tag_music (Music *m, SCM tag, Input ip) -{ - SCM tags = m->get_property ("tags"); - if (scm_is_symbol (tag)) - tags = scm_cons (tag, tags); - else if (ly_is_list (tag)) - tags = ly_append2 (tag, tags); - else - ip.warning (_ ("tag must be symbol or list of symbols")); +/* We use SCMs to do strings, because it saves us the trouble of +deleting them. Let's hope that a stack overflow doesnt trigger a move +of the parse stack onto the heap. */ - m->set_property ("tags", tags); -} +%left PREC_TOP +%left ADDLYRICS +%left PREC_BOT -bool -is_regular_identifier (SCM id) -{ - String str = ly_scm2string (id); - char const *s = str.to_str0 (); +%expect 1 - bool v = true; -#if 0 - isalpha (*s); - s++; -#endif - while (*s && v) - { - v = v && isalnum (*s); - s++; - } - return v; -} +/* One shift/reduce problem +1. \repeat + \repeat .. \alternative -SCM -get_first_context_id (SCM type, Music *m) -{ - SCM id = m->get_property ("context-id"); - if (SCM_BOOL_T == scm_equal_p (m->get_property ("context-type"), type) - && scm_is_string (m->get_property ("context-id")) - && scm_c_string_length (id) > 0) - { - return id; - } - return SCM_EOL; -} + \repeat { \repeat .. \alternative } -SCM -make_simple_markup (SCM a) -{ - return a; -} +or -bool -is_duration (int t) -{ - return t && t == 1 << intlog2 (t); -} + \repeat { \repeat } \alternative +*/ -void -set_music_properties (Music *p, SCM a) -{ - for (SCM k = a; scm_is_pair (k); k = scm_cdr (k)) - p->internal_set_property (scm_caar (k), scm_cdar (k)); -} -SCM -make_chord_step (int step, int alter) -{ - if (step == 7) - alter += FLAT; +%pure_parser +%locations - while (step < 0) - step += 7; - Pitch m ((step -1) / 7, (step - 1) % 7, alter); - return m.smobbed_copy (); -} -SCM -make_chord (SCM pitch, SCM dur, SCM modification_list) -{ - SCM chord_ctor = ly_lily_module_constant ("construct-chord"); - SCM ch = scm_call_3 (chord_ctor, pitch, dur, modification_list); +%{ // -*-Fundamental-*- - unsmob_music (ch)->protect(); - return ch; -} +/* +FIXME: -/* Todo: actually also use apply iso. call too ... */ -bool -ly_input_procedure_p (SCM x) -{ - return ly_is_procedure (x) - || (scm_is_pair (x) && ly_is_procedure (scm_car (x))); -} + * The rules for who is protecting what are very shady. Uniformise + this. -Music* -set_property_music (SCM sym, SCM value) -{ - Music *p = MY_MAKE_MUSIC ("PropertySet"); - p->set_property ("symbol", sym); - p->set_property ("value", value); - return p; -} + * There are too many lexical modes? +*/ -Music* -make_music_relative (Pitch start, Music *music) -{ - Music *relative = MY_MAKE_MUSIC ("RelativeOctaveMusic"); - relative->set_property ("element", music->self_scm ()); - - Pitch last = music->to_relative_octave (start); - if (lily_1_8_relative) - music->set_property ("last-pitch", last.smobbed_copy ()); - return relative; -} +#include "config.hh" -Music* -make_lyric_combine_music (SCM name, Music *music) -{ - Music *combine = MY_MAKE_MUSIC ("LyricCombineMusic"); - combine->set_property ("element", music->self_scm ()); - combine->set_property ("associated-context", name); - return combine; -} +#include +#include +#include +using namespace std; -%} +#include "book.hh" +#include "context-def.hh" +#include "dimensions.hh" +#include "file-path.hh" +#include "input-smob.hh" +#include "input.hh" +#include "international.hh" +#include "lily-guile.hh" +#include "lily-lexer.hh" +#include "lily-parser.hh" +#include "lilypond-input-version.hh" +#include "main.hh" +#include "misc.hh" +#include "music.hh" +#include "music.hh" +#include "output-def.hh" +#include "paper-book.hh" +#include "program-option.hh" +#include "scm-hash.hh" +#include "score.hh" +#include "text-interface.hh" +#include "warn.hh" -/* We use SCMs to do strings, because it saves us the trouble of -deleting them. Let's hope that a stack overflow doesnt trigger a move -of the parse stack onto the heap. */ +%} -%left PREC_TOP -%left ADDLYRICS -%left PREC_BOT %union { Book *book; Output_def *outputdef; SCM scm; - String *string; + std::string *string; Music *music; Score *score; int i; } -%{ -int -yylex (YYSTYPE *s, YYLTYPE *loc, void *v) -{ - Lily_parser *pars = (Lily_parser*) v; - Lily_lexer *lex = pars->lexer_; - - lex->lexval = (void*) s; - lex->lexloc = loc; - lex->prepare_for_next_token (); - return lex->yylex (); -} - - -%} +%{ -%expect 1 +#define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x)) -/* One shift/reduce problem +Music *property_op_to_music (SCM op); +Music *context_spec_music (SCM type, SCM id, Music *m, SCM ops, bool create_new); +SCM get_next_unique_context_id (); +SCM get_next_unique_lyrics_context_id (); -1. \repeat - \repeat .. \alternative +#undef _ +#if !HAVE_GETTEXT +#define _(x) x +#else +#include +#define _(x) gettext (x) +#endif - \repeat { \repeat .. \alternative } -or - \repeat { \repeat } \alternative -*/ +Music *make_lyric_combine_music (SCM name, Music *music); +Music *make_music_relative (Pitch start, Music *music); +Music *run_music_function (Lily_parser *, SCM expr); +Music *set_property_music (SCM sym, SCM value); +SCM get_first_context_id (SCM type, Music *m); +SCM make_chord (SCM pitch, SCM dur, SCM modification_list); +SCM make_chord_step (int step, int alter); +SCM make_simple_markup (SCM a); +bool is_duration (int t); +bool is_regular_identifier (SCM id); +bool ly_input_procedure_p (SCM x); +int yylex (YYSTYPE *s, YYLTYPE *loc, void *v); +void set_music_properties (Music *p, SCM a); - -%pure_parser -%locations +%} /* The third option is an alias that will be used to display the syntax error. Bison CVS now correctly handles backslash escapes. @@ -273,12 +155,10 @@ or %token ADDQUOTE "\\addquote" %token ALIAS "\\alias" %token ALTERNATIVE "\\alternative" -%token BAR "\\bar" %token BOOK "\book" %token CHANGE "\\change" %token CHORDMODE "\\chordmode" %token CHORDS "\\chords" -%token CLEF "\\clef" %token CONSISTS "\\consists" %token CONTEXT "\\context" %token DEFAULT "\\default" @@ -318,7 +198,6 @@ or %token SET "\\set" %token SIMULTANEOUS "\\simultaneous" %token SKIP "\\skip" -%token TAG "\\tag" %token TEMPO "\\tempo" %token TIMES "\\times" %token TRANSPOSE "\\transpose" @@ -372,8 +251,7 @@ If we give names, Bison complains. %token E_UNSIGNED %token UNSIGNED -%token IDENTIFIER - +%token BOOK_IDENTIFIER %token CHORDMODIFIER_PITCH %token CHORD_MODIFIER %token CONTEXT_DEF_IDENTIFIER @@ -407,6 +285,8 @@ If we give names, Bison complains. %token MUSIC_FUNCTION_SCM_SCM %token MUSIC_FUNCTION_SCM_SCM_MUSIC %token MUSIC_FUNCTION_SCM_SCM_SCM +%token MUSIC_FUNCTION_SCM_SCM_SCM_MUSIC +%token MUSIC_FUNCTION_SCM_SCM_SCM_SCM_MUSIC %token MUSIC_IDENTIFIER %token NOTENAME_PITCH %token NUMBER_IDENTIFIER @@ -436,7 +316,6 @@ If we give names, Bison complains. %type tremolo_type %type Composite_music -%type Generic_prefix_music %type Grouped_music_list %type Music %type Prefix_composite_music @@ -460,12 +339,12 @@ If we give names, Bison complains. %type relative_music %type simple_element %type string_number_event -%type tagged_post_event %type tempo_event %type toplevel_music %type output_def_body %type output_def_head +%type output_def_head_with_mode_switch %type output_def %type paper_block @@ -475,6 +354,9 @@ If we give names, Bison complains. %type absolute_pitch %type assignment_id %type bare_number +%type music_function_event +%type music_function_chord_body +%type music_function_musicless_prefix %type bass_figure %type figured_bass_modification %type br_bass_figure @@ -520,6 +402,7 @@ If we give names, Bison complains. %type object_id_setting %type octave_check %type optional_context_mod +%type optional_id %type optional_notemode_duration %type pitch %type pitch_also_in_chords @@ -535,6 +418,7 @@ If we give names, Bison complains. %type step_number %type step_numbers %type string +%type function_scm_argument %type score_block %type score_body @@ -570,9 +454,6 @@ object_id_setting: toplevel_expression: lilypond_header { THIS->lexer_->set_identifier (ly_symbol2scm ("$defaultheader"), $1); - } - | add_quote { - } | book_block { Book *book = $1; @@ -652,9 +533,13 @@ assignment: assignment_id '=' identifier_init { if (! is_regular_identifier ($1)) { +#if 0 + /* no longer valid with dashes in \paper{} block. */ @1.warning (_ ("identifier should have alphabetic characters only")); +#endif } + THIS->lexer_->set_identifier ($1, $3); /* @@ -674,6 +559,10 @@ identifier_init: $$ = $1->self_scm (); $1->unprotect (); } + | book_block { + $$ = $1->self_scm (); + $1->unprotect (); + } | output_def { $$ = $1->self_scm (); $1->unprotect (); @@ -757,6 +646,10 @@ book_body: $$->paper_->unprotect (); $$->header_ = THIS->lexer_->lookup_identifier ("$defaultheader"); } + | BOOK_IDENTIFIER { + $$ = unsmob_book ($1); + $$->set_spot (@$); + } | book_body paper_block { $$->paper_ = $2; $2->unprotect (); @@ -817,7 +710,7 @@ score_body: } else { - $$->defs_.push ($2); + $$->add_output_def ($2); } $2->unprotect (); } @@ -871,21 +764,25 @@ output_def_head: } ; +output_def_head_with_mode_switch: + output_def_head { + THIS->lexer_->push_initial_state (); + $$ = $1; + } + ; output_def_body: - output_def_head '{' { + output_def_head_with_mode_switch '{' { $$ = $1; $$->input_origin_.set_spot (@$); - THIS->lexer_->push_initial_state (); } - | output_def_head '{' OUTPUT_DEF_IDENTIFIER { + | output_def_head_with_mode_switch '{' OUTPUT_DEF_IDENTIFIER { $1->unprotect (); Output_def *o = unsmob_output_def ($3); o->input_origin_.set_spot (@$); $$ = o; THIS->lexer_->remove_scope (); THIS->lexer_->add_scope (o->scope_); - THIS->lexer_->push_initial_state (); } | output_def_body assignment { @@ -975,6 +872,7 @@ Alternative_music: Repeated_music: REPEAT simple_string bare_unsigned Music Alternative_music { + /*TODO: move to Scheme.*/ Music *beg = $4; int times = $3; SCM alts = scm_is_pair ($5) ? scm_car ($5) : SCM_EOL; @@ -1067,7 +965,6 @@ Simple_music: | context_change ; - optional_context_mod: /**/ { $$ = SCM_EOL; } | WITH { THIS->lexer_->push_initial_state (); } @@ -1085,7 +982,6 @@ context_mod_list: } ; - Composite_music: Prefix_composite_music { $$ = $1; } | Grouped_music_list { $$ = $1; } @@ -1096,33 +992,34 @@ Grouped_music_list: | Sequential_music { $$ = $1; } ; +function_scm_argument: + embedded_scm + | simple_string + ; + +/* +TODO: use code generation for this +*/ Generic_prefix_music_scm: MUSIC_FUNCTION { $$ = scm_list_2 ($1, make_input (@$)); } - | MUSIC_FUNCTION_SCM embedded_scm { + | MUSIC_FUNCTION_SCM function_scm_argument { $$ = scm_list_3 ($1, make_input (@$), $2); } | MUSIC_FUNCTION_MARKUP full_markup { $$ = scm_list_3 ($1, make_input (@$), $2); } - | MUSIC_FUNCTION_MUSIC Music { - $$ = scm_list_3 ($1, make_input (@$), $2->self_scm ()); + | music_function_musicless_prefix Music { + $$ = ly_append2 ($1, scm_list_1 ($2->self_scm ())); $2->unprotect (); } - | MUSIC_FUNCTION_SCM_MUSIC embedded_scm Music { - $$ = scm_list_4 ($1, make_input (@$), $2, $3->self_scm ()); - $3->unprotect (); - } - | MUSIC_FUNCTION_SCM_SCM embedded_scm embedded_scm { + | MUSIC_FUNCTION_SCM_SCM function_scm_argument function_scm_argument { $$ = scm_list_4 ($1, make_input (@$), $2, $3); } - | MUSIC_FUNCTION_SCM_SCM_SCM embedded_scm embedded_scm embedded_scm { + | MUSIC_FUNCTION_SCM_SCM_SCM function_scm_argument function_scm_argument function_scm_argument { $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4); } - | MUSIC_FUNCTION_SCM_SCM_MUSIC embedded_scm embedded_scm Music { - $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4->self_scm ()); - } | MUSIC_FUNCTION_MARKUP_MUSIC full_markup Music { $$ = scm_list_4 ($1, make_input (@$), $2, $3->self_scm ()); $3->unprotect (); @@ -1135,7 +1032,7 @@ Generic_prefix_music_scm: $2->unprotect (); $3->unprotect (); } - | MUSIC_FUNCTION_SCM_MUSIC_MUSIC embedded_scm Music Music { + | MUSIC_FUNCTION_SCM_MUSIC_MUSIC function_scm_argument Music Music { $$ = scm_list_5 ($1, make_input (@$), $2, $3->self_scm (), $4->self_scm ()); $4->unprotect (); $3->unprotect (); @@ -1147,63 +1044,29 @@ Generic_prefix_music_scm: } ; -Generic_prefix_music: - Generic_prefix_music_scm { - SCM func = scm_car ($1); - Input *loc = unsmob_input (scm_cadr ($1)); - SCM args = scm_cddr ($1); - SCM sig = scm_object_property (func, ly_symbol2scm ("music-function-signature")); - - SCM type_check_proc = ly_lily_module_constant ("type-check-list"); - bool ok = true; - - if (!to_boolean (scm_call_3 (type_check_proc, scm_cadr ($1), sig, args))) - { - THIS->error_level_ = 1; - ok = false; - } - - SCM m = SCM_EOL; - if (ok) - m = scm_apply_0 (func, scm_cons (THIS->self_scm(), - scm_cdr ($1))); - - if (unsmob_music (m)) - { - $$ = unsmob_music (m); - $$->protect (); - } - else - { - if (ok) - loc->error (_ ("music head function must return Music object")); - $$ = MY_MAKE_MUSIC ("Music"); - } - $$->set_spot (*loc); +optional_id: + /**/ { $$ = SCM_EOL; } + | '=' simple_string { + $$ = $2; } - ; + ; Prefix_composite_music: - Generic_prefix_music { - $$ = $1; - } - | CONTEXT simple_string '=' simple_string optional_context_mod Music { - $$ = context_spec_music ($2, $4, $6, $5); - + Generic_prefix_music_scm { + $$ = run_music_function (THIS, $1); } - | CONTEXT simple_string optional_context_mod Music { - $$ = context_spec_music ($2, SCM_UNDEFINED, $4, $3); + | CONTEXT simple_string optional_id optional_context_mod Music { + $$ = context_spec_music ($2, $3, $5, $4, false); } - | NEWCONTEXT simple_string optional_context_mod Music { - $$ = context_spec_music ($2, get_next_unique_context_id (), $4, - $3); + | NEWCONTEXT simple_string optional_id optional_context_mod Music { + $$ = context_spec_music ($2, $3, $5, $4, true); } | TIMES fraction Music - { - int n = scm_to_int (scm_car ($2)); int d = scm_to_int (scm_cdr ($2)); + int n = scm_to_int (scm_car ($2)); + int d = scm_to_int (scm_cdr ($2)); Music *mp = $3; $$= MY_MAKE_MUSIC ("TimeScaledMusic"); @@ -1242,8 +1105,7 @@ Prefix_composite_music: THIS->lexer_->pop_state (); } | mode_changing_head_with_context optional_context_mod Grouped_music_list { - $$ = context_spec_music ($1, get_next_unique_context_id (), - $3, $2); + $$ = context_spec_music ($1, SCM_UNDEFINED, $3, $2, true); if ($1 == ly_symbol2scm ("ChordNames")) { Music *chm = MY_MAKE_MUSIC ("UnrelativableMusic"); @@ -1255,10 +1117,6 @@ Prefix_composite_music: } | relative_music { $$ = $1; } | re_rhythmed_music { $$ = $1; } - | TAG embedded_scm Music { - tag_music ($3, $2, @$); - $$ = $3; - } ; mode_changing_head: @@ -1363,7 +1221,7 @@ re_rhythmed_music: name = get_next_unique_lyrics_context_id (); voice = context_spec_music (scm_makfrom0str ("Voice"), name, - voice, SCM_EOL); + voice, SCM_EOL, false); } SCM context = scm_makfrom0str ("Lyrics"); @@ -1375,7 +1233,7 @@ re_rhythmed_music: Music *music = unsmob_music (scm_car (s)); Music *com = make_lyric_combine_music (name, music); Music *csm = context_spec_music (context, - get_next_unique_context_id (), com, SCM_EOL); + SCM_UNDEFINED, com, SCM_EOL, true); lst = scm_cons (csm->self_scm (), lst); } all->set_property ("elements", scm_cons (voice->self_scm (), @@ -1471,14 +1329,14 @@ music_property_def: ly_symbol2scm ("push"), scm_cadr ($2), $5, $3)); - $$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL); + $$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL, false); } | OVERRIDE context_prop_spec embedded_scm embedded_scm '=' scalar { $$ = property_op_to_music (scm_list_5 ( ly_symbol2scm ("push"), scm_cadr ($2), $6, $4, $3)); - $$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL); + $$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL, false); } | REVERT context_prop_spec embedded_scm { $$ = property_op_to_music (scm_list_3 ( @@ -1486,20 +1344,20 @@ music_property_def: scm_cadr ($2), $3)); - $$= context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL); + $$= context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL, false); } | SET context_prop_spec '=' scalar { $$ = property_op_to_music (scm_list_3 ( ly_symbol2scm ("assign"), scm_cadr ($2), $4)); - $$= context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL); + $$= context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL, false); } | UNSET context_prop_spec { $$ = property_op_to_music (scm_list_2 ( ly_symbol2scm ("unset"), scm_cadr ($2))); - $$= context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL); + $$= context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL, false); } | ONCE music_property_def { SCM e = $2->get_property ("element"); @@ -1682,17 +1540,51 @@ chord_body_element: } $$ = n; } + | music_function_chord_body { + $$ = run_music_function (THIS, $1); + $$->set_spot (@$); + } ; -add_quote: - ADDQUOTE string Music { - SCM adder = ly_lily_module_constant ("add-quotable"); - - scm_call_2 (adder, $2, $3->self_scm ()); - $3->unprotect(); +music_function_chord_body: + MUSIC_FUNCTION { + $$ = scm_list_2 ($1, make_input (@$)); + } + | music_function_musicless_prefix chord_body_element { + $$ = ly_append2 ($1, scm_list_1 ($2->self_scm ())); + $2->unprotect (); } ; +music_function_event: + music_function_musicless_prefix post_event { + $$ = ly_append2 ($1, scm_list_1 ($2->self_scm ())); + $2->unprotect (); + } + ; + +/* +TODO: use code generation for this +*/ +music_function_musicless_prefix: + MUSIC_FUNCTION_MUSIC { + $$ = scm_list_2 ($1, make_input (@$)); + } + | MUSIC_FUNCTION_SCM_MUSIC function_scm_argument { + $$ = scm_list_3 ($1, make_input (@$), $2); + } + | MUSIC_FUNCTION_SCM_SCM_MUSIC function_scm_argument function_scm_argument { + $$ = scm_list_4 ($1, make_input (@$), $2, $3); + } + | MUSIC_FUNCTION_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument { + $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4); + } + | MUSIC_FUNCTION_SCM_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument function_scm_argument { + $$ = scm_list_n ($1, make_input (@$), $2, $3, $4, $5, SCM_UNDEFINED); + } + ; + + command_element: command_event { $$ = MY_MAKE_MUSIC ("EventChord"); @@ -1708,12 +1600,6 @@ command_element: skip->set_spot (@$); $$ = skip; } - | OCTAVE pitch { - Music *m = MY_MAKE_MUSIC ("RelativeOctaveCheck"); - $$ = m; - $$->set_spot (@$); - $$->set_property ("pitch", $2); - } | E_BRACKET_OPEN { Music *m = MY_MAKE_MUSIC ("LigatureEvent"); m->set_property ("span-direction", scm_from_int (START)); @@ -1755,34 +1641,19 @@ command_element: sounds_as_c.smobbed_copy()); $$->set_spot (@$); $$ = context_spec_music (ly_symbol2scm ("Staff"), SCM_UNDEFINED, - $$, SCM_EOL); - } - | BAR STRING { - Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2); - - Music *csm = context_spec_music (ly_symbol2scm ("Timing"), SCM_UNDEFINED, - t, SCM_EOL); - $$ = context_spec_music (ly_symbol2scm ("Score"), SCM_UNDEFINED, csm, SCM_EOL); - $$->set_spot (@$); - t->set_spot (@$); + $$, SCM_EOL, false); } | PARTIAL duration_length { Moment m = - unsmob_duration ($2)->get_length (); Music *p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ()); p->set_spot (@$); p = context_spec_music (ly_symbol2scm ("Timing"), SCM_UNDEFINED, - p, SCM_EOL); + p, SCM_EOL, false); p = context_spec_music (ly_symbol2scm ("Score"), SCM_UNDEFINED, - p, SCM_EOL); + p, SCM_EOL, false); $$ = p; } - | CLEF STRING { - SCM proc = ly_lily_module_constant ("make-clef-set"); - SCM result = scm_call_1 (proc, $2); - $$ = unsmob_music (result); - $$->protect (); - } | TIME_T fraction { SCM proc = ly_lily_module_constant ("make-time-signature-set"); @@ -1840,26 +1711,17 @@ post_events: $$ = scm_cons ($2->self_scm (), $$); $2->unprotect (); } - | post_events tagged_post_event { - $2 -> set_spot (@2); - $$ = scm_cons ($2->self_scm (), $$); - $2->unprotect (); - } - ; - - -tagged_post_event: - '-' TAG embedded_scm post_event { - tag_music ($4, $3, @$); - $$ = $4; - } ; - - + post_event: direction_less_event { $$ = $1; } + | '-' music_function_event { + Music *mus = run_music_function (THIS, $2); + mus->set_spot (@1); + $$ = mus; + } | HYPHEN { if (!THIS->lexer_->is_lyric_state ()) THIS->parser_error (@1, _ ("have to be in Lyric mode for lyrics")); @@ -2196,6 +2058,7 @@ bass_figure: Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent"); $$ = bfr->self_scm (); bfr->unprotect (); + bfr->set_spot (@1); } | bass_number { Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent"); @@ -2207,6 +2070,7 @@ bass_figure: bfr->set_property ("text", $1); bfr->unprotect (); + bfr->set_spot (@1); } | bass_figure ']' { $$ = $1; @@ -2714,6 +2578,9 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid) if (scm_is_string (sid)) { *destination = sid; return STRING_IDENTIFIER; + } else if (unsmob_book (sid)) { + *destination = unsmob_book (sid)->clone ()->self_scm (); + return BOOK_IDENTIFIER; } else if (scm_is_number (sid)) { *destination = sid; return NUMBER_IDENTIFIER; @@ -2796,7 +2663,7 @@ property_op_to_music (SCM op) } Music* -context_spec_music (SCM type, SCM id, Music *m, SCM ops) +context_spec_music (SCM type, SCM id, Music *m, SCM ops, bool create_new) { Music *csm = MY_MAKE_MUSIC ("ContextSpeccedMusic"); @@ -2806,6 +2673,8 @@ context_spec_music (SCM type, SCM id, Music *m, SCM ops) csm->set_property ("context-type", scm_is_symbol (type) ? type : scm_string_to_symbol (type)); csm->set_property ("property-operations", ops); + if (create_new) + csm->set_property ("create-new", SCM_BOOL_T); if (scm_is_string (id)) csm->set_property ("context-id", id); @@ -2824,6 +2693,174 @@ get_next_unique_lyrics_context_id () { static int new_context_count; char s[128]; - snprintf (s, 1024, "uniqueContext%d", new_context_count++); + snprintf (s, sizeof (s)-1, "uniqueContext%d", new_context_count++); return scm_makfrom0str (s); } + + +Music * +run_music_function (Lily_parser *parser, SCM expr) +{ + SCM func = scm_car (expr); + Input *loc = unsmob_input (scm_cadr (expr)); + SCM args = scm_cddr (expr); + SCM sig = scm_object_property (func, ly_symbol2scm ("music-function-signature")); + + SCM type_check_proc = ly_lily_module_constant ("type-check-list"); + bool ok = true; + + if (!to_boolean (scm_call_3 (type_check_proc, scm_cadr (expr), sig, args))) + { + parser->error_level_ = 1; + ok = false; + } + + SCM m = SCM_EOL; + if (ok) + m = scm_apply_0 (func, scm_cons (parser->self_scm(), + scm_cdr (expr))); + + + Music* retval = 0; + if (unsmob_music (m)) + { + retval = unsmob_music (m); + retval->protect (); + } + else + { + if (ok) + loc->error (_ ("music head function must return Music object")); + retval = MY_MAKE_MUSIC ("Music"); + } + retval->set_spot (*loc); + return retval; +} + +bool +is_regular_identifier (SCM id) +{ + string str = ly_scm2string (id); + char const *s = str.c_str (); + + bool v = true; +#if 0 + isalpha (*s); + s++; +#endif + while (*s && v) + { + v = v && isalnum (*s); + s++; + } + return v; +} + + +SCM +get_first_context_id (SCM type, Music *m) +{ + SCM id = m->get_property ("context-id"); + if (SCM_BOOL_T == scm_equal_p (m->get_property ("context-type"), type) + && scm_is_string (m->get_property ("context-id")) + && scm_c_string_length (id) > 0) + { + return id; + } + return SCM_EOL; +} + +SCM +make_simple_markup (SCM a) +{ + return a; +} + +bool +is_duration (int t) +{ + return t && t == 1 << intlog2 (t); +} + +void +set_music_properties (Music *p, SCM a) +{ + for (SCM k = a; scm_is_pair (k); k = scm_cdr (k)) + p->internal_set_property (scm_caar (k), scm_cdar (k)); +} + + +SCM +make_chord_step (int step, int alter) +{ + if (step == 7) + alter += FLAT; + + while (step < 0) + step += 7; + Pitch m ((step -1) / 7, (step - 1) % 7, alter); + return m.smobbed_copy (); +} + + +SCM +make_chord (SCM pitch, SCM dur, SCM modification_list) +{ + SCM chord_ctor = ly_lily_module_constant ("construct-chord"); + SCM ch = scm_call_3 (chord_ctor, pitch, dur, modification_list); + + unsmob_music (ch)->protect(); + return ch; +} + + +/* Todo: actually also use apply iso. call too ... */ +bool +ly_input_procedure_p (SCM x) +{ + return ly_is_procedure (x) + || (scm_is_pair (x) && ly_is_procedure (scm_car (x))); +} + +Music* +set_property_music (SCM sym, SCM value) +{ + Music *p = MY_MAKE_MUSIC ("PropertySet"); + p->set_property ("symbol", sym); + p->set_property ("value", value); + return p; +} + +Music* +make_music_relative (Pitch start, Music *music) +{ + Music *relative = MY_MAKE_MUSIC ("RelativeOctaveMusic"); + relative->set_property ("element", music->self_scm ()); + + Pitch last = music->to_relative_octave (start); + if (lily_1_8_relative) + music->set_property ("last-pitch", last.smobbed_copy ()); + return relative; +} + +Music * +make_lyric_combine_music (SCM name, Music *music) +{ + Music *combine = MY_MAKE_MUSIC ("LyricCombineMusic"); + combine->set_property ("element", music->self_scm ()); + combine->set_property ("associated-context", name); + return combine; +} + + +int +yylex (YYSTYPE *s, YYLTYPE *loc, void *v) +{ + Lily_parser *pars = (Lily_parser*) v; + Lily_lexer *lex = pars->lexer_; + + lex->lexval = (void*) s; + lex->lexloc = loc; + lex->prepare_for_next_token (); + return lex->yylex (); +}