From 9ae2f67d4354383977e006968befbbbe8cc56ffd Mon Sep 17 00:00:00 2001 From: hanwen Date: Sun, 1 Aug 2004 14:12:58 +0000 Subject: [PATCH] rename my-lily* files. --- ChangeLog | 2 + lily/lexer.ll | 2 +- lily/lily-lexer.cc | 308 ++++++++++++++++++++++++++ lily/lily-parser.cc | 514 ++++++++++++++++++++++++++++++++++++++++++++ lily/parser.yy | 4 +- 5 files changed, 827 insertions(+), 3 deletions(-) create mode 100644 lily/lily-lexer.cc create mode 100644 lily/lily-parser.cc diff --git a/ChangeLog b/ChangeLog index 7729ba0313..cfe06bec83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2004-08-01 Han-Wen Nienhuys + * lily/lily-parser.cc: rename my-lily* files. + * lily/my-lily-parser.cc (LY_DEFINE): plug memory leak: unprotect parser. diff --git a/lily/lexer.ll b/lily/lexer.ll index b80af4b60a..6ec3cf94b9 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -38,7 +38,7 @@ using namespace std; #include "lily-guile.hh" #include "string.hh" #include "string-convert.hh" -#include "my-lily-lexer.hh" +#include "lily-lexer.hh" #include "interval.hh" #include "lily-guile.hh" #include "parser.hh" diff --git a/lily/lily-lexer.cc b/lily/lily-lexer.cc new file mode 100644 index 0000000000..fa0ae8d544 --- /dev/null +++ b/lily/lily-lexer.cc @@ -0,0 +1,308 @@ +/* + lily-lexer.cc -- implement Lily_lexer + + source file of the GNU LilyPond music typesetter + + (c) 1997--2004 Han-Wen Nienhuys +*/ + +#include +#include + +#include "lily-proto.hh" +#include "scm-hash.hh" +#include "interval.hh" +#include "lily-guile.hh" +#include "parser.hh" +#include "keyword.hh" +#include "lily-lexer.hh" +#include "warn.hh" +#include "source-file.hh" +#include "main.hh" +#include "input.hh" +#include "moment.hh" +#include "ly-module.hh" + + +static Keyword_ent the_key_tab[] = { + {"accepts", ACCEPTS}, + {"addquote", ADDQUOTE}, + {"alias", ALIAS}, + {"alternative", ALTERNATIVE}, + {"bar", BAR}, + {"book", BOOK}, + {"bookpaper", BOOKPAPER}, + {"change", CHANGE}, + {"chords", CHORDS}, + {"clef", CLEF}, + {"consists", CONSISTS}, + {"context", CONTEXT}, + {"default", DEFAULT}, + {"denies", DENIES}, + {"drums", DRUMS}, + {"description", DESCRIPTION}, + {"figures",FIGURES}, + {"grobdescriptions", GROBDESCRIPTIONS}, + {"header", HEADER}, + {"key", KEY}, + {"lyrics", LYRICS}, + {"lyricsto", LYRICSTO}, + {"mark", MARK}, + {"markup", MARKUP}, + {"midi", MIDI}, + {"name", NAME}, + {"new", NEWCONTEXT}, + {"newlyrics", NEWLYRICS}, + {"notes", NOTES}, + {"octave", OCTAVE}, + {"once", ONCE}, + {"override", OVERRIDE}, + {"paper", PAPER}, + {"partial", PARTIAL}, + {"quote", QUOTE}, + {"relative", RELATIVE}, + {"remove", REMOVE}, + {"repeat", REPEAT}, + {"rest", REST}, + {"revert", REVERT}, + {"score", SCORE}, + {"sequential", SEQUENTIAL}, + {"set", SET}, + {"simultaneous", SIMULTANEOUS}, + {"skip", SKIP}, + {"tag", TAG}, + {"tempo", TEMPO}, + {"time", TIME_T}, + {"times", TIMES}, + {"transpose", TRANSPOSE}, + {"transposition", TRANSPOSITION}, + {"type", TYPE}, + {"unset", UNSET}, + {"with", WITH}, + {0, 0} +}; + + +Lily_lexer::Lily_lexer (Sources *sources) +{ + keytable_ = new Keyword_table (the_key_tab); + encoding_ = SCM_EOL; + chordmodifier_tab_ = SCM_EOL; + pitchname_tab_stack_ = SCM_EOL; + sources_ = sources; + scopes_ = SCM_EOL; + error_level_ = 0; + main_input_b_ = false; + + smobify_self (); + + add_scope (ly_make_anonymous_module (false)); + push_note_state (scm_c_make_hash_table (0)); + chordmodifier_tab_ = scm_make_vector (scm_int2num (1), SCM_EOL); +} + +Lily_lexer::Lily_lexer (Lily_lexer const &src) + : Includable_lexer () +{ + keytable_ = (src.keytable_) ? new Keyword_table (*src.keytable_) : 0; + encoding_ = src.encoding_; + chordmodifier_tab_ = src.chordmodifier_tab_; + pitchname_tab_stack_ = src.pitchname_tab_stack_; + sources_ = src.sources_; + + error_level_ = src.error_level_; + main_input_b_ = src.main_input_b_; + + scopes_ = SCM_EOL; + + smobify_self (); + + SCM scopes = SCM_EOL; + SCM* tail = &scopes; + for (SCM s = src.scopes_; ly_c_pair_p (s); s = ly_cdr (s)) + { + SCM newmod = ly_make_anonymous_module (false); + ly_import_module (newmod, ly_car (s)); + *tail = scm_cons (newmod, SCM_EOL); + tail = SCM_CDRLOC (*tail); + } + + scopes_ = scopes; + push_note_state (scm_c_make_hash_table (0)); +} + +Lily_lexer::~Lily_lexer () +{ + delete keytable_; +} + +SCM +Lily_lexer::encoding () const +{ + return encoding_ ; +} + + +void +Lily_lexer::add_scope (SCM module) +{ + ly_reexport_module (scm_current_module ()); + scm_set_current_module (module); + for (SCM s = scopes_; ly_c_pair_p (s); s = ly_cdr (s)) + { + ly_use_module (module, ly_car (s)); + } + scopes_ = scm_cons (module, scopes_); +} + +SCM +Lily_lexer::remove_scope () +{ + SCM sc = ly_car (scopes_); + scopes_ = ly_cdr (scopes_); + scm_set_current_module (ly_car (scopes_)); + + return sc; +} + + +int +Lily_lexer::lookup_keyword (String s) +{ + return keytable_->lookup (s.to_str0 ()); +} + +SCM +Lily_lexer::lookup_identifier_symbol (SCM sym) +{ + for (SCM s = scopes_; ly_c_pair_p (s); s = ly_cdr (s)) + { + SCM var = ly_module_lookup (ly_car (s), sym); + if (var != SCM_BOOL_F) + return scm_variable_ref (var); + } + + return SCM_UNDEFINED; +} + +SCM +Lily_lexer::lookup_identifier (String name) +{ + return lookup_identifier_symbol (ly_symbol2scm (name.to_str0 ())); +} + +void +Lily_lexer::start_main_input () +{ + // yy_flex_debug = 1; + new_input (main_input_name_, sources_); + + /* Do not allow \include in --safe-mode */ + allow_includes_b_ = allow_includes_b_ && !safe_global_b; + + scm_module_define (ly_car (scopes_), + ly_symbol2scm ("input-file-name"), + scm_makfrom0str (main_input_name_.to_str0 ())); +} + +void +Lily_lexer::set_identifier (SCM name, SCM s) +{ + SCM sym = name; + if (ly_c_string_p (name)) + sym = scm_string_to_symbol (name); + + if (ly_c_symbol_p (sym)) + { + if (lookup_keyword (ly_symbol2string (sym)) >= 0) + { + warning (_f ("Identifier name is a keyword: `%s'", SCM_SYMBOL_CHARS (sym))); + } + + SCM mod = ly_car (scopes_); + + scm_module_define (mod, sym, s); + } + else + { + programming_error ("Identifier is not a symbol."); + } +} + +void +Lily_lexer::LexerError (char const *s) +{ + if (include_stack_.is_empty ()) + progress_indication (_f ("error at EOF: %s", s) + String ("\n")); + else + { + error_level_ |= 1; + Input spot (get_source_file (), here_str0 ()); + spot.error (s); + } +} + +char +Lily_lexer::escaped_char (char c) const +{ + switch (c) + { + case 'n': + return '\n'; + case 't': + return '\t'; + case '\'': + case '\"': + case '\\': + return c; + } + return 0; +} + +Input +Lily_lexer::here_input () const +{ + Source_file * f= get_source_file (); + return Input (f, (char*)here_str0 ()); +} + +void +Lily_lexer::prepare_for_next_token () +{ + last_input_ = here_input (); +} + +void +Lily_lexer::set_encoding (String s) +{ + if (s.length ()) + encoding_ = ly_symbol2scm (s.to_str0 ()); + else + encoding_ = SCM_EOL; +} + + +#include "ly-smobs.icc" + +IMPLEMENT_SMOBS (Lily_lexer); +IMPLEMENT_TYPE_P (Lily_lexer, "ly:lily-lexer?"); +IMPLEMENT_DEFAULT_EQUAL_P (Lily_lexer); + +SCM +Lily_lexer::mark_smob (SCM s) +{ + Lily_lexer *lexer = (Lily_lexer*) ly_cdr (s); + + scm_gc_mark (lexer->chordmodifier_tab_); + scm_gc_mark (lexer->pitchname_tab_stack_); + scm_gc_mark (lexer->scopes_); + return lexer->encoding_; +} + +int +Lily_lexer::print_smob (SCM, SCM port, scm_print_state*) +{ + scm_puts ("#", port); + return 1; +} diff --git a/lily/lily-parser.cc b/lily/lily-parser.cc new file mode 100644 index 0000000000..5827f75a95 --- /dev/null +++ b/lily/lily-parser.cc @@ -0,0 +1,514 @@ +/* + lily-parser.cc -- implement Lily_parser + + source file of the GNU LilyPond music typesetter + + (c) 1997--2004 Han-Wen Nienhuys + Jan Nieuwenhuizen +*/ + +#include "book.hh" +#include "file-name.hh" +#include "file-path.hh" +#include "lily-version.hh" +#include "ly-module.hh" +#include "main.hh" +#include "lily-lexer.hh" +#include "lily-parser.hh" +#include "output-def.hh" +#include "paper-book.hh" +#include "parser.hh" +#include "score.hh" +#include "source.hh" +#include "warn.hh" + + +Lily_parser::Lily_parser (Sources *sources) +{ + book_count_ = 0; + score_count_ = 0; + lexer_ = 0; + sources_ = sources; + default_duration_ = Duration (2,0); + error_level_ = 0; + last_beam_start_ = SCM_EOL; + + smobify_self (); +} + +Lily_parser::Lily_parser (Lily_parser const &src) +{ + book_count_ = src.book_count_; + score_count_ = src.score_count_; + lexer_ = 0; + sources_ = src.sources_; + default_duration_ = src.default_duration_; + error_level_ = src.error_level_; + last_beam_start_ = src.last_beam_start_; + + smobify_self (); + if (src.lexer_) + lexer_ = new Lily_lexer (*src.lexer_); + + scm_gc_unprotect_object (lexer_->self_scm ()); +} + +Lily_parser::~Lily_parser () +{ +} + +#include "ly-smobs.icc" + +IMPLEMENT_SMOBS (Lily_parser); +IMPLEMENT_TYPE_P (Lily_parser, "ly:lily-parser?"); +IMPLEMENT_DEFAULT_EQUAL_P (Lily_parser); + +SCM +Lily_parser::mark_smob (SCM s) +{ + Lily_parser *parser = (Lily_parser*) ly_cdr (s); + return (parser->lexer_) ? parser->lexer_->self_scm () : SCM_EOL; +} + +int +Lily_parser::print_smob (SCM s, SCM port, scm_print_state*) +{ + scm_puts ("#", port); + return 1; +} + + +/* Process one .ly file, or book. */ +void +Lily_parser::parse_file (String init, String name, String out_name) +{ + lexer_ = new Lily_lexer (sources_); + scm_gc_unprotect_object (lexer_->self_scm ()); + // TODO: use $parser + lexer_->set_identifier (ly_symbol2scm ("parser"), + self_scm ()); + output_basename_ = out_name; + + lexer_->main_input_name_ = name; + + progress_indication (_ ("Parsing...")); + progress_indication ("\n"); + + set_yydebug (0); + + lexer_->new_input (init, sources_); + + /* Read .ly IN_FILE, lex, parse, write \score blocks from IN_FILE to + OUT_FILE (unless IN_FILE redefines output file name). */ + do_yyparse (); + + if (!define_spots_.is_empty ()) + { + define_spots_.top ().warning (_ ("Braces don't match")); + error_level_ = 1; + } + + error_level_ = error_level_ | lexer_->error_level_; + lexer_ = 0; +} + +void +Lily_parser::parse_string (String ly_code) +{ + Lily_lexer *parent = lexer_; + lexer_ = (parent == 0 ? new Lily_lexer (sources_) + : new Lily_lexer (*parent)); + scm_gc_unprotect_object (lexer_->self_scm ()); + + + SCM oldmod = scm_current_module (); + scm_set_current_module (ly_car (lexer_->scopes_)); + + // TODO: use $parser + lexer_->set_identifier (ly_symbol2scm ("parser"), + self_scm ()); + + lexer_->main_input_name_ = ""; + lexer_->main_input_b_ = true; + + set_yydebug (0); + lexer_->new_input (lexer_->main_input_name_, ly_code, sources_); + do_yyparse (); + + if (!define_spots_.is_empty ()) + { + define_spots_.top ().warning (_ ("Braces don't match")); + error_level_ = 1; + } + + error_level_ = error_level_ | lexer_->error_level_; + + if (parent != 0) + { + parent->keytable_ = lexer_->keytable_; + parent->encoding_ = lexer_->encoding_; + parent->chordmodifier_tab_ = lexer_->chordmodifier_tab_; + parent->pitchname_tab_stack_ = lexer_->pitchname_tab_stack_; + parent->sources_ = lexer_->sources_; + parent->scopes_ = lexer_->scopes_; + parent->error_level_ = lexer_->error_level_; + parent->main_input_b_ = lexer_->main_input_b_; + } + + scm_set_current_module (oldmod); + lexer_ = 0; +} + +void +Lily_parser::push_spot () +{ + define_spots_.push (here_input ()); +} + +char const * +Lily_parser::here_str0 () const +{ + return lexer_->here_str0 (); +} + +void +Lily_parser::parser_error (String s) +{ + here_input ().error (s); + error_level_ = 1; +} + +Input +Lily_parser::pop_spot () +{ + return define_spots_.pop (); +} + +Input +Lily_parser::here_input () const +{ + /* + Parsing looks ahead , so we really want the previous location of the + lexer, not lexer_->here_input (). + */ + + /* + Actually, that gets very icky when there are white space, because + the line-numbers are all wrong. Let's try the character before + the current token. That gets the right result for note/duration + stuff, but doesn't mess up for errors in the 1st token of the + line. + */ + Input hi (lexer_->here_input ()); + + char const * bla = hi.defined_str0_; + if (hi.line_number () > 1 + || hi.column_number () > 1) + bla --; + + return Input (hi.source_file_, bla); +} + + +/****************************************************************/ + + +/* + junkme? + */ +bool store_locations_global_b; + +/* Do not append `!' suffix, since 1st argument is not modified. */ +LY_DEFINE (ly_set_point_and_click, "ly:set-point-and-click", + 1, 0, 0, (SCM what), + "Set the options for Point-and-click source specials output. The\n" +"argument is a symbol. Possible options are @code{none} (no source specials),\n" +"@code{line} and @code{line-column}") +{ + /* UGH. */ + SCM val = SCM_BOOL_F; + if (ly_symbol2scm ("line-column") == what) + val = ly_scheme_function ("line-column-location"); + else if (what == ly_symbol2scm ("line")) + val = ly_scheme_function ("line-location"); + + scm_module_define (global_lily_module, ly_symbol2scm ("point-and-click"), + val); + store_locations_global_b = ly_c_procedure_p (val); + return SCM_UNSPECIFIED; +} + +LY_DEFINE (ly_parse_file, "ly:parse-file", + 1, 0, 0, (SCM name), + "Parse a single @code{.ly} file. " + "Upon failure, throw @code{ly-file-failed} key.") +{ + SCM_ASSERT_TYPE (ly_c_string_p (name), name, SCM_ARG1, __FUNCTION__, "string"); + char const *file = SCM_STRING_CHARS (name); + char const *extensions[] = {"ly", "", 0}; + + String file_name = global_path.find (file, extensions); + + /* By default, use base name of input file for output file name, + write output to cwd; do not use root and directory parts of input + file name. */ + File_name out_file_name (file_name); + + global_path.append (out_file_name.dir_); + + out_file_name.ext_ = ""; + out_file_name.root_ = ""; + out_file_name.dir_ = ""; + + if (!output_name_global.is_empty ()) + out_file_name = File_name (output_name_global); + + String init; + if (!init_name_global.is_empty ()) + init = init_name_global; + else + init = "init.ly"; + + String out_file = out_file_name.to_string (); + + if (init.length () && global_path.find (init).is_empty ()) + { + warning (_f ("can't find init file: `%s'", init)); + warning (_f ("(search path: `%s')", + global_path.to_string ().to_str0 ())); + exit (2); + } + + if ((file_name != "-") && global_path.find (file_name).is_empty ()) + { + warning (_f ("can't find file: `%s'", file_name)); + scm_throw (ly_symbol2scm ("ly-file-failed"), + scm_list_1 (scm_makfrom0str (file_name.to_str0 ()))); + } + else + { + Sources sources; + sources.set_path (&global_path); + + progress_indication (_f ("Now processing `%s'", file_name.to_str0 ())); + progress_indication ("\n"); + + Lily_parser *parser = new Lily_parser (&sources); + + parser->parse_file (init, file_name, out_file); + + bool error = parser->error_level_; + scm_gc_unprotect_object (parser->self_scm ()); + parser = 0; + if (error) + /* TODO: pass renamed input file too. */ + scm_throw (ly_symbol2scm ("ly-file-failed"), + scm_list_1 (scm_makfrom0str (file_name.to_str0 ()))); + } + return SCM_UNSPECIFIED; +} + +LY_DEFINE (ly_parse_string, "ly:parse-string", + 1, 0, 0, (SCM ly_code), + "Parse the string LY_CODE. " + "Upon failure, throw @code{ly-file-failed} key.") +{ + SCM_ASSERT_TYPE (ly_c_string_p (ly_code), ly_code, SCM_ARG1, __FUNCTION__, "string"); + + Sources sources; + sources.set_path (&global_path); + Lily_parser *parser = new Lily_parser (&sources); + scm_module_define (global_lily_module, ly_symbol2scm ("parser"), + parser->self_scm ()); + parser->parse_string (ly_scm2string (ly_code)); + scm_gc_unprotect_object (parser->self_scm ()); + parser = 0; + + return SCM_UNSPECIFIED; +} + +LY_DEFINE (ly_clone_parser, "ly:clone-parser", + 1, 0, 0, (SCM parser_smob), + "Return a clone of PARSER_SMOB.") +{ + Lily_parser *parser = unsmob_my_lily_parser (parser_smob); + Lily_parser *clone = new Lily_parser (*parser); + + /* FIXME: should copy scopes too. */ + return scm_gc_unprotect_object (clone->self_scm ()); +} + +LY_DEFINE (ly_parser_define, "ly:parser-define", + 3, 0, 0, (SCM parser_smob, SCM symbol, SCM val), + "Bind SYMBOL to VAL in PARSER_SMOB's module.") +{ + Lily_parser *parser = unsmob_my_lily_parser (parser_smob); + SCM_ASSERT_TYPE (ly_c_symbol_p (symbol), symbol, SCM_ARG2, __FUNCTION__, "symbol"); + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG2, __FUNCTION__, "parser"); + + parser->lexer_->set_identifier (scm_symbol_to_string (symbol), val); + return SCM_UNSPECIFIED; +} + +LY_DEFINE (ly_parser_lookup, "ly:parser-lookup", + 2, 0, 0, (SCM parser_smob, SCM symbol), + "Lookup @var{symbol} in @var{parser_smob}'s module. " + "Undefined is '().") +{ + Lily_parser *parser = unsmob_my_lily_parser (parser_smob); + + SCM_ASSERT_TYPE (ly_c_symbol_p (symbol), symbol, SCM_ARG2, __FUNCTION__, "symbol"); + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG2, __FUNCTION__, "parser"); + + SCM val= parser->lexer_->lookup_identifier (ly_scm2string (scm_symbol_to_string (symbol))); + if (val != SCM_UNDEFINED) + return val; + else + return SCM_EOL; +} + +LY_DEFINE (ly_parser_parse_string, "ly:parser-parse-string", + 2, 0, 0, (SCM parser_smob, SCM ly_code), + "Parse the string LY_CODE with PARSER_SMOB." + "Upon failure, throw @code{ly-file-failed} key.") +{ + Lily_parser *parser = unsmob_my_lily_parser (parser_smob); + + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG1, __FUNCTION__, "parser"); + SCM_ASSERT_TYPE (ly_c_string_p (ly_code), ly_code, SCM_ARG2, __FUNCTION__, "string"); + + parser->parse_string (ly_scm2string (ly_code)); + + return SCM_UNSPECIFIED; +} + +Output_def* +get_paper (Lily_parser *parser) +{ + SCM id = parser->lexer_->lookup_identifier ("$defaultpaper"); + Output_def *paper = unsmob_output_def (id); + paper = paper ? paper->clone () : new Output_def; + paper->set_variable (ly_symbol2scm ("is-paper"), SCM_BOOL_T); + + paper->parent_ = unsmob_output_def (parser->lexer_->lookup_identifier ("$defaultbookpaper")); + return paper; +} + + +Output_def* +get_midi (Lily_parser *parser) +{ + SCM id = parser->lexer_->lookup_identifier ("$defaultmidi"); + Output_def *paper = unsmob_output_def (id); + paper = paper ? paper->clone () : new Output_def; + paper->set_variable (ly_symbol2scm ("is-midi"), SCM_BOOL_T); + return paper; +} + + +Output_def* +get_bookpaper (Lily_parser *parser) +{ + SCM id = parser->lexer_->lookup_identifier ("$defaultbookpaper"); + Output_def *paper = unsmob_output_def (id); + + paper = paper ? dynamic_cast (paper->clone ()) : new Output_def; + paper->set_variable (ly_symbol2scm ("is-bookpaper"), SCM_BOOL_T); + return paper; +} + + +/* TODO: move this to Scheme? Why take the parser arg, and all the back + & forth between scm and c++? */ +LY_DEFINE (ly_parser_print_score, "ly:parser-print-score", + 2, 0, 0, + (SCM parser_smob, SCM score_smob), + "Print score, i.e., the classic way.") +{ + Lily_parser *parser = unsmob_my_lily_parser (parser_smob); + Score *score = unsmob_score (score_smob); + + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG1, __FUNCTION__, "parser"); + SCM_ASSERT_TYPE (score, score_smob, SCM_ARG2, __FUNCTION__, "score"); + + SCM header = ly_c_module_p (score->header_) ? score->header_ + : parser->lexer_->lookup_identifier ("$globalheader"); + + File_name outname (parser->output_basename_); + int *c = &parser->book_count_; + if (*c) + outname.base_ += "-" + to_string (*c); + (*c)++; + + SCM os = scm_makfrom0str (outname.to_string ().to_str0 ()); + SCM bookpaper = get_bookpaper (parser)->self_scm (); + for (int i = 0; i < score->defs_.size (); i++) + default_rendering (score->music_, score->defs_[i]->self_scm (), + bookpaper, + header, os); + + if (score->defs_.is_empty ()) + { + Output_def *paper = get_paper (parser); + default_rendering (score->music_, paper->self_scm (), + get_bookpaper (parser)->self_scm (), + header, os); + scm_gc_unprotect_object (paper->self_scm ()); + } + return SCM_UNSPECIFIED; +} + + +LY_DEFINE (ly_parser_set_note_names, "ly:parser-set-note-names", + 2, 0, 0, (SCM parser, SCM names), + "Replace current note names in @var{parser}. " + "@var{names} is an alist of symbols. " + "This only has effect if the current mode is notes.") +{ + Lily_parser *p = unsmob_my_lily_parser (parser); + SCM_ASSERT_TYPE(p, parser, SCM_ARG1, __FUNCTION__, "Lilypond parser"); + + if (p->lexer_->is_note_state ()) + { + p->lexer_->pop_state (); + p->lexer_->push_note_state (alist_to_hashq (names)); + } + + return SCM_UNSPECIFIED; +} + +LY_DEFINE (ly_parser_print_book, "ly:parser-print-book", + 2, 0, 0, (SCM parser_smob, SCM book_smob), + "Print book.") +{ + Lily_parser *parser = unsmob_my_lily_parser (parser_smob); + Book *book = unsmob_book (book_smob); + Output_def *bp = unsmob_output_def (parser->lexer_->lookup_identifier ("$defaultbookpaper")); + + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG1, __FUNCTION__, "Lilypond parser"); + SCM_ASSERT_TYPE (book, book_smob, SCM_ARG2, __FUNCTION__, "Book"); + + /* ugh. changing argument.*/ + book->bookpaper_ = bp; + + File_name outname (parser->output_basename_); + int *c = &parser->book_count_; + if (*c) + outname.base_ += "-" + to_string (*c); + (*c)++; + + Output_def *paper = get_paper (parser); + + Paper_book* pb = book->process (outname.to_string (), paper); + + pb->output (outname.to_string ()); + + scm_gc_unprotect_object (paper->self_scm ()); + scm_gc_unprotect_object (pb->self_scm ()); + + return SCM_UNSPECIFIED; +} + diff --git a/lily/parser.yy b/lily/parser.yy index 2188cd934d..6326421b81 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -40,8 +40,8 @@ TODO: #include "misc.hh" #include "music-list.hh" #include "music-sequence.hh" -#include "my-lily-lexer.hh" -#include "my-lily-parser.hh" +#include "lily-lexer.hh" +#include "lily-parser.hh" #include "paper-book.hh" #include "output-def.hh" #include "scm-hash.hh" -- 2.39.2