X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=lily%2Fparser.yy;h=4c5413acdd595138a48d1dfe441c97c63ce3f267;hb=881fede3d7f33766c404d90303f7a929b58c7316;hp=eb0dc92973cdfca60a387539bfdca3a196a8010c;hpb=5150591b92618e65e8718e72dfd6230d4cfba438;p=lilypond.git diff --git a/lily/parser.yy b/lily/parser.yy index eb0dc92973..4c5413acdd 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 - - -#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,186 +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 ADDLYRICS %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 - -/* One shift/reduce problem +#define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x)) -1. \repeat - \repeat .. \alternative +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 (); - \repeat { \repeat .. \alternative } +#undef _ +#if !HAVE_GETTEXT +#define _(x) x +#else +#include +#define _(x) gettext (x) +#endif -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. @@ -271,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" @@ -316,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" @@ -348,15 +229,12 @@ or %token E_OPEN "\\(" %token E_BRACKET_CLOSE "\\]" %token E_ANGLE_OPEN "\\<" +%token E_PLUS "\\+" %token E_TILDE "\\~" %token EXTENDER "__" -/* These used at all? - %token FIGURE_BRACKET_CLOSE - %token FIGURE_BRACKET_OPEN - -parser.yy:348.8-25: warning: symbol `"\\>"' used more than once as a literal string -parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal string +/* +If we give names, Bison complains. */ %token FIGURE_CLOSE /* "\\>" */ %token FIGURE_OPEN /* "\\<" */ @@ -373,8 +251,7 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %token E_UNSIGNED %token UNSIGNED -%token IDENTIFIER - +%token BOOK_IDENTIFIER %token CHORDMODIFIER_PITCH %token CHORD_MODIFIER %token CONTEXT_DEF_IDENTIFIER @@ -407,6 +284,7 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %token MUSIC_FUNCTION_SCM_MUSIC_MUSIC %token MUSIC_FUNCTION_SCM_SCM %token MUSIC_FUNCTION_SCM_SCM_MUSIC +%token MUSIC_FUNCTION_SCM_SCM_SCM %token MUSIC_IDENTIFIER %token NOTENAME_PITCH %token NUMBER_IDENTIFIER @@ -425,7 +303,7 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %type book_body %type bare_unsigned -%type bass_mod +%type figured_bass_alteration %type dots %type exclamations %type optional_rest @@ -436,7 +314,6 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %type tremolo_type %type Composite_music -%type Generic_prefix_music %type Grouped_music_list %type Music %type Prefix_composite_music @@ -460,12 +337,12 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %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,9 +352,12 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %type absolute_pitch %type assignment_id %type bare_number +%type music_function_event +%type music_function_chord_body %type bass_figure -%type bass_number +%type figured_bass_modification %type br_bass_figure +%type bass_number %type chord_body_elements %type chord_item %type chord_items @@ -534,6 +414,7 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %type step_number %type step_numbers %type string +%type function_scm_argument %type score_block %type score_body @@ -651,9 +532,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); /* @@ -673,6 +558,10 @@ identifier_init: $$ = $1->self_scm (); $1->unprotect (); } + | book_block { + $$ = $1->self_scm (); + $1->unprotect (); + } | output_def { $$ = $1->self_scm (); $1->unprotect (); @@ -756,6 +645,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 (); @@ -816,7 +709,7 @@ score_body: } else { - $$->defs_.push ($2); + $$->add_output_def ($2); } $2->unprotect (); } @@ -870,21 +763,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 { @@ -1095,28 +992,38 @@ Grouped_music_list: | Sequential_music { $$ = $1; } ; + +function_scm_argument: + embedded_scm + | simple_string + ; + 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 ()); - $2->unprotect (); - } - | MUSIC_FUNCTION_SCM_MUSIC embedded_scm Music { + + | MUSIC_FUNCTION_SCM_MUSIC function_scm_argument 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_MUSIC embedded_scm embedded_scm Music { + | 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_MUSIC Music { + $$ = scm_list_3 ($1, make_input (@$), $2->self_scm ()); + $2->unprotect (); + } + | MUSIC_FUNCTION_SCM_SCM_MUSIC function_scm_argument function_scm_argument Music { $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4->self_scm ()); } | MUSIC_FUNCTION_MARKUP_MUSIC full_markup Music { @@ -1131,7 +1038,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 (); @@ -1143,46 +1050,9 @@ 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); - } - ; - - Prefix_composite_music: - Generic_prefix_music { - $$ = $1; + Generic_prefix_music_scm { + $$ = run_music_function (THIS, $1); } | CONTEXT simple_string '=' simple_string optional_context_mod Music { $$ = context_spec_music ($2, $4, $6, $5); @@ -1251,10 +1121,6 @@ Prefix_composite_music: } | relative_music { $$ = $1; } | re_rhythmed_music { $$ = $1; } - | TAG embedded_scm Music { - tag_music ($3, $2, @$); - $$ = $3; - } ; mode_changing_head: @@ -1412,7 +1278,11 @@ property_operation: } | OVERRIDE simple_string embedded_scm '=' embedded_scm { $$ = scm_list_4 (ly_symbol2scm ("push"), - scm_string_to_symbol ($2), $3, $5); + scm_string_to_symbol ($2), $5, $3); + } + | OVERRIDE simple_string embedded_scm embedded_scm '=' embedded_scm { + $$ = scm_list_5 (ly_symbol2scm ("push"), + scm_string_to_symbol ($2), $6, $4, $3); } | REVERT simple_string embedded_scm { $$ = scm_list_3 (ly_symbol2scm ("pop"), @@ -1460,10 +1330,17 @@ context_prop_spec: music_property_def: OVERRIDE context_prop_spec embedded_scm '=' scalar { $$ = property_op_to_music (scm_list_4 ( - ly_symbol2scm ("poppush"), + ly_symbol2scm ("push"), scm_cadr ($2), - $3, $5)); - $$= context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL); + $5, $3)); + $$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, $$, SCM_EOL); + } + | 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); } | REVERT context_prop_spec embedded_scm { $$ = property_op_to_music (scm_list_3 ( @@ -1513,6 +1390,9 @@ simple_string: STRING { | LYRICS_STRING { $$ = $1; } + | STRING_IDENTIFIER { + $$ = $1; + } ; scalar: string { @@ -1664,8 +1544,33 @@ chord_body_element: } $$ = n; } + | music_function_chord_body { + $$ = run_music_function (THIS, $1); + $$->set_spot (@$); + } + ; + +music_function_chord_body: + MUSIC_FUNCTION { + $$ = scm_list_2 ($1, make_input (@$)); + } + | MUSIC_FUNCTION_MUSIC chord_body_element { + $$ = scm_list_3 ($1, make_input (@$), + $2->self_scm ()); + } + | MUSIC_FUNCTION_SCM_MUSIC function_scm_argument chord_body_element { + $$ = scm_list_4 ($1, make_input (@$), + $2, $3->self_scm ()); + } + | MUSIC_FUNCTION_SCM_SCM_MUSIC function_scm_argument function_scm_argument + chord_body_element { + + $$ = scm_list_5 ($1, make_input (@$), + $2, $3, $4->self_scm ()); + } ; + add_quote: ADDQUOTE string Music { SCM adder = ly_lily_module_constant ("add-quotable"); @@ -1739,15 +1644,6 @@ command_element: $$ = 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 (@$); - } | PARTIAL duration_length { Moment m = - unsmob_duration ($2)->get_length (); Music *p = set_property_music (ly_symbol2scm ( "measurePosition"),m.smobbed_copy ()); @@ -1758,13 +1654,7 @@ command_element: p, SCM_EOL); $$ = 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"); @@ -1776,7 +1666,6 @@ command_element: SCM proc = ly_lily_module_constant ("make-mark-set"); SCM result = scm_call_1 (proc, $2); - scm_gc_protect_object (result); $$ = unsmob_music (result); $$->protect (); } @@ -1823,26 +1712,30 @@ 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; +music_function_event: + MUSIC_FUNCTION_MUSIC post_event { + $$ = scm_list_3 ($1, make_input (@$), $2->self_scm ()); + } + | MUSIC_FUNCTION_SCM_MUSIC function_scm_argument post_event { + $$ = scm_list_4 ($1, make_input (@$), $2, $3->self_scm ()); + } + | MUSIC_FUNCTION_SCM_SCM_MUSIC function_scm_argument function_scm_argument post_event { + $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4->self_scm ()); } ; - + 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")); @@ -2159,20 +2052,16 @@ tremolo_type: bass_number: DIGIT { - $$ = scm_number_to_string (scm_from_int ($1), scm_from_int (10)); - $$ = scm_list_2 (ly_lily_module_constant ("number-markup"), - $$); + $$ = scm_from_int ($1); } | UNSIGNED { - $$ = scm_number_to_string (scm_from_int ($1), scm_from_int (10)); - $$ = scm_list_2 (ly_lily_module_constant ("number-markup"), - $$); + $$ = scm_from_int ($1); } | STRING { $$ = $1; } | full_markup { $$ = $1; } ; -bass_mod: +figured_bass_alteration: '-' { $$ = -2; } | '+' { $$ = 2; } | '!' { $$ = 0; } @@ -2183,15 +2072,25 @@ 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"); $$ = bfr->self_scm (); - bfr->set_property ("figure", $1); + if (scm_is_number ($1)) + bfr->set_property ("figure", $1); + else if (Text_interface::is_markup ($1)) + bfr->set_property ("text", $1); + bfr->unprotect (); + bfr->set_spot (@1); + } + | bass_figure ']' { + $$ = $1; + unsmob_music ($1)->set_property ("bracket-stop", SCM_BOOL_T); } - | bass_figure bass_mod { + | bass_figure figured_bass_alteration { Music *m = unsmob_music ($1); if ($2) { SCM salter = m->get_property ("alteration"); @@ -2202,19 +2101,43 @@ bass_figure: m->set_property ("alteration", scm_from_int (0)); } } + | bass_figure figured_bass_modification { + Music *m = unsmob_music ($1); + if ($2 == ly_symbol2scm ("plus")) + { + m->set_property ("augmented", SCM_BOOL_T); + } + else if ($2 == ly_symbol2scm ("slash")) + { + m->set_property ("diminished", SCM_BOOL_T); + } + else if ($2 == ly_symbol2scm ("exclamation")) + { + m->set_property ("no-continuation", SCM_BOOL_T); + } + } ; -br_bass_figure: - '[' bass_figure { - $$ = $2; - unsmob_music ($$)->set_property ("bracket-start", SCM_BOOL_T); + +figured_bass_modification: + E_PLUS { + $$ = ly_symbol2scm ("plus"); } - | bass_figure { - $$ = $1; + | E_EXCLAMATION { + $$ = ly_symbol2scm ("exclamation"); + } + | '/' { + $$ = ly_symbol2scm ("slash"); } - | br_bass_figure ']' { + ; + +br_bass_figure: + bass_figure { $$ = $1; - unsmob_music ($1)->set_property ("bracket-stop", SCM_BOOL_T); + } + | '[' bass_figure { + $$ = $2; + unsmob_music ($$)->set_property ("bracket-start", SCM_BOOL_T); } ; @@ -2669,6 +2592,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; @@ -2698,7 +2624,7 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid) *destination = p->self_scm (); return OUTPUT_DEF_IDENTIFIER; - } else if (Text_interface::markup_p (sid)) { + } else if (Text_interface::is_markup (sid)) { *destination = sid; if (is_lyric_state ()) return LYRIC_MARKUP_IDENTIFIER; @@ -2716,7 +2642,7 @@ property_op_to_music (SCM op) SCM symbol = scm_cadr (op); SCM args = scm_cddr (op); SCM grob_val = SCM_UNDEFINED; - SCM grob_sym = SCM_UNDEFINED; + SCM grob_path = SCM_UNDEFINED; SCM val = SCM_UNDEFINED; if (tag == ly_symbol2scm ("assign")) @@ -2726,16 +2652,16 @@ property_op_to_music (SCM op) } else if (tag == ly_symbol2scm ("unset")) m = MY_MAKE_MUSIC ("PropertyUnset"); - else if (tag == ly_symbol2scm ("poppush") - || tag == ly_symbol2scm ("push")) + else if (tag == ly_symbol2scm ("push")) { m = MY_MAKE_MUSIC ("OverrideProperty"); - grob_sym = scm_car (args); - grob_val = scm_cadr (args); + grob_val = scm_car (args); + grob_path = scm_cdr (args); + m->set_property ("pop-first", SCM_BOOL_T); } else if (tag == ly_symbol2scm ("pop")) { m = MY_MAKE_MUSIC ("RevertProperty"); - grob_sym = scm_car (args); + grob_path = args; } m->set_property ("symbol", symbol); @@ -2744,23 +2670,8 @@ property_op_to_music (SCM op) m->set_property ("value", val); if (grob_val != SCM_UNDEFINED) m->set_property ("grob-value", grob_val); - - if (grob_sym != SCM_UNDEFINED) - { - bool itc = do_internal_type_checking_global; - /* UGH. - */ - bool autobeam = ly_is_equal (symbol, ly_symbol2scm ("autoBeamSettings")); - if (autobeam) - do_internal_type_checking_global = false; - m->set_property ("grob-property", grob_sym); - if (autobeam) - do_internal_type_checking_global = itc; - } - - if (tag == ly_symbol2scm ("poppush")) - m->set_property ("pop-first", SCM_BOOL_T); - + if (grob_path != SCM_UNDEFINED) + m->set_property ("grob-property-path", grob_path); return m; } @@ -2794,6 +2705,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) +{ + std::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 (); +}