(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))))
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 ();
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);
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}/.* {
}
}
-<*><<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
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)
{
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"
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)
{
/* 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
%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
%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
%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
%%
-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 {
| 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:
{
(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.
,@(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)