]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/parser.yy
Merge remote-tracking branch 'origin/master' into translation
[lilypond.git] / lily / parser.yy
index 9d641146f2c85ad912b1d6c5dab132fe521b39bb..0804ce575b59f240ff3b43fcd1487ad7c9511fe0 100644 (file)
@@ -224,14 +224,14 @@ SCM get_next_unique_lyrics_context_id ();
 
 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 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 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);
 bool is_duration (int t);
-bool is_regular_identifier (SCM id);
+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);
 
@@ -379,7 +379,6 @@ If we give names, Bison complains.
 %token SCM_FUNCTION
 %token SCM_IDENTIFIER
 %token SCM_TOKEN
-%token SCORE_IDENTIFIER
 %token STRING
 %token SYMBOL_LIST
 %token TONICNAME_PITCH
@@ -830,8 +829,16 @@ score_body:
 
                unsmob_score ($$)->origin ()->set_spot (@$);
        }
-       | SCORE_IDENTIFIER {
+       | embedded_scm_active {
+               Score *score;
+               if (unsmob_score ($1))
+                       score = new Score (*unsmob_score ($1));
+               else {
+                       score = new Score;
+                       parser->parser_error (@1, _("score expected"));
+               }
                unsmob_score ($$)->origin ()->set_spot (@$);
+               $$ = score->unprotect ();
        }
        | score_body
        {
@@ -1229,11 +1236,8 @@ function_arglist_nonbackup_common:
                else {
                        Music *t = MY_MAKE_MUSIC ("FingeringEvent", @5);
                        t->set_property ("digit", $5);
-                       $$ = t->unprotect ();
-                       if (scm_is_true (scm_call_1 ($2, $$)))
-                               $$ = scm_cons ($$, $3);
-                       else
-                               $$ = check_scheme_arg (parser, @4, n, $3, $2);
+                       $$ = check_scheme_arg (parser, @4, t->unprotect (),
+                                              $3, $2, n);
                }
                
        }
@@ -1263,27 +1267,21 @@ function_arglist_closed_nonbackup:
        }
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist SCM_IDENTIFIER
        {
-               SCM res = try_string_variants ($2, $4);
-               if (SCM_UNBNDP (res))
-                       $$ = check_scheme_arg (parser, @4, $4, $3, $2);
-               else
-                       $$ = scm_cons (res, $3);
+               $$ = check_scheme_arg (parser, @4,
+                                      try_string_variants ($2, $4),
+                                      $3, $2, $4);
        }
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist STRING
        {
-               SCM res = try_string_variants ($2, $4);
-               if (SCM_UNBNDP (res))
-                       $$ = check_scheme_arg (parser, @4, $4, $3, $2);
-               else
-                       $$ = scm_cons (res, $3);
+               $$ = check_scheme_arg (parser, @4,
+                                      try_string_variants ($2, $4),
+                                      $3, $2, $4);
        }
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist LYRICS_STRING
        {
-               SCM res = try_string_variants ($2, $4);
-               if (SCM_UNBNDP (res))
-                       $$ = check_scheme_arg (parser, @4, $4, $3, $2);
-               else
-                       $$ = scm_cons (res, $3);
+               $$ = check_scheme_arg (parser, @4,
+                                      try_string_variants ($2, $4),
+                                      $3, $2, $4);
        }
        | EXPECT_OPTIONAL EXPECT_SCM function_arglist lyric_markup
        {
@@ -1313,15 +1311,12 @@ symbol_list_part:
        symbol_list_element
        {
                SCM sym_l_p = ly_lily_module_constant ("symbol-list?");
-               if (scm_is_true (scm_call_1 (sym_l_p, $1)))
-                       $$ = scm_reverse ($1);
-               else {
-                       $$ = try_string_variants (sym_l_p, $1);
-                       if (SCM_UNBNDP ($$)) {
-                               parser->parser_error (@1, _("not a symbol"));
-                               $$ = SCM_EOL;
-                       }
-               }
+               $$ = try_string_variants (sym_l_p, $1);
+               if (SCM_UNBNDP ($$)) {
+                       parser->parser_error (@1, _("not a symbol"));
+                       $$ = SCM_EOL;
+               } else
+                       $$ = scm_reverse ($$);
        }
        ;
 
@@ -2770,7 +2765,7 @@ gen_text_def:
                        make_simple_markup ($1));
                $$ = t->unprotect ();
        }
-       | embedded_scm_bare
+       | embedded_scm_closed
        {
                Music *m = unsmob_music ($1);
                if (m && m->is_mus_type ("post-event"))
@@ -3488,12 +3483,6 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
                 *destination = unsmob_context_mod (sid)->smobbed_copy ();
 
                 return CONTEXT_MOD_IDENTIFIER;
-       } else if (unsmob_score (sid)) {
-               Score *score = new Score (*unsmob_score (sid));
-               *destination = score->self_scm ();
-
-               score->unprotect ();
-               return SCORE_IDENTIFIER;
        } else if (Music *mus = unsmob_music (sid)) {
                mus = mus->clone ();
                *destination = mus->self_scm ();
@@ -3537,14 +3526,34 @@ get_next_unique_lyrics_context_id ()
        return scm_from_locale_string (s);
 }
 
