#include "book.hh"
+
#include "context-def.hh"
#include "dimensions.hh"
#include "event.hh"
#include "lilypond-input-version.hh"
#include "ly-module.hh"
#include "main.hh"
-#include "midi-def.hh"
#include "misc.hh"
#include "music-list.hh"
#include "music-sequence.hh"
#include "my-lily-lexer.hh"
#include "my-lily-parser.hh"
#include "paper-book.hh"
-#include "paper-def.hh"
+#include "output-def.hh"
#include "scm-hash.hh"
#include "scm-option.hh"
#include "score.hh"
%union {
Book *book;
- Music_output_def *outputdef;
+ Output_def *outputdef;
SCM scm;
String *string;
Music *music;
%pure_parser
%token ACCEPTS
-%token ADDLYRICS
%token ADDQUOTE
%token LYRICSTO
%token ALIAS
%token ALTERNATIVE
-%token APPLY
-%token APPLYCONTEXT
-%token APPLYOUTPUT
-%token AUTOCHANGE
%token BAR
%token BOOK
-%token BREATHE
+%token BOOKPAPER
%token CHANGE
%token CHORDMODIFIERS
%token CHORDS
%token EXTENDER
%token FIGURES FIGURE_OPEN FIGURE_CLOSE
%token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
-%token GRACE
-%token ACCIACCATURA
-%token APPOGGIATURA
%token GROBDESCRIPTIONS
%token HEADER
%token HYPHEN
%token ONCE
%token OVERRIDE SET REVERT
%token PAPER
-%token PARTCOMBINE
%token PARTIAL
%token QUOTE
%token RELATIVE
%token WITH
/* escaped */
+/* FIXME: this sucks. The user will get to see these names:
+ syntax error, unexpected E_CHAR:
+ \
+ %%
+ */
%token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
%token E_LEFTSQUARE E_RIGHTSQUARE E_TILDE
%token E_BACKSLASH
%token <scm> MARKUP_HEAD_SCM0_SCM1_SCM2
%token <scm> MARKUP_HEAD_SCM0_SCM1_MARKUP2
+%token <scm> MUSIC_FUNCTION
+%token <scm> MUSIC_FUNCTION_SCM
+%token <scm> MUSIC_FUNCTION_MUSIC
+%token <scm> MUSIC_FUNCTION_SCM_MUSIC
+%token <scm> MUSIC_FUNCTION_MUSIC_MUSIC
+%token <scm> MUSIC_FUNCTION_SCM_SCM_MUSIC
+%token <scm> MUSIC_FUNCTION_SCM_MUSIC_MUSIC
+
%token <scm> MARKUP_IDENTIFIER MARKUP_HEAD_LIST0
%type <scm> markup markup_line markup_list markup_list_body full_markup
%type <book> book_block book_body
+%type <outputdef> book_paper_head book_paper_block book_paper_body
+
%type <i> exclamations questions dots optional_rest
-%type <i> bass_mod
-%type <scm> grace_head
+%type <i> bass_mod
%type <scm> oct_check
%type <scm> context_mod_list
%type <scm> lyric_element
%type <i> sub_quotes sup_quotes
%type <music> toplevel_music
%type <music> simple_element event_chord command_element
-%type <music> Composite_music Simple_music Prefix_composite_music
+%type <music> Composite_music Simple_music Prefix_composite_music Generic_prefix_music
+%type <scm> Generic_prefix_music_scm
%type <music> Grouped_music_list
%type <music> Repeated_music
%type <scm> Alternative_music
}
| output_def {
SCM id = SCM_EOL;
- if (dynamic_cast<Paper_def*> ($1))
- id = scm_makfrom0str ("$defaultpaper");
- else if (dynamic_cast<Midi_def*> ($1))
- id = scm_makfrom0str ("$defaultmidi");
- THIS->lexer_->set_identifier (id, $1->self_scm ());
+ Output_def * od = $1;
+
+ if ($1->c_variable ("is-paper") == SCM_BOOL_T)
+ id = ly_symbol2scm ("$defaultpaper");
+ else if ($1->c_variable ("is-midi") == SCM_BOOL_T)
+ id = ly_symbol2scm ("$defaultmidi");
+ else if ($1->c_variable ("is-bookpaper") == SCM_BOOL_T)
+ id = ly_symbol2scm ("$defaultbookpaper");
+
+ THIS->lexer_->set_identifier (id, od->self_scm ());
+ scm_gc_unprotect_object (od->self_scm ());
+ }
+ | book_paper_block {
+ THIS->lexer_->set_identifier (ly_symbol2scm ("$defaultbookpaper"), $1->self_scm ());
scm_gc_unprotect_object ($1->self_scm ());
}
;
lilypond_header_body:
{
- $$ = ly_make_anonymous_module ();
+ $$ = ly_make_anonymous_module (safe_global_b);
THIS->lexer_->add_scope ($$);
}
| lilypond_header_body assignment {
}
;
+
+book_paper_block:
+ book_paper_body '}' {
+ $$ = $1;
+ THIS->lexer_->remove_scope ();
+ }
+ ;
+book_paper_head:
+ BOOKPAPER '{' {
+ $$ = get_bookpaper (THIS);
+ $$->input_origin_ = THIS->here_input ();
+ THIS->lexer_->add_scope ($$->scope_);
+ }
+ ;
+
+book_paper_body:
+ book_paper_head
+ | book_paper_body assignment { }
+ ;
+
+
+
book_block:
BOOK {
THIS->push_spot ();
}
;
+/* FIXME:
+ * Use 'handlers' like for toplevel-* stuff?
+ * grok \paper and \midi? */
book_body:
{
$$ = new Book;
$$->set_spot (THIS->here_input ());
+ $$->bookpaper_ = dynamic_cast<Output_def*> (unsmob_output_def (THIS->lexer_->lookup_identifier ("$defaultbookpaper"))->clone ());
+ scm_gc_unprotect_object ($$->bookpaper_->self_scm ());
}
- | book_body score_block {
- $$->scores_.push ($2);
+ | book_body book_paper_block {
+ $$->bookpaper_ = $2;
scm_gc_unprotect_object ($2->self_scm ());
}
+ | book_body score_block {
+ Score *score = $2;
+ $$->scores_.push (score);
+ scm_gc_unprotect_object (score->self_scm ());
+ }
+ | book_body Composite_music {
+ Music *music = $2;
+ Score *score
+ = unsmob_score (ly_music_scorify (music->self_scm ()));
+ $$->scores_.push (score);
+ scm_gc_unprotect_object (music->self_scm ());
+ }
+ | lilypond_header {
+ THIS->header_ = $1;
+ }
| book_body error {
+
}
;
output_def:
music_output_def_body '}' {
$$ = $1;
+ if ($1->parent_)
+ THIS->lexer_->remove_scope ();
+
THIS->lexer_->remove_scope ();
THIS->lexer_->pop_state ();
}
music_output_def_head:
MIDI {
- Music_output_def *id = unsmob_music_output_def (THIS->lexer_->lookup_identifier ("$defaultmidi"));
-
-
- Midi_def *p = 0;
- if (id)
- p = dynamic_cast<Midi_def*> (id->clone ());
- else
- p = new Midi_def;
-
+ Output_def *p = get_midi (THIS);
$$ = p;
THIS->lexer_->add_scope (p->scope_);
}
| PAPER {
- Music_output_def *id = unsmob_music_output_def (THIS->lexer_->lookup_identifier ("$defaultpaper"));
- Paper_def *p = 0;
- if (id)
- p = dynamic_cast<Paper_def*> (id->clone ());
- else
- p = new Paper_def;
+ Output_def* p = get_paper (THIS);
+
+ if (p->parent_)
+ THIS->lexer_->add_scope (p->parent_->scope_);
THIS->lexer_->add_scope (p->scope_);
$$ = p;
music_output_def_body:
music_output_def_head '{' {
$$ = $1;
- $$->input_origin_. set_spot (THIS->here_input ());
+ $$->input_origin_.set_spot (THIS->here_input ());
THIS->lexer_->push_initial_state ();
}
| music_output_def_head '{' MUSIC_OUTPUT_DEF_IDENTIFIER {
scm_gc_unprotect_object ($1->self_scm ());
- Music_output_def *o = unsmob_music_output_def ($3);
+ Output_def *o = unsmob_output_def ($3);
o->input_origin_.set_spot (THIS->here_input ());
$$ = o;
THIS->lexer_->remove_scope ();
}
| music_output_def_body context_def_spec_block {
- $$->assign_context_def ($2);
+ assign_context_def ($$, $2);
}
| music_output_def_body tempo_event {
/*
junk this ? there already is tempo stuff in
music.
*/
- int m = ly_scm2int ( $2->get_property ("metronome-count"));
+ int m = ly_scm2int ($2->get_property ("metronome-count"));
Duration *d = unsmob_duration ($2->get_property ("tempo-unit"));
- Midi_def *md = dynamic_cast<Midi_def*> ($$);
- if (md)
- md->set_tempo (d->get_length (), m);
+ set_tempo ($$, d->get_length (), m);
scm_gc_unprotect_object ($2->self_scm ());
}
| music_output_def_body error {
Simple_music:
event_chord { $$ = $1; }
- | APPLYOUTPUT embedded_scm {
- if (!ly_input_procedure_p ($2))
- THIS->parser_error (_ ("\\applycontext takes function argument"));
- $$ = MY_MAKE_MUSIC ("ApplyOutputEvent");
- $$->set_property ("procedure", $2);
- $$->set_spot (THIS->here_input ());
- }
- | APPLYCONTEXT embedded_scm {
- if (!ly_input_procedure_p ($2))
- THIS->parser_error (_ ("\\applycontext takes function argument"));
- $$ = MY_MAKE_MUSIC ("ApplyContext");
- $$->set_property ("procedure", $2);
- $$->set_spot (THIS->here_input ());
- }
| MUSIC_IDENTIFIER {
$$ = unsmob_music ($1);
}
}
;
-grace_head:
- GRACE { $$ = scm_makfrom0str ("Grace"); }
- | ACCIACCATURA { $$ = scm_makfrom0str ("Acciaccatura"); }
- | APPOGGIATURA { $$ = scm_makfrom0str ("Appoggiatura"); }
- ;
-
context_mod_list:
/* */ { $$ = SCM_EOL; }
| context_mod_list context_mod {
Simultaneous_music { $$ = $1; }
| Sequential_music { $$ = $1; }
;
-
-Prefix_composite_music:
- AUTOCHANGE Music {
- SCM proc = ly_scheme_function ("make-autochange-music");
-
- SCM res = scm_call_1 (proc, $2->self_scm ());
- scm_gc_unprotect_object ($2->self_scm ());
- $$ = unsmob_music (res);
- scm_gc_protect_object (res);
- $$->set_spot (THIS->here_input ());
- }
- | PARTCOMBINE Music Music {
- SCM proc = ly_scheme_function ("make-part-combine-music");
- SCM res = scm_call_1 (proc, scm_listify ($2->self_scm (),
- $3->self_scm (), SCM_UNDEFINED));
+Generic_prefix_music_scm:
+ MUSIC_FUNCTION {
+ $$ = scm_list_2 ($1, make_input (THIS->here_input ()));
+ }
+ | MUSIC_FUNCTION_SCM {
+ THIS->push_spot ();
+ } embedded_scm {
+ $$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3);
+ }
+ | MUSIC_FUNCTION_MUSIC {
+ THIS->push_spot ();
+ } Music {
+ $$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3->self_scm ());
scm_gc_unprotect_object ($3->self_scm ());
- scm_gc_unprotect_object ($2->self_scm ());
- $$ = unsmob_music (res);
- scm_gc_protect_object (res);
- $$->set_spot (THIS->here_input ());
}
- | grace_head Music {
-#if 1
- /*
- The other version is for easier debugging of
- Sequential_music_iterator in combination with grace notes.
- */
-
-/*
-
-TODO: should distinguish between both grace types in the
-basic music objects too, since the meaning is different.
-
-*/
-
- String start_str = "start" + ly_scm2string ($1) + "Music";
- String stop_str = "stop" + ly_scm2string ($1) + "Music";
-
- SCM start = THIS->lexer_->lookup_identifier (start_str);
- SCM stop = THIS->lexer_->lookup_identifier (stop_str);
-
- Music *startm = unsmob_music (start);
- Music *stopm = unsmob_music (stop);
-
- SCM ms = SCM_EOL;
- if (stopm) {
- stopm = stopm->clone ();
- ms = scm_cons (stopm->self_scm (), ms);
- scm_gc_unprotect_object (stopm->self_scm ());
- }
- ms = scm_cons ($2->self_scm (), ms);
- scm_gc_unprotect_object ($2->self_scm ());
- if (startm) {
- startm = startm->clone ();
- ms = scm_cons (startm->self_scm (), ms);
- scm_gc_unprotect_object (startm->self_scm ());
+ | MUSIC_FUNCTION_SCM_MUSIC {
+ THIS->push_spot ();
+ } embedded_scm Music {
+ $$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3, $4->self_scm ());
+ scm_gc_unprotect_object ($4->self_scm ());
+ }
+ | MUSIC_FUNCTION_MUSIC_MUSIC {
+ THIS->push_spot ();
+ } Music Music {
+ $$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3->self_scm (), $4->self_scm ());
+ scm_gc_unprotect_object ($3->self_scm ());
+ scm_gc_unprotect_object ($4->self_scm ());
+ }
+ | MUSIC_FUNCTION_SCM_MUSIC_MUSIC {
+ THIS->push_spot ();
+ } embedded_scm Music Music {
+ $$ = scm_list_5 ($1, make_input (THIS->pop_spot ()),
+ $3, $4->self_scm (), $5->self_scm ());
+ scm_gc_unprotect_object ($5->self_scm ());
+ scm_gc_unprotect_object ($4->self_scm ());
+ }
+ ;
+
+Generic_prefix_music:
+ Generic_prefix_music_scm {
+ SCM func = ly_car ($1);
+ Input *loc = unsmob_input (ly_cadr ($1));
+ SCM args = ly_cddr ($1);
+ SCM sig = scm_object_property (func, ly_symbol2scm ("music-function-signature"));
+ int k = 0;
+ bool ok = true;
+ for (SCM s = sig, t = args;
+ ok && ly_c_pair_p (s) && ly_c_pair_p (t);
+ s = ly_cdr (s), t = ly_cdr (t)) {
+ k++;
+ if (scm_call_1 (ly_car (s), ly_car (t)) != SCM_BOOL_T)
+ {
+ loc->error (_f ("Argument %d failed typecheck", k));
+ THIS->error_level_ = 1;
+ ok = false;
+ }
}
+ SCM m = SCM_EOL;
+ if (ok)
+ m = scm_apply_0 (func, ly_cdr ($1));
+ if (unsmob_music (m))
+ {
+ $$ = unsmob_music (m);
+ scm_gc_protect_object (m);
+ }
+ else
+ {
+ if (ok)
+ loc->error (_ ("Music head function should return Music object."));
+ $$ = MY_MAKE_MUSIC ("Music");
+ }
+ $$->set_spot (*loc);
+ }
+ ;
- Music* seq = MY_MAKE_MUSIC ("SequentialMusic");
- seq->set_property ("elements", ms);
-
- $$ = MY_MAKE_MUSIC ("GraceMusic");
- $$->set_property ("element", seq->self_scm ());
- scm_gc_unprotect_object (seq->self_scm ());
-#else
- $$ = MY_MAKE_MUSIC ("GraceMusic");
- $$->set_property ("element", $2->self_scm ());
- scm_gc_unprotect_object ($2->self_scm ());
-#endif
+Prefix_composite_music:
+ Generic_prefix_music {
+ $$ = $1;
}
| CONTEXT simple_string '=' simple_string optional_context_mod Music {
$$ = context_spec_music ($2, $4, $6, $5);
$$->set_property ("element", p->self_scm ());
scm_gc_unprotect_object (p->self_scm ());
}
- | APPLY embedded_scm Music {
- if (!ly_input_procedure_p ($2))
- {
- THIS->parser_error (_ ("\\apply takes function argument"));
- $$ = $3;
- }
- else
- {
- SCM ret = scm_call_1 ($2, $3->self_scm ());
- Music *m = unsmob_music (ret);
- if (!m) {
- THIS->parser_error ("\\apply must return a Music");
- m = MY_MAKE_MUSIC ("Music");
- }
- $$ = m;
- }
- }
| NOTES
{
SCM nn = THIS->lexer_->lookup_identifier ("pitchnames");
;
re_rhythmed_music:
- ADDLYRICS Music Music {
- Music *m = MY_MAKE_MUSIC ("LyricCombineMusic");
- m->set_property ("elements", scm_listify ($2->self_scm (),
- $3->self_scm (), SCM_UNDEFINED));
- scm_gc_unprotect_object ($3->self_scm ());
- scm_gc_unprotect_object ($2->self_scm ());
- $$ = m;
- }
- | Grouped_music_list new_lyrics {
+ Grouped_music_list new_lyrics {
/* FIXME: should find out uniqueXXX name from music */
SCM name = $1->get_property ("context-id");
;
command_req:
- BREATHE {
- $$ = MY_MAKE_MUSIC ("BreathingSignEvent");
- }
- | E_TILDE {
+ E_TILDE {
$$ = MY_MAKE_MUSIC ("PesOrFlexaEvent");
}
| MARK DEFAULT {
bass_number:
DIGIT {
$$ = scm_number_to_string (scm_int2num ($1), scm_int2num (10));
+ $$ = scm_list_2 (ly_scheme_function ("number-markup"),
+ $$);
}
| UNSIGNED {
$$ = scm_number_to_string (scm_int2num ($1), scm_int2num (10));
+ $$ = scm_list_2 (ly_scheme_function ("number-markup"),
+ $$);
}
| STRING { $$ = $1; }
;
| STRING_IDENTIFIER {
$$ = $1;
}
- | score_block {
- Score *score = $1;
- //Book *book = unsmob_book (ly_score_bookify (score->self_scm ()));
+ | {
+ SCM nn = THIS->lexer_->lookup_identifier ("pitchnames");
+ THIS->lexer_->push_note_state (alist_to_hashq (nn));
+ }
+ /* cont */ score_block {
+ /* WIP this is a bit arbitrary,
+ we should also allow \book or Composite_music.
+ However, you'd typically want to change paper
+ settings, and need a \score block anyway. */
+
+ THIS->lexer_->pop_state ();
+ Score *score = $2;
Book *book = new Book;
book->scores_.push (score);
- extern Music_output_def* get_paper (My_lily_parser *parser);
- Music_output_def *paper = get_paper (THIS);
+
+ Output_def *paper = get_paper (THIS);
+ book->bookpaper_ = get_bookpaper (THIS);
+
SCM s = book->to_stencil (paper, THIS->header_);
-// $$ = s;
- $$ = Text_item::interpret_markup (paper->self_scm (), SCM_EOL, s);
+ scm_gc_unprotect_object (score->self_scm ());
+ scm_gc_unprotect_object (book->self_scm ());
+ $$ = scm_list_2 (ly_scheme_function ("stencil-markup"), s);
}
;
} else if (unsmob_duration (sid)) {
*destination = unsmob_duration (sid)->smobbed_copy ();
return DURATION_IDENTIFIER;
- } else if (unsmob_music_output_def (sid)) {
- Music_output_def *p = unsmob_music_output_def (sid);
+ } else if (unsmob_output_def (sid)) {
+ Output_def *p = unsmob_output_def (sid);
p = p->clone ();
*destination = p->self_scm ();
internal_type_checking_global_b = itc;
}
- if (op == ly_symbol2scm ("poppush"))
+ if (tag == ly_symbol2scm ("poppush"))
m->set_property ("pop-first", SCM_BOOL_T);