]> git.donarmstrong.com Git - lilypond.git/commitdiff
Make #{ #} accept everything an assignment accepts.
authorDavid Kastrup <dak@gnu.org>
Sat, 27 Aug 2011 20:23:44 +0000 (22:23 +0200)
committerDavid Kastrup <dak@gnu.org>
Sun, 28 Aug 2011 19:42:10 +0000 (21:42 +0200)
This also makes #{ #} return a void music event, and does not create
sequential music if not necessary.

input/regression/display-lily-tests.ly
lily/include/lily-lexer.hh
lily/include/lily-parser.hh
lily/lexer.ll
lily/lily-parser-scheme.cc
lily/lily-parser.cc
lily/parser.yy
scm/parser-ly-from-scheme.scm

index a62cc103d31b6732c6d17d58e0a731f2e5e05e6d..848ff190d86b147cdbbc12fc207d40e6522dc59d 100644 (file)
@@ -17,9 +17,7 @@
                           (display c out))))))
     `(let* ((parser-clone (ly:parser-clone parser))
             (input-str (string-trim-both ,lily-string))
-            (music (car (ly:music-property (parse-string-result input-str
-                                                                parser-clone)
-                                           'elements)))
+            (music (ly:parse-string-expression parser-clone input-str))
             (result-str (string-trim-both (music->lily-string music parser-clone))))
        (cons input-str result-str))))
 
index 72391a087748cdd676739a8ed2b3646547f077c7..b87188b4017630239fb923ee9a4e59e5de63d8da 100644 (file)
@@ -102,6 +102,7 @@ public:
   SCM lookup_identifier (string s);
   SCM lookup_identifier_symbol (SCM s);
   void push_extra_token (int token_type);
+  void push_embedded_token ();
   void push_chord_state (SCM tab);
   void push_figuredbass_state ();
   void push_lyric_state ();
index 0387e2efd71cfdec019c5c844072e7c0d2ba1ecd..9839d38f4d04e4e2d859172ba44f999a178bba87 100644 (file)
@@ -66,6 +66,7 @@ public:
   void include_string (string ly_code);
   void parse_file (string init, string name, string out_name);
   void parse_string (string ly_code);
+  SCM parse_string_expression (string ly_code);
   void parser_error (string);
   void parser_error (Input const &, string);
   void set_yydebug (bool);
index 5743f44964d9e7ba99a393903d53dcd5a0faaeeb..a9b1d3980ebb4866967996a8c7ec108614aa45b7 100644 (file)
@@ -182,6 +182,18 @@ BOM_UTF8   \357\273\277
   return type;
 }
 
+<extratoken><<EOF>>    {
+  /* Generate a token without swallowing anything */
+
+  /* produce requested token */
+  int type = extra_token_types_.back ();
+  extra_token_types_.pop_back ();
+  if (extra_token_types_.empty ())
+    yy_pop_state ();
+
+  return type;
+}
+
    /* Use the trailing context feature. Otherwise, the BOM will not be
       found if the file starts with an identifier definition. */
 <INITIAL,chords,lyrics,figures,notes>{BOM_UTF8}/.* {
@@ -610,15 +622,14 @@ BOM_UTF8  \357\273\277
        }
 }
 
-<*><<EOF>> {
-       if (YY_START == longcomment)
-       {
+<longcomment><<EOF>> {
                LexerError (_ ("EOF found inside a comment").c_str ());
                is_main_input_ = false; // should be safe , can't have \include in --safe.
                if (!close_input ())
                  yyterminate (); // can't move this, since it actually rets a YY_NULL
        }
-       else if (is_main_input_)
+
+<<EOF>> { if (is_main_input_)
        {
                /* 2 = init.ly + current file.
                   > because we're before closing, but is_main_input_ should
@@ -730,6 +741,12 @@ Lily_lexer::push_extra_token (int token_type)
        extra_token_types_.push_back (token_type);
 }
 
+void
+Lily_lexer::push_embedded_token ()
+{
+       push_extra_token (EMBEDDED_LILY);
+}
+
 void
 Lily_lexer::push_chord_state (SCM tab)
 {
index 1107af999592991478f479aa8e2db8d3a46441ba..dc6b652b3d285503ff089ea1b587632868f5c80e 100644 (file)
@@ -207,6 +207,25 @@ LY_DEFINE (ly_parser_parse_string, "ly:parser-parse-string",
   return SCM_UNSPECIFIED;
 }
 
+LY_DEFINE (ly_parse_string_expression, "ly:parse-string-expression",
+           2, 0, 0, (SCM parser_smob, SCM ly_code),
+           "Parse the string @var{ly-code} with @var{parser-smob}."
+" Return the contained music expression.")
+{
+  LY_ASSERT_SMOB (Lily_parser, parser_smob, 1);
+  Lily_parser *parser = unsmob_lily_parser (parser_smob);
+  LY_ASSERT_TYPE (scm_is_string, ly_code, 2);
+
+  if (!parser->lexer_->is_clean ())
+    {
+      parser->parser_error (_ ("ly:parse-string-expression is only valid with a new parser."
+                              "  Use ly:parser-include-string instead."));
+      return SCM_UNSPECIFIED;
+    }
+
+  return parser->parse_string_expression (ly_scm2string (ly_code));
+}
+
 LY_DEFINE (ly_parser_include_string, "ly:parser-include-string",
            2, 0, 0, (SCM parser_smob, SCM ly_code),
            "Include the string @var{ly-code} into the input stream"
index ba3bd0f99be8c0f5a503d5dffe50d7cb007f047a..5c1a3d358d61f390212f14915fa60e1d5c3536ce 100644 (file)
@@ -163,6 +163,36 @@ Lily_parser::parse_string (string ly_code)
   error_level_ = error_level_ | lexer_->error_level_;
 }
 
+SCM
+Lily_parser::parse_string_expression (string ly_code)
+{
+  // TODO: use $parser
+  lexer_->set_identifier (ly_symbol2scm ("parser"),
+                          self_scm ());
+
+  lexer_->main_input_name_ = "<string>";
+  lexer_->is_main_input_ = true;
+  lexer_->new_input (lexer_->main_input_name_, ly_code, sources_);
+
+  SCM mod = lexer_->set_current_scope ();
+  lexer_->push_embedded_token ();
+  do_yyparse ();
+  SCM result = lexer_->lookup_identifier_symbol (ly_symbol2scm ("$parseStringResult"));
+  // $parseStringResult is set in the grammar rule for embedded_lilypond
+  
+  scm_set_current_module (mod);
+
+  if (!define_spots_.empty ())
+    {
+      if (define_spots_.empty ()
+          && !error_level_)
+        programming_error ("define_spots_ don't match, but error_level_ not set.");
+    }
+
+  error_level_ = error_level_ | lexer_->error_level_;
+  return result;
+}
+
 void
 Lily_parser::include_string (string ly_code)
 {
index c54adb757594031ee13e6c434442da780775243b..a744ed71926b6bd43175d55457c0f6ad336a7ba2 100644 (file)
@@ -277,6 +277,9 @@ If we give names, Bison complains.
 /* After the last argument. */
 %token <i> EXPECT_NO_MORE_ARGS;
 
+/* An artificial token for parsing embedded Lilypond */
+%token <i> EMBEDDED_LILY "#{"
+
 %token <scm> BOOK_IDENTIFIER
 %token <scm> CHORDMODIFIER_PITCH
 %token <scm> CHORD_MODIFIER
@@ -343,6 +346,7 @@ If we give names, Bison complains.
 %type <scm> context_change
 %type <scm> direction_less_event
 %type <scm> direction_reqd_event
+%type <scm> embedded_lilypond
 %type <scm> event_chord
 %type <scm> gen_text_def
 %type <scm> music_property_def
@@ -352,6 +356,7 @@ If we give names, Bison complains.
 %type <scm> relative_music
 %type <scm> simple_element
 %type <scm> simple_music_property_def
+%type <scm> start_symbol
 %type <scm> string_number_event
 %type <scm> tempo_event
 
@@ -396,6 +401,7 @@ If we give names, Bison complains.
 %type <scm> closed_function_arglist
 %type <scm> open_function_arglist
 %type <scm> identifier_init
+%type <scm> lilypond
 %type <scm> lilypond_header
 %type <scm> lilypond_header_body
 %type <scm> lyric_element
@@ -458,7 +464,18 @@ prec levels in different prods */
 
 %%
 
-lilypond:      /* empty */
+start_symbol:
+       lilypond
+       | EMBEDDED_LILY {
+               SCM nn = PARSER->lexer_->lookup_identifier ("pitchnames");
+               PARSER->lexer_->push_note_state (alist_to_hashq (nn));
+       } embedded_lilypond {
+               PARSER->lexer_->pop_state ();
+               PARSER->lexer_->set_identifier (ly_symbol2scm ("$parseStringResult"), $3);
+       }
+       ;
+
+lilypond:      /* empty */ { }
        | lilypond toplevel_expression {
        }
        | lilypond assignment {
@@ -529,6 +546,21 @@ embedded_scm:
        | SCM_IDENTIFIER
        ;
 
+embedded_lilypond:
+       { $$ = MAKE_SYNTAX ("void-music", @$, SCM_UNDEFINED); }
+       | identifier_init
+       | music music music_list {
+               $$ = MAKE_SYNTAX ("sequential-music", @$,       
+                                 scm_cons2 ($1, $2, scm_reverse_x ($3, SCM_EOL)));
+       }
+       | error {
+               PARSER->error_level_ = 1;
+       }
+       | embedded_lilypond INVALID     {
+               PARSER->error_level_ = 1;
+       }
+       ;
+
 
 lilypond_header_body:
        {
index b86392623fddbf3b27ed5a4550e57b4aef5ad528..a17edb63f9e59ff2445734b5f38aa5b5b26267b2 100644 (file)
                                                                         (char->integer #\0)))))
                                                  (string->list (number->string var-idx)))))))))
 
-(define-public (parse-string-result str parser)
-  "Parse @var{str}, which is supposed to contain a music expression."
-
-  (ly:parser-parse-string
-   parser
-   (format #f "parseStringResult = \\notemode { ~a }" str))
-  (ly:parser-lookup parser 'parseStringResult))
-
 (define-public (read-lily-expression chr port)
   "Read a lilypond music expression enclosed within @code{#@}} and @code{#@}}
 from @var{port} and return the corresponding Scheme music expression.
@@ -93,6 +85,6 @@ symbols.  @code{$$} may be used to simply write a @samp{$} character itself."
          ,@(map (lambda (binding)
                   `(ly:parser-define! parser-clone ',(car binding) ,(cdr binding)))
                 (reverse bindings))
-         (parse-string-result ,lily-string parser-clone)))))
+         (ly:parse-string-expression parser-clone ,lily-string)))))
 
 (read-hash-extend #\{ read-lily-expression)