From: David Kastrup Date: Tue, 20 Sep 2011 20:29:52 +0000 (+0200) Subject: parser.yy et al: implement optional arguments for music functions X-Git-Tag: release/2.15.13-1~26^2~1 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=6b66e44d3d9f2ea8a7ef052db1caac0355d3073c;p=lilypond.git parser.yy et al: implement optional arguments for music functions --- diff --git a/lily/lexer.ll b/lily/lexer.ll index 8a07f1b2c0..e88ed791c4 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -828,7 +828,14 @@ Lily_lexer::scan_escaped_word (string str) push_extra_token (EXPECT_NO_MORE_ARGS); for (s = scm_cdr (s); scm_is_pair (s); s = scm_cdr (s)) { + SCM optional = SCM_UNDEFINED; cs = scm_car (s); + + if (scm_is_pair (cs)) + { + optional = SCM_CDR (cs); + cs = SCM_CAR (cs); + } if (cs == ly_music_p_proc) push_extra_token (EXPECT_MUSIC); @@ -840,7 +847,13 @@ Lily_lexer::scan_escaped_word (string str) push_extra_token (EXPECT_MARKUP); else if (ly_is_procedure (cs)) push_extra_token (EXPECT_SCM); - else programming_error ("Function parameter without type-checking predicate"); + else + { + programming_error ("Function parameter without type-checking predicate"); + continue; + } + if (!scm_is_eq (optional, SCM_UNDEFINED)) + push_extra_token (EXPECT_OPTIONAL, optional); } return funtype; } diff --git a/lily/parser.yy b/lily/parser.yy index c34c4acee4..a74587fd0e 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -43,9 +43,6 @@ of the parse stack onto the heap. */ %left PREC_BOT %nonassoc REPEAT %nonassoc ALTERNATIVE -%left ADDLYRICS -%left PREC_TOP - /* The above precedences tackle the shift/reduce problem @@ -59,6 +56,20 @@ or \repeat { \repeat } \alternative */ +%right FUNCTION_ARGUMENTS + MARKUP LYRICS_STRING MARKUP_IDENTIFIER STRING STRING_IDENTIFIER + SEQUENTIAL SIMULTANEOUS DOUBLE_ANGLE_OPEN MUSIC_IDENTIFIER '{' + PITCH_IDENTIFIER NOTENAME_PITCH TONICNAME_PITCH + SCM_FUNCTION SCM_IDENTIFIER SCM_TOKEN + UNSIGNED DURATION_IDENTIFIER + + /* The above are the symbols that can start function arguments */ + +%left ADDLYRICS +%left PREC_TOP + + + %pure_parser %locations @@ -270,6 +281,7 @@ If we give names, Bison complains. %token EXPECT_DURATION "ly:duration?" %token EXPECT_SCM "scheme?" %token EXPECT_MARKUP_LIST "markup-list?" +%token EXPECT_OPTIONAL "optional?" /* After the last argument. */ %token EXPECT_NO_MORE_ARGS; @@ -402,8 +414,12 @@ If we give names, Bison complains. %type full_markup %type full_markup_list %type function_arglist +%type function_arglist_optional +%type function_arglist_keep %type function_arglist_bare %type function_arglist_closed +%type function_arglist_closed_optional +%type function_arglist_closed_keep %type identifier_init %type lilypond %type lilypond_header @@ -1114,24 +1130,133 @@ and this rule returns the reversed list of arguments. */ function_arglist: function_arglist_bare - | EXPECT_MUSIC function_arglist music { + | EXPECT_MUSIC function_arglist_optional music + { + $$ = scm_cons ($3, $2); + } + | EXPECT_SCM function_arglist_optional embedded_scm + { $$ = scm_cons ($3, $2); } - | EXPECT_SCM function_arglist embedded_scm { - $$ = scm_cons ($3, $2); + ; + +function_arglist_optional: + function_arglist_keep %prec FUNCTION_ARGUMENTS + | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_optional + { + $$ = scm_cons ($1, $3); + } + ; + +function_arglist_keep: + EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep full_markup { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep simple_string { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_keep pitch_also_in_chords { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_keep duration_length { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep simple_string + { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_keep closed_music + { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm + { + $$ = scm_cons ($4, $3); } + | function_arglist ; + function_arglist_closed: function_arglist_bare - | EXPECT_MUSIC function_arglist closed_music { + | EXPECT_MUSIC function_arglist_optional closed_music + { $$ = scm_cons ($3, $2); } - | EXPECT_SCM function_arglist embedded_scm_closed { - $$ = scm_cons ($3, $2); + | EXPECT_SCM function_arglist_optional embedded_scm_closed + { + $$ = scm_cons ($3, $2); + } + ; + +function_arglist_closed_optional: + function_arglist_closed_keep %prec FUNCTION_ARGUMENTS + | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_closed_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_closed_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_closed_optional + { + $$ = scm_cons ($1, $3); + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_closed_optional + { + $$ = scm_cons ($1, $3); } ; +function_arglist_closed_keep: + EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep full_markup { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_MARKUP function_arglist_keep simple_string { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_PITCH function_arglist_keep pitch_also_in_chords { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_keep duration_length { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep simple_string + { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_keep closed_music + { + $$ = scm_cons ($4, $3); + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm_closed + { + $$ = scm_cons ($4, $3); + } + | function_arglist_closed + ; + embedded_scm_closed: embedded_scm_bare | scm_function_call_closed @@ -1146,24 +1271,22 @@ scm_function_call_closed: function_arglist_bare: EXPECT_NO_MORE_ARGS { - /* This is for 0-ary functions, so they don't need to - read a lookahead token */ $$ = SCM_EOL; } - | EXPECT_MARKUP function_arglist full_markup { + | EXPECT_MARKUP function_arglist_optional full_markup { $$ = scm_cons ($3, $2); } - | EXPECT_MARKUP function_arglist simple_string { + | EXPECT_MARKUP function_arglist_optional simple_string { $$ = scm_cons ($3, $2); } - | EXPECT_PITCH function_arglist pitch_also_in_chords { - $$ = scm_cons ($3, $2); + | EXPECT_PITCH function_arglist_optional pitch_also_in_chords { + $$ = scm_cons ($3, $2); } - | EXPECT_DURATION function_arglist_closed duration_length { - $$ = scm_cons ($3, $2); + | EXPECT_DURATION function_arglist_closed_optional duration_length { + $$ = scm_cons ($3, $2); } - | EXPECT_SCM function_arglist simple_string { - $$ = scm_cons ($3, $2); + | EXPECT_SCM function_arglist_optional simple_string { + $$ = scm_cons ($3, $2); } ; @@ -1635,7 +1758,7 @@ music_function_chord_body_arglist: | EXPECT_MUSIC music_function_chord_body_arglist chord_body_element { $$ = scm_cons ($3, $2); } - | EXPECT_SCM function_arglist embedded_scm_chord_body { + | EXPECT_SCM function_arglist_optional embedded_scm_chord_body { $$ = scm_cons ($3, $2); } ; @@ -1665,7 +1788,7 @@ music_function_event_arglist: | EXPECT_MUSIC music_function_event_arglist post_event { $$ = scm_cons ($3, $2); } - | EXPECT_SCM function_arglist embedded_scm_event { + | EXPECT_SCM function_arglist_optional embedded_scm_event { $$ = scm_cons ($3, $2); } ; diff --git a/scm/lily.scm b/scm/lily.scm index 6230940860..ec7aebfd43 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -350,6 +350,8 @@ messages into errors.") Print a message at LOCATION if any predicate failed." (define (recursion-helper signature arguments count) (define (helper pred? arg count) + (if (pair? pred?) + (set! pred? (car pred?))) (if (not (pred? arg)) (begin (ly:input-warning