[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Cues (CueVoice) and quoted instrument name : InstrumentSwitch
From: |
David Kastrup |
Subject: |
Re: Cues (CueVoice) and quoted instrument name : InstrumentSwitch |
Date: |
Tue, 11 Oct 2011 23:40:13 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux) |
David Kastrup <address@hidden> writes:
> "Keith OHara" <address@hidden> writes:
>
>>>>> so it can take *optional* arguments,
>>>> I have not yet learned to use David's new facility for optional
>>>> arguments...
>>>
>>> Please report the parts of the documentation you find hard to
>>> understand. Optional arguments are quite easy to use: if reading the
>>> documentation gives you a headache, there is something wrong with it.
>>
>> The new docs are clear, mostly it took me some time to re-learn
>> everything in "Extending" up to your addition. (I have done no
>> extending myself beyond adapting other people's Lisp-in-Lilypond.)
>>
>> It would be good to warn people that optional arguments must come
>> immediately before an argument that will be read in LilyPond syntax,
>> so that the parser knows which argument is missing.
>
> That's not exactly true: optional arguments can be _skipped_ only when
> the following actual non-optional argument looks differently to the
> parser.
>
> Scheme arguments currently look all the same to the parser: letting the
> parser _call_ the actual predicate for deciding how to parse on is hard.
> It must not have made any irreversible decisions at that point of time.
> And what Bison's LALR(1) parser algorithm considers irreversible is a
> bit tricky.
>
> I'll take a look whether just implementing this predicate-based
> backtracking for optional-Scheme-before-Scheme is feasible on the
> current code base: in the long run, I'll make this much more reliable.
You could try the following patch. It has to run around Bison's totally
broken YYBACKUP macro. I am also pretty sure that if an optional
argument is given by a Scheme function that has a duration or pitch as
its last argument, you'll get a "cannot backup" error. I am not
actually sure that it's worth reworking the grammar for this, since all
it will buy you is getting a syntax error of at most slightly better
comprehensibility (something like "unexpected "ly:pitch?" or so).
I have to think about whether there is a way to do the same using our
own token pushback mechanism, making dealing with the YYBACKUP bug
unnecessary.
diff --git a/lily/parser.yy b/lily/parser.yy
index b0a584f..74ac5da 100644
--- a/lily/parser.yy
+++ b/lily/parser.yy
@@ -116,6 +116,25 @@ using namespace std;
#include "text-interface.hh"
#include "warn.hh"
+#define MYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ yylen = 0; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
%}
@@ -224,6 +243,7 @@ void set_music_properties (Music *p, SCM a);
%token SEQUENTIAL "\\sequential"
%token SET "\\set"
%token SIMULTANEOUS "\\simultaneous"
+%token <scm> SKIPPED_SCM
%token TEMPO "\\tempo"
%token TIMES "\\times"
%token TYPE "\\type"
@@ -1110,7 +1130,7 @@ composite_music:
| closed_music
;
-/* Music that can't be followed by additional events or durations */
+/* Music that can be parsed without lookahead */
closed_music:
mode_changed_music
| MUSIC_IDENTIFIER
@@ -1137,6 +1157,11 @@ function_arglist:
{
$$ = check_scheme_arg (PARSER, @3, SCM_UNDEFINED, $3, $2, $1);
}
+ | EXPECT_SCM SKIPPED_SCM
+ {
+ $$ = check_scheme_arg (PARSER, @$, SCM_UNDEFINED,
+ scm_car ($2), scm_cdr ($2), $1);
+ }
;
function_arglist_optional:
@@ -1157,10 +1182,6 @@ function_arglist_optional:
{
$$ = scm_cons ($1, $3);
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_optional
- {
- $$ = scm_cons (loc_on_music (@3, $1), $3);
- }
;
function_arglist_keep:
@@ -1176,17 +1197,41 @@ function_arglist_keep:
| EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_keep
duration_length {
$$ = scm_cons ($4, $3);
}
+ | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_keep closed_music
+ {
+ $$ = scm_cons ($4, $3);
+ }
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep simple_string
{
- $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
+ } else {
+ $$ = scm_cons2 ($4, loc_on_music (@3, $1), $3);
+ MYBACKUP (SKIPPED_SCM, yyval);
+ }
}
- | EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_keep closed_music
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm_closed
{
- $$ = scm_cons ($4, $3);
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
+ } else {
+ $$ = scm_cons2 ($4, loc_on_music (@3, $1), $3);
+ MYBACKUP (SKIPPED_SCM, yyval);
+ }
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm
+ | EXPECT_OPTIONAL EXPECT_SCM SKIPPED_SCM
{
- $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
+ if (scm_is_true (scm_call_1 ($2, scm_car ($3))))
+ {
+ $$ = check_scheme_arg (PARSER, @3, $1, scm_car ($3),
+ scm_cdr ($3), $2);
+ } else {
+ $$ = scm_cons2 (scm_car ($3), loc_on_music (@3, $1),
+ scm_cdr ($3));
+ MYBACKUP (SKIPPED_SCM, yyval);
+ }
}
| function_arglist
;
@@ -1202,6 +1247,11 @@ function_arglist_closed:
{
$$ = check_scheme_arg (PARSER, @3, SCM_UNDEFINED, $3, $2, $1);
}
+ | EXPECT_SCM SKIPPED_SCM
+ {
+ $$ = check_scheme_arg (PARSER, @$, SCM_UNDEFINED,
+ scm_car ($2), scm_cdr ($2), $1);
+ }
;
function_arglist_closed_optional:
@@ -1241,17 +1291,41 @@ function_arglist_closed_keep:
| EXPECT_OPTIONAL EXPECT_DURATION function_arglist_closed_keep
duration_length {
$$ = scm_cons ($4, $3);
}
- | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep simple_string
- {
- $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
- }
| EXPECT_OPTIONAL EXPECT_MUSIC function_arglist_keep closed_music
{
$$ = scm_cons ($4, $3);
}
+ | EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep simple_string
+ {
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
+ } else {
+ $$ = scm_cons2 ($4, loc_on_music (@3, $1), $3);
+ MYBACKUP (SKIPPED_SCM, yyval);
+ }
+ }
| EXPECT_OPTIONAL EXPECT_SCM function_arglist_keep embedded_scm_closed
{
- $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
+ if (scm_is_true (scm_call_1 ($2, $4)))
+ {
+ $$ = check_scheme_arg (PARSER, @4, $1, $4, $3, $2);
+ } else {
+ $$ = scm_cons2 ($4, loc_on_music (@3, $1), $3);
+ MYBACKUP (SKIPPED_SCM, yyval);
+ }
+ }
+ | EXPECT_OPTIONAL EXPECT_SCM SKIPPED_SCM
+ {
+ if (scm_is_true (scm_call_1 ($2, scm_car ($3))))
+ {
+ $$ = check_scheme_arg (PARSER, @3, $1, scm_car ($3),
+ scm_cdr ($3), $2);
+ } else {
+ $$ = scm_cons2 (scm_car ($3), loc_on_music (@3, $1),
+ scm_cdr ($3));
+ MYBACKUP (SKIPPED_SCM, yyval);
+ }
}
| function_arglist_closed
;
@@ -1747,6 +1821,11 @@ music_function_chord_body_arglist:
| EXPECT_SCM function_arglist_optional embedded_scm_chord_body {
$$ = check_scheme_arg (PARSER, @3, SCM_UNDEFINED, $3, $2, $1);
}
+ | EXPECT_SCM SKIPPED_SCM
+ {
+ $$ = check_scheme_arg (PARSER, @$, SCM_UNDEFINED,
+ scm_car ($2), scm_cdr ($2), $1);
+ }
;
embedded_scm_chord_body:
@@ -1777,6 +1856,11 @@ music_function_event_arglist:
| EXPECT_SCM function_arglist_optional embedded_scm_event {
$$ = check_scheme_arg (PARSER, @3, SCM_UNDEFINED, $3, $2, $1);
}
+ | EXPECT_SCM SKIPPED_SCM
+ {
+ $$ = check_scheme_arg (PARSER, @$, SCM_UNDEFINED,
+ scm_car ($2), scm_cdr ($2), $1);
+ }
;
embedded_scm_event:
--
David Kastrup