From c2f9f8e2223355678b0247feae7edffe358b1360 Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Sat, 23 Jul 2011 00:09:02 +0200 Subject: [PATCH] Make the parser interpret music function signatures ly:pitch? and ly:duration? --- .../extending/programming-interface.itely | 13 ++++++++- lily/include/duration.hh | 2 ++ lily/include/pitch.hh | 1 + lily/lexer.ll | 14 +++++++-- lily/parser.yy | 29 ++++++++++++++----- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/Documentation/extending/programming-interface.itely b/Documentation/extending/programming-interface.itely index acbff57119..72ca39e83d 100644 --- a/Documentation/extending/programming-interface.itely +++ b/Documentation/extending/programming-interface.itely @@ -66,7 +66,18 @@ where @item @code{@var{typeN?}} @tab a scheme @emph{type predicate} for which @code{@var{argN}} -must return @code{#t}. +must return @code{#t}. Some of these predicates are specially +recognized by the parser, making the respective values be read in +Lilypond syntax rather than in Scheme syntax. Currently these are +@code{ly:music?}, @code{markup?}, @code{ly:pitch?}, and +@code{ly:duration?}. Not all combinations are allowed: i.e., you can't +look for a duration after music since music may end @emph{optionally} +with a duration. + +If you really want to input some of those items as a Scheme rather than +a Lilypond expression, you may wrap them in a call of @code{ly:export}. +@c TODO: document what kind of argument lists are permitted in what +@c syntactical context of a music function call. @item @code{@var{music}} @tab A music expression, optionally written in scheme, with any diff --git a/lily/include/duration.hh b/lily/include/duration.hh index 003b9e8efa..69ac4872b5 100644 --- a/lily/include/duration.hh +++ b/lily/include/duration.hh @@ -56,5 +56,7 @@ private: INSTANTIATE_COMPARE (Duration, Duration::compare); DECLARE_UNSMOB (Duration, duration); +extern SCM Duration_type_p_proc; + #endif // DURATION_HH diff --git a/lily/include/pitch.hh b/lily/include/pitch.hh index 1ef59f3e94..df829b2a0d 100644 --- a/lily/include/pitch.hh +++ b/lily/include/pitch.hh @@ -106,5 +106,6 @@ INSTANTIATE_COMPARE (Pitch, Pitch::compare); extern SCM pitch_less_proc; Pitch pitch_interval (Pitch const &from, Pitch const &to); +extern SCM Pitch_type_p_proc; #endif /* PITCH_HH */ diff --git a/lily/lexer.ll b/lily/lexer.ll index 882418242d..83a7940b69 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -46,6 +46,7 @@ using namespace std; #include "context-def.hh" +#include "duration.hh" #include "identifier-smob.hh" #include "international.hh" #include "interval.hh" @@ -58,6 +59,7 @@ using namespace std; #include "music-function.hh" #include "parse-scm.hh" #include "parser.hh" +#include "pitch.hh" #include "source-file.hh" #include "std-string.hh" #include "string-convert.hh" @@ -794,11 +796,17 @@ Lily_lexer::scan_escaped_word (string str) push_extra_token (EXPECT_NO_MORE_ARGS); for (; scm_is_pair (s); s = scm_cdr (s)) { - if (scm_car (s) == ly_music_p_proc) + SCM cs = scm_car (s); + + if (cs == ly_music_p_proc) push_extra_token (EXPECT_MUSIC); - else if (scm_car (s) == ly_lily_module_constant ("markup?")) + else if (cs == Pitch_type_p_proc) + push_extra_token (EXPECT_PITCH); + else if (cs == Duration_type_p_proc) + push_extra_token (EXPECT_DURATION); + else if (cs == ly_lily_module_constant ("markup?")) push_extra_token (EXPECT_MARKUP); - else if (ly_is_procedure (scm_car (s))) + else if (ly_is_procedure (cs)) push_extra_token (EXPECT_SCM); else programming_error ("Function parameter without type-checking predicate"); } diff --git a/lily/parser.yy b/lily/parser.yy index 9b46bfe3cc..38f4eb4f23 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -270,6 +270,8 @@ If we give names, Bison complains. /* Artificial tokens, for more generic function syntax */ %token EXPECT_MARKUP; %token EXPECT_MUSIC; +%token EXPECT_PITCH; +%token EXPECT_DURATION; %token EXPECT_SCM; %token EXPECT_MARKUP_LIST /* After the last argument. */ @@ -1075,12 +1077,23 @@ function_arglist_music_last: ; function_arglist_nonmusic_last: - EXPECT_MARKUP function_arglist full_markup { + 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 { $$ = scm_cons ($3, $2); } | EXPECT_MARKUP function_arglist simple_string { $$ = scm_cons ($3, $2); } + | EXPECT_PITCH function_arglist pitch { + $$ = scm_cons ($3, $2); + } + | EXPECT_DURATION function_arglist_nonmusic_last duration_length { + $$ = scm_cons ($3, $2); + } | EXPECT_SCM function_arglist function_scm_argument { $$ = scm_cons ($3, $2); } @@ -1095,17 +1108,19 @@ function_arglist_nonmusic: EXPECT_NO_MORE_ARGS { | EXPECT_MARKUP function_arglist_nonmusic simple_string { $$ = scm_cons ($3, $2); } + | EXPECT_PITCH function_arglist_nonmusic pitch { + $$ = scm_cons ($3, $2); + } + | EXPECT_DURATION function_arglist_nonmusic duration_length { + $$ = scm_cons ($3, $2); + } | EXPECT_SCM function_arglist_nonmusic function_scm_argument { $$ = scm_cons ($3, $2); } ; -function_arglist: EXPECT_NO_MORE_ARGS { - /* This is for 0-ary functions, so they don't need to - read a lookahead token */ - $$ = SCM_EOL; - } - | function_arglist_music_last +function_arglist: + function_arglist_music_last | function_arglist_nonmusic_last ; -- 2.39.5