lilypond-devel
[Top][All Lists]
Advanced

[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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]