@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
INSTANTIATE_COMPARE (Duration, Duration::compare);
DECLARE_UNSMOB (Duration, duration);
+extern SCM Duration_type_p_proc;
+
#endif // DURATION_HH
extern SCM pitch_less_proc;
Pitch pitch_interval (Pitch const &from, Pitch const &to);
+extern SCM Pitch_type_p_proc;
#endif /* PITCH_HH */
using namespace std;
#include "context-def.hh"
+#include "duration.hh"
#include "identifier-smob.hh"
#include "international.hh"
#include "interval.hh"
#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"
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");
}
/* Artificial tokens, for more generic function syntax */
%token <i> EXPECT_MARKUP;
%token <i> EXPECT_MUSIC;
+%token <i> EXPECT_PITCH;
+%token <i> EXPECT_DURATION;
%token <i> EXPECT_SCM;
%token <i> EXPECT_MARKUP_LIST
/* After the last argument. */
;
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);
}
| 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
;