#include "lily-imports.hh"
void
-Lily_parser::parser_error (Input const *i, Lily_parser *parser, SCM *, const std::string &s)
+Lily_parser::parser_error (Input const *i, Lily_parser *parser, SCM *, const string &s)
{
parser->parser_error (*i, s);
}
#define _(x) gettext (x)
#endif
-using std::string;
static Music *make_music_with_input (SCM name, Input where);
SCM check_scheme_arg (Lily_parser *parser, Input loc,
SCM arg, SCM args, SCM pred, SCM disp = SCM_UNDEFINED);
SCM make_music_from_simple (Lily_parser *parser, Input loc, SCM pitch);
-SCM loc_on_music (Input loc, SCM arg);
+SCM loc_on_music (Lily_parser *parser, Input loc, SCM arg);
SCM make_chord_elements (Input loc, SCM pitch, SCM dur, SCM modification_list);
SCM make_chord_step (SCM step, Rational alter);
SCM make_simple_markup (SCM a);
-SCM make_duration (SCM t, int dots = 0);
+SCM make_duration (SCM t, int dots = 0, SCM factor = SCM_UNDEFINED);
bool is_regular_identifier (SCM id, bool multiple=false);
SCM try_string_variants (SCM pred, SCM str);
int yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser);
%token CHORD_REPETITION
%token CONTEXT_MOD_IDENTIFIER
%token DRUM_PITCH
-%token PITCH_IDENTIFIER
+ /* Artificial token for durations in argument lists */
+%token DURATION_ARG
%token DURATION_IDENTIFIER
%token EVENT_IDENTIFIER
%token EVENT_FUNCTION
%token MUSIC_IDENTIFIER
%token NOTENAME_PITCH
%token NUMBER_IDENTIFIER
+%token PITCH_IDENTIFIER
%token REAL
%token RESTNAME
%token SCM_ARG
| pitch_or_music
| FRACTION
| string
- | embedded_scm
+ | embedded_scm
| partial_markup
| full_markup_list
| context_modification
TEMPO steno_duration '=' tempo_range {
$$ = MAKE_SYNTAX (tempo, @$, SCM_EOL, $2, $4);
}
- | TEMPO scalar steno_duration '=' tempo_range {
+ | TEMPO text steno_duration '=' tempo_range {
$$ = MAKE_SYNTAX (tempo, @$, $2, $3, $5);
}
- | TEMPO scalar {
+ | TEMPO text {
$$ = MAKE_SYNTAX (tempo, @$, $2);
} %prec ':'
;
(parser, @3, $3),
$1, $2);
}
- | function_arglist_nonbackup_reparse REPARSE duration_length
+ | function_arglist_nonbackup_reparse REPARSE multiplied_duration
+ {
+ $$ = check_scheme_arg (parser, @3, $3, $1, $2);
+ }
+ | function_arglist_nonbackup_reparse REPARSE reparsed_rhythm
{
$$ = check_scheme_arg (parser, @3, $3, $1, $2);
}
}
;
+
+reparsed_rhythm:
+ DURATION_ARG dots multipliers post_events
+ {
+ $$ = make_music_from_simple (parser, @$,
+ make_duration ($1, scm_to_int ($2), $3));
+ Music *m = unsmob<Music> ($$);
+ assert (m);
+ if (scm_is_pair ($4))
+ m->set_property ("articulations",
+ scm_reverse_x ($4, SCM_EOL));
+ } %prec ':'
+ ;
+
function_arglist_nonbackup_reparse:
EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup SCM_IDENTIFIER
{
{
$$ = $3;
if (scm_is_true (scm_call_1 ($2, $4)))
+ // May be 3 \cm or similar
MYREPARSE (@4, $2, REAL, $4);
else {
SCM d = make_duration ($4);
- if (SCM_UNBNDP (d) || scm_is_false (scm_call_1 ($2, d)))
- MYREPARSE (@4, $2, REAL, $4); // trigger error
- else
- MYREPARSE (@4, $2, DURATION_IDENTIFIER, d);
+ if (!SCM_UNBNDP (d)) {
+ if (scm_is_true (scm_call_1 ($2, d)))
+ MYREPARSE (@4, $2, DURATION_IDENTIFIER, d);
+ else if (scm_is_true
+ (scm_call_1
+ ($2, make_music_from_simple (parser, @4, d))))
+ MYREPARSE (@4, $2, DURATION_ARG, d);
+ else
+ MYREPARSE (@4, $2, SCM_ARG, $4); // trigger error
+ } else
+ MYREPARSE (@4, $2, SCM_ARG, $4); // trigger error
}
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup DURATION_IDENTIFIER {
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup DURATION_IDENTIFIER
+ {
$$ = $3;
- MYREPARSE (@4, $2, DURATION_IDENTIFIER, $4);
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ MYREPARSE (@4, $2, DURATION_IDENTIFIER, $4);
+ else if (scm_is_true
+ (scm_call_1
+ ($2, make_music_from_simple (parser, @4, $4))))
+ MYREPARSE (@4, $2, DURATION_ARG, $4);
+ else
+ MYREPARSE (@4, $2, SCM_ARG, $4); // trigger error
}
;
$$ = scm_cons ($$, $3);
else
{
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (SCM_ARG, $4, @4);
}
}
{
$$ = scm_cons ($4, $3);
} else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (EVENT_IDENTIFIER, $4, @4);
}
}
} else if (scm_is_true (scm_call_1 ($2, $4)))
$$ = scm_cons ($4, $3);
else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (PITCH_IDENTIFIER, $4, @4);
}
}
} else if (scm_is_true (scm_call_1 ($2, $4)))
$$ = scm_cons ($4, $3);
else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (TONICNAME_PITCH, $4, @4);
}
}
if (scm_is_true (scm_call_1 ($2, $4)))
$$ = scm_cons ($4, $3);
else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (SCM_IDENTIFIER, $4, @4);
}
}
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup UNSIGNED
{
+ $$ = $3;
if (scm_is_true (scm_call_1 ($2, $4)))
- {
+ // May be 3 \cm or similar
MYREPARSE (@4, $2, REAL, $4);
- $$ = $3;
- } else {
+ else {
SCM d = make_duration ($4);
- if (SCM_UNBNDP (d) || scm_is_false (scm_call_1 ($2, d)))
- {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
- MYBACKUP (UNSIGNED, $4, @4);
+ if (!SCM_UNBNDP (d)) {
+ if (scm_is_true (scm_call_1 ($2, d)))
+ MYREPARSE (@4, $2, DURATION_IDENTIFIER, d);
+ else if (scm_is_true
+ (scm_call_1
+ ($2, make_music_from_simple (parser, @4, d))))
+ MYREPARSE (@4, $2, DURATION_ARG, d);
+ else {
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+ MYBACKUP (UNSIGNED, $4, @4);
+ }
} else {
- MYREPARSE (@4, $2, DURATION_IDENTIFIER, d);
- $$ = $3;
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
+ MYBACKUP (UNSIGNED, $4, @4);
}
}
}
$$ = $3;
MYREPARSE (@4, $2, REAL, $4);
} else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (REAL, $4, @4);
}
}
{
$$ = scm_cons ($4, $3);
} else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (NUMBER_IDENTIFIER, $4, @4);
}
}
if (scm_is_true (scm_call_1 ($2, $$)))
$$ = scm_cons ($$, $3);
else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (UNSIGNED, $5, @5);
parser->lexer_->push_extra_token (@4, '-');
}
MYREPARSE (@5, $2, REAL, n);
$$ = $3;
} else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (REAL, n, @5);
}
}
if (scm_is_true (scm_call_1 ($2, n))) {
$$ = scm_cons (n, $3);
} else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (NUMBER_IDENTIFIER, n, @5);
}
}
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup DURATION_IDENTIFIER
{
+ $$ = $3;
if (scm_is_true (scm_call_1 ($2, $4)))
- {
MYREPARSE (@4, $2, DURATION_IDENTIFIER, $4);
- $$ = $3;
- } else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ else if (scm_is_true
+ (scm_call_1
+ ($2, make_music_from_simple (parser, @4, $4))))
+ MYREPARSE (@4, $2, DURATION_ARG, $4);
+ else {
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (DURATION_IDENTIFIER, $4, @4);
}
}
else
$$ = scm_cons (res, $3);
else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (SCM_IDENTIFIER, $4, @4);
}
}
else
$$ = scm_cons (res, $3);
else {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
MYBACKUP (STRING, $4, @4);
}
}
$$ = check_scheme_arg (parser, @3,
$3, $1, $2);
}
- | function_arglist_backup REPARSE duration_length
+ | function_arglist_backup REPARSE multiplied_duration
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ | function_arglist_backup REPARSE reparsed_rhythm
{
$$ = check_scheme_arg (parser, @3,
$3, $1, $2);
function_arglist_nonbackup
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_nonbackup DEFAULT
{
- $$ = scm_cons (loc_on_music (@4, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @4, $1), $3);
}
;
function_arglist_nonbackup
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_nonbackup
{
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
}
;
$$ = check_scheme_arg (parser, @3,
$3, $1, $2);
}
- | function_arglist_common_reparse REPARSE duration_length
+ | function_arglist_common_reparse REPARSE multiplied_duration
+ {
+ $$ = check_scheme_arg (parser, @3,
+ $3, $1, $2);
+ }
+ | function_arglist_common_reparse REPARSE reparsed_rhythm
{
$$ = check_scheme_arg (parser, @3,
$3, $1, $2);
{
$$ = $2;
if (scm_is_true (scm_call_1 ($1, $3)))
+ // May be 3 \cm or similar
MYREPARSE (@3, $1, REAL, $3);
else {
SCM d = make_duration ($3);
- if (SCM_UNBNDP (d) || scm_is_false (scm_call_1 ($1, d)))
- MYREPARSE (@3, $1, REAL, $3);
- else
- MYREPARSE (@3, $1, DURATION_IDENTIFIER, d);
+ if (!SCM_UNBNDP (d)) {
+ if (scm_is_true (scm_call_1 ($1, d)))
+ MYREPARSE (@3, $1, DURATION_IDENTIFIER, d);
+ else if (scm_is_true
+ (scm_call_1
+ ($1, make_music_from_simple (parser, @3, d))))
+ MYREPARSE (@3, $1, DURATION_ARG, d);
+ else
+ MYREPARSE (@3, $1, SCM_ARG, $3); // trigger error
+ } else
+ MYREPARSE (@3, $1, SCM_ARG, $3); // trigger error
}
}
| EXPECT_SCM function_arglist_optional DURATION_IDENTIFIER
{
$$ = $2;
- MYREPARSE (@3, $1, DURATION_IDENTIFIER, $3);
+ if (scm_is_true (scm_call_1 ($1, $3)))
+ MYREPARSE (@3, $1, DURATION_IDENTIFIER, $3);
+ else if (scm_is_true
+ (scm_call_1
+ ($1, make_music_from_simple (parser, @3, $3))))
+ MYREPARSE (@3, $1, DURATION_ARG, $3);
+ else
+ MYREPARSE (@3, $1, SCM_ARG, $3); // trigger error
}
| EXPECT_SCM function_arglist_optional '-' UNSIGNED
{
function_arglist_backup
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_backup DEFAULT
{
- $$ = scm_cons (loc_on_music (@4, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @4, $1), $3);
}
| function_arglist_skip_backup BACKUP
;
function_arglist_backup
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_skip_backup
{
- $$ = scm_cons (loc_on_music (@3, $1), $3);
+ $$ = scm_cons (loc_on_music (parser, @3, $1), $3);
}
;
;
string:
- STRING {
- $$ = $1;
- }
+ STRING
| full_markup
;
-simple_string: STRING {
- $$ = $1;
+text:
+ STRING
+ | full_markup
+ | embedded_scm_bare
+ {
+ if (Text_interface::is_markup ($1)) {
+ $$ = $1;
+ } else {
+ parser->parser_error (@1, (_ ("markup expected")));
+ $$ = scm_string (SCM_EOL);
+ }
}
+ ;
+
+simple_string: STRING
| embedded_scm_bare
{
if (scm_is_string ($1)) {
unsmob<Music> (scm_car (s))->set_property ("duration", dur);
es = ly_append2 (es, postevs);
- m-> set_property ("elements", es);
- m->set_spot (@$);
+ m->set_property ("elements", es);
+ m->set_spot (parser->lexer_->override_input (@$));
$$ = m->self_scm ();
} %prec ':'
;
$$ = scm_cons (scm_car (p), $$);
}
} else {
- m->set_spot (@2);
+ m->set_spot (parser->lexer_->override_input (@2));
$$ = scm_cons ($2, $$);
}
}
| '-' { $$ = SCM_UNDEFINED; }
;
-duration_length:
- multiplied_duration {
- $$ = $1;
- }
- ;
-
maybe_notemode_duration:
{
$$ = SCM_UNDEFINED;
}
}
| DURATION_IDENTIFIER dots {
- Duration *d = unsmob<Duration> ($1);
- Duration k (d->duration_log (),
- d->dot_count () + scm_to_int ($2));
- k = k.compressed (d->factor ());
- scm_remember_upto_here_1 ($1);
- $$ = k.smobbed_copy ();
+ $$ = make_duration ($1, scm_to_int ($2));
}
;
multiplied_duration:
- steno_duration {
- $$ = $1;
- }
- | multiplied_duration '*' UNSIGNED {
- $$ = unsmob<Duration> ($$)->compressed (scm_to_int ($3)).smobbed_copy ();
- }
- | multiplied_duration '*' FRACTION {
- Rational m (scm_to_int (scm_car ($3)), scm_to_int (scm_cdr ($3)));
-
- $$ = unsmob<Duration> ($$)->compressed (m).smobbed_copy ();
+ steno_duration multipliers {
+ $$ = make_duration ($1, 0, $2);
}
;
}
;
+multipliers:
+ /* empty */
+ {
+ $$ = SCM_UNDEFINED;
+ }
+ | multipliers '*' UNSIGNED
+ {
+ if (!SCM_UNBNDP ($1))
+ $$ = scm_product ($1, $3);
+ else
+ $$ = $3;
+ }
+ | multipliers '*' FRACTION
+ {
+ if (!SCM_UNBNDP ($1))
+ $$ = scm_product ($1, scm_divide (scm_car ($3),
+ scm_cdr ($3)));
+ else
+ $$ = scm_divide (scm_car ($3), scm_cdr ($3));
+ }
+ ;
+
tremolo_type:
':' {
$$ = scm_from_int (parser->default_tremolo_type_);
;
partial_markup:
- markup_mode markup_head_1_list ETC
+ markup_mode markup_partial_function ETC
{
$$ = MAKE_SYNTAX (partial_markup, @2, $2);
parser->lexer_->pop_state ();
;
markup_scm:
- embedded_scm_bare
+ embedded_scm
{
if (Text_interface::is_markup ($1))
MYBACKUP (MARKUP_IDENTIFIER, $1, @1);
}
;
+markup_partial_function:
+ MARKUP_FUNCTION markup_arglist_partial
+ {
+ $$ = scm_list_1 (scm_cons ($1, scm_reverse_x ($2, SCM_EOL)));
+ }
+ | markup_head_1_list MARKUP_FUNCTION markup_arglist_partial
+ {
+ $$ = scm_cons (scm_cons ($2, scm_reverse_x ($3, SCM_EOL)),
+ $1);
+ }
+ ;
+
+markup_arglist_partial:
+ EXPECT_MARKUP markup_arglist_partial
+ {
+ $$ = $2;
+ }
+ | EXPECT_SCM markup_arglist_partial
+ {
+ $$= $2;
+ }
+ | EXPECT_MARKUP markup_command_list_arguments
+ {
+ $$ = $2;
+ }
+ | EXPECT_SCM markup_command_list_arguments
+ {
+ $$ = $2;
+ }
+ ;
+
markup_head_1_item:
MARKUP_FUNCTION EXPECT_MARKUP markup_command_list_arguments {
$$ = scm_cons ($1, scm_reverse_x ($3, SCM_EOL));
return args;
}
-SCM loc_on_music (Input loc, SCM arg)
+SCM loc_on_music (Lily_parser *parser, Input loc, SCM arg)
{
if (Music *m = unsmob<Music> (arg))
{
m = m->clone ();
- m->set_spot (loc);
+ m->set_spot (parser->lexer_->override_input (loc));
return m->unprotect ();
}
return arg;
n->set_property ("pitch", simple);
return n->unprotect ();
}
+ SCM d = simple;
+ if (scm_is_integer (simple))
+ d = make_duration (simple);
+ if (unsmob<Duration> (d)) {
+ Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
+ n->set_property ("duration", d);
+ return n->unprotect ();
+ }
return simple;
} else if (parser->lexer_->is_lyric_state ()) {
if (Text_interface::is_markup (simple))
}
SCM
-make_duration (SCM d, int dots)
+make_duration (SCM d, int dots, SCM factor)
{
- int t = scm_to_int (d);
- if (t > 0 && (t & (t-1)) == 0)
- return Duration (intlog2 (t), dots).smobbed_copy ();
- else
- return SCM_UNDEFINED;
+ Duration k;
+
+ if (Duration *dur = unsmob<Duration> (d)) {
+ if (!dots && SCM_UNBNDP (factor))
+ return d;
+ k = *dur;
+ if (dots)
+ k = Duration (k.duration_log (), k.dot_count () + dots)
+ .compressed (k.factor ());
+ } else {
+ int t = scm_to_int (d);
+ if (t > 0 && (t & (t-1)) == 0)
+ k = Duration (intlog2 (t), dots);
+ else
+ return SCM_UNDEFINED;
+ }
+
+ if (!SCM_UNBNDP (factor))
+ k = k.compressed (ly_scm2rational (factor));
+
+ return k.smobbed_copy ();
}
SCM