David Kastrup <d...@gnu.org> writes:

> Jean Abou Samra <j...@abou-samra.fr> writes:
>
>> Le 27/06/2022 à 20:10, Simon Albrecht a écrit :
>>> Hello everyone,
>>>
>>> I’m trying to encode a piece such that I can switch whether or not
>>> durations will be shifted (note values
>>> halved/doubled). Unfortunately \tempo isn’t affected by
>>> \shiftDurations (that would be a sensible feature request, right?),
>>
>> Go open an issue.
>>
>>
>>> so I tried this:
>>> %%%%%%%%%%%%%%%%%%%%%%%%%%%
>>> \version "2.23.9"
>>>
>>> durationShiftOne = #-1
>>> {
>>>   \tempo #(ly:make-duration (+ 3 durationShiftOne)) = 152
>>>   \shiftDurations \durationShiftOne #0 { 8 }
>>> }
>>> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>>>
>>> but unfortunately Lily won’t accept that Scheme expression instead
>>> of the normal duration.
>>>
>>> Can I make that work some other way?
>>>
>>> Should the parser be able to take that Scheme expression there?
>>
>>
>> \version "2.23.9"
>>
>> durationShiftOne = #-1
>> {
>>   \tempo $(ly:make-duration (+ 3 durationShiftOne)) = 152
>>   \shiftDurations \durationShiftOne #0 { 8 }
>> }
>>
>>
>> You just need to use $ instead of #. See these pages about the difference:
>>
>> https://lilypond.org/doc/v2.23/Documentation/extending/lilypond-scheme-syntax.html
>> https://extending-lilypond.readthedocs.io/en/latest/lily-and-scheme.html#hash-vs-dollar
>>
>> The problem is that \tempo has multiple syntaxes (\tempo <markup>,
>> \tempo <duration> = <bpm> and \tempo <markup> <duration> = <bpm>),
>> which makes it impossible to accept # here because early evaluation
>> is needed to disambiguate, I think. I'm no expert of the parser
>> though.
>
> It's sort of like that.  Before looking for a possible following `=`
> LilyPond has to have made a decision what type the token/expression
> coming before that has.  It cannot look at the type of a #... expression
> before deciding to look for `=` but it can (and will) look at the type
> of a $... expression.
>
> Now syntax errors are comparatively unhelpful, so one could try to
> tentatively accept an #... = ... expression anyway and then barf if the
> expression type does not support it.  The result would likely not be
> worse for the user.

To wit:

>From 56869db10837eac331e89d074efa5952116ce3d6 Mon Sep 17 00:00:00 2001
From: David Kastrup <d...@gnu.org>
Date: Tue, 28 Jun 2022 00:06:17 +0200
Subject: [PATCH] Allow \tempo #<Duration> = ... for tempo specifications

What doesn't work is specifying \tempo "text" #<Duration> = ...
because its implementation would lead to parser conflicts.
---
 lily/parser.yy | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/lily/parser.yy b/lily/parser.yy
index 9207e479c8..7fff2fd019 100644
--- a/lily/parser.yy
+++ b/lily/parser.yy
@@ -1403,6 +1403,16 @@ tempo_event:
 	TEMPO steno_duration '=' tempo_range	{
 		$$ = MAKE_SYNTAX (tempo, @$, SCM_EOL, $2, $4);
 	}
+	| TEMPO embedded_scm_bare '=' tempo_range {
+		if (unsmob<Duration> ($2))
+		{
+			$$ = MAKE_SYNTAX (tempo, @$, SCM_EOL, $2, $4);
+		} else {
+			parser->parser_error (@2, _("duration expected"));
+			$$ = MAKE_SYNTAX (tempo, @$,
+					  SCM_EOL, Duration (2, 0).smobbed_copy (), $4);
+		}
+	}
 	| TEMPO text steno_duration '=' tempo_range	{
 		$$ = MAKE_SYNTAX (tempo, @$, $2, $3, $5);
 	}
-- 
2.34.1

It's debatable whether this partial ability to specify the duration as
#... but not in the long form including text is worth the confusion.
Anyone who wants to tackle the resulting parser conflicts is welcome to
try: Bison appears to do a pretty good job these days proposing
productions that may trigger the problem when giving the right options.

-- 
David Kastrup

Reply via email to