+// check_scheme_arg checks one argument with a given predicate for use
+// in an argument list and throws a syntax error if it is unusable.
+// The argument is prepended to the argument list in any case.  After
+// throwing a syntax error, the argument list is terminated with #f as
+// its last cdr in order to mark it as uncallable while not losing
+// track of its total length.
+//
+// There are a few special considerations: if optional argument disp
+// is given (otherwise it defaults to SCM_UNDEFINED), it will be used
+// instead of arg in a prospective error message.  This is useful if
+// arg is not the actual argument but rather a transformation of it.
+//
+// If arg itself is SCM_UNDEFINED, the predicate is considered false
+// and an error message using disp is produced unconditionally.
+
 SCM check_scheme_arg (Lily_parser *parser, Input loc,
-                     SCM arg, SCM args, SCM pred)
+                     SCM arg, SCM args, SCM pred, SCM disp)
 {
-       args = scm_cons (arg, args);
-       if (scm_is_true (scm_call_1 (pred, arg)))
-               return args;
+       if (SCM_UNBNDP (arg))
+               args = scm_cons (disp, args);
+       else {
+               args = scm_cons (arg, args);
+               if (scm_is_true (scm_call_1 (pred, arg)))
+                       return args;
+       }
        scm_set_cdr_x (scm_last_pair (args), SCM_EOL);
-       MAKE_SYNTAX ("argument-error", loc, scm_length (args), pred, arg);
+       MAKE_SYNTAX ("argument-error", loc, scm_length (args), pred,
+                    SCM_UNBNDP (disp) ? arg : disp);
        scm_set_cdr_x (scm_last_pair (args), SCM_BOOL_F);
        return args;
 }
@@ -3563,27 +3572,47 @@ SCM loc_on_music (Input loc, SCM arg)
 SCM
 try_string_variants (SCM pred, SCM str)
 {
+       // a matching predicate is always ok
        if (scm_is_true (scm_call_1 (pred, str)))
                return str;
-       if (scm_is_string (str))
-       {
-               if (!is_regular_identifier (str))
-                       return SCM_UNDEFINED;
-
-               str = scm_string_to_symbol (str);
+       // a symbol may be interpreted as a list of symbols if it helps
+       if (scm_is_symbol (str)) {
+               str = scm_list_1 (str);
                if (scm_is_true (scm_call_1 (pred, str)))
                        return str;
-       } else if (!scm_is_symbol (str))
                return SCM_UNDEFINED;
+       }
+
+       // If this cannot be a string representation of a symbol list,
+       // we are through.
+
+       if (!is_regular_identifier (str, true))
+               return SCM_UNDEFINED;
+
+       str = scm_string_split (str, SCM_MAKE_CHAR ('.'));
+       for (SCM p = str; scm_is_pair (p); p = scm_cdr (p))
+               scm_set_car_x (p, scm_string_to_symbol (scm_car (p)));
+
+       // Let's attempt the symbol list interpretation first.
 
-       str = scm_list_1 (str);
        if (scm_is_true (scm_call_1 (pred, str)))
                return str;
+
+       // If there is just one symbol in the list, we might interpret
+       // it as a single symbol
+
+       if (scm_is_null (scm_cdr (str)))
+       {
+               str = scm_car (str);
+               if (scm_is_true (scm_call_1 (pred, str)))
+                       return str;
+       }
+
        return SCM_UNDEFINED;
 }
 
 bool
-is_regular_identifier (SCM id)
+is_regular_identifier (SCM id, bool multiple)
 {
   if (!scm_is_string (id))
          return false;
@@ -3599,7 +3628,7 @@ is_regular_identifier (SCM id)
              || (c >= 'A' && c <= 'Z')
              || c > 0x7f)
                  middle = true;
-         else if (middle && (c == '-' || c == '_'))
+         else if (middle && (c == '-' || c == '_' || (multiple && c == '.')))
                  middle = false;
          else
                  return false;
@@ -3613,17 +3642,19 @@ make_music_from_simple (Lily_parser *parser, Input loc, SCM simple)
        if (unsmob_music (simple))
                return simple;
        if (parser->lexer_->is_note_state ()) {
-               Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
-               n->set_property ("duration", parser->default_duration_.smobbed_copy ());
-               if (scm_is_symbol (simple))
+               if (scm_is_symbol (simple)) {
+                       Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
+                       n->set_property ("duration", parser->default_duration_.smobbed_copy ());
                        n->set_property ("drum-type", simple);
-               else if (unsmob_pitch (simple))
+                       return n->unprotect ();
+               }
+               if (unsmob_pitch (simple)) {
+                       Music *n = MY_MAKE_MUSIC ("NoteEvent", loc);
+                       n->set_property ("duration", parser->default_duration_.smobbed_copy ());
                        n->set_property ("pitch", simple);
-               else {
-                       n->unprotect ();
-                       return simple;
+                       return n->unprotect ();
                }
-               return n->unprotect ();
+               return simple;
        } else if (parser->lexer_->is_lyric_state ()) {
                if (Text_interface::is_markup (simple))
                        return MAKE_SYNTAX ("lyric-event", loc, simple,