]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/parser.yy
* lily/translator-group.cc (connect_to_context): non const error message.
[lilypond.git] / lily / parser.yy
index 63f38ae6b173119e5d46ea8380d9e1911734fc99..08c0e1e742083472bb87a62f75a81c37ce59aa74 100644 (file)
@@ -9,7 +9,6 @@
 
 %{
 
-#define YYDEBUG 1
 #define YYERROR_VERBOSE 1
 #define YYPARSE_PARAM my_lily_parser
 #define YYLEX_PARAM my_lily_parser
@@ -75,6 +74,7 @@ using namespace std;
 #include "context-def.hh"
 #include "dimensions.hh"
 #include "file-path.hh"
+#include "input-smob.hh"
 #include "input.hh"
 #include "international.hh"
 #include "lily-guile.hh"
@@ -160,7 +160,7 @@ void set_music_properties (Music *p, SCM a);
 %token ADDQUOTE "\\addquote"
 %token ALIAS "\\alias"
 %token ALTERNATIVE "\\alternative"
-%token BOOK "\\book"
+%token BOOK "\book"
 %token CHANGE "\\change"
 %token CHORDMODE "\\chordmode"
 %token CHORDS "\\chords"
@@ -206,6 +206,7 @@ void set_music_properties (Music *p, SCM a);
 %token TEMPO "\\tempo"
 %token TIMES "\\times"
 %token TRANSPOSE "\\transpose"
+%token TRANSPOSITION "\\transposition"
 %token TYPE "\\type"
 %token UNSET "\\unset"
 %token WITH "\\with"
@@ -222,10 +223,8 @@ void set_music_properties (Music *p, SCM a);
 %token CHORD_COLON ":"
 %token CHORD_MINUS "-"
 %token CHORD_SLASH "/"
-%token ANGLE_OPEN "<"
-%token ANGLE_CLOSE ">"
-%token DOUBLE_ANGLE_OPEN "<<"
 %token DOUBLE_ANGLE_CLOSE ">>"
+%token DOUBLE_ANGLE_OPEN "<<"
 %token E_BACKSLASH "\\"
 %token E_ANGLE_CLOSE "\\>"
 %token E_CHAR "\\C[haracter]"
@@ -250,17 +249,13 @@ If we give names, Bison complains.
 %token CHORDMODIFIERS
 %token LYRIC_MARKUP
 %token MULTI_MEASURE_REST
+%token SCM_T
 
 
 %token <i> DIGIT
 %token <i> E_UNSIGNED
 %token <i> UNSIGNED
 
-/* Artificial tokens, for more generic function syntax */
-%token <i> EXPECT_MARKUP;
-%token <i> EXPECT_MUSIC;
-%token <i> EXPECT_SCM;
-
 %token <scm> BOOK_IDENTIFIER
 %token <scm> CHORDMODIFIER_PITCH
 %token <scm> CHORD_MODIFIER
@@ -282,6 +277,22 @@ If we give names, Bison complains.
 %token <scm> MARKUP_HEAD_SCM0_SCM1_SCM2
 %token <scm> MARKUP_IDENTIFIER
 %token <scm> MUSIC_FUNCTION
+%token <scm> MUSIC_FUNCTION_MARKUP 
+%token <scm> MUSIC_FUNCTION_MARKUP_MARKUP 
+%token <scm> MUSIC_FUNCTION_MARKUP_MARKUP_MUSIC 
+%token <scm> MUSIC_FUNCTION_MARKUP_MUSIC 
+%token <scm> MUSIC_FUNCTION_MARKUP_MUSIC_MUSIC 
+%token <scm> MUSIC_FUNCTION_MUSIC 
+%token <scm> MUSIC_FUNCTION_MUSIC_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM 
+%token <scm> MUSIC_FUNCTION_SCM_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_MUSIC_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_SCM_MUSIC_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_SCM 
+%token <scm> MUSIC_FUNCTION_SCM_SCM_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_SCM_SCM 
+%token <scm> MUSIC_FUNCTION_SCM_SCM_SCM_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_SCM_SCM_SCM_MUSIC 
 %token <scm> MUSIC_IDENTIFIER
 %token <scm> NOTENAME_PITCH
 %token <scm> NUMBER_IDENTIFIER
@@ -289,7 +300,7 @@ If we give names, Bison complains.
 %token <scm> REAL
 %token <scm> RESTNAME
 %token <scm> SCM_IDENTIFIER
-%token <scm> SCM_TOKEN
+%token <scm> SCM_T
 %token <scm> SCORE_IDENTIFIER
 %token <scm> STRING
 %token <scm> STRING_IDENTIFIER
@@ -337,6 +348,7 @@ If we give names, Bison complains.
 %type <scm> simple_music_property_def
 %type <scm> string_number_event
 %type <scm> tempo_event
+%type <scm> toplevel_music
 
 %type <outputdef> output_def_body
 %type <outputdef> output_def_head
@@ -350,6 +362,9 @@ If we give names, Bison complains.
 %type <scm> absolute_pitch
 %type <scm> assignment_id
 %type <scm> bare_number
+%type <scm> music_function_event
+%type <scm> music_function_chord_body
+%type <scm> music_function_musicless_prefix
 %type <scm> bass_figure
 %type <scm> figured_bass_modification
 %type <scm> br_bass_figure
@@ -371,11 +386,6 @@ If we give names, Bison complains.
 %type <scm> figure_spec
 %type <scm> fraction
 %type <scm> full_markup
-%type <scm> function_scm_argument
-%type <scm> function_arglist
-%type <scm> function_arglist_music_last
-%type <scm> function_arglist_nonmusic_last
-%type <scm> function_arglist_nonmusic
 %type <scm> identifier_init
 %type <scm> lilypond_header
 %type <scm> lilypond_header_body
@@ -392,9 +402,6 @@ If we give names, Bison complains.
 %type <scm> mode_changing_head
 %type <scm> mode_changing_head_with_context
 %type <scm> multiplied_duration
-%type <scm> music_function_identifier_musicless_prefix
-%type <scm> music_function_event
-%type <scm> music_function_chord_body
 %type <scm> new_chord
 %type <scm> new_lyrics
 %type <scm> number_expression
@@ -420,6 +427,7 @@ If we give names, Bison complains.
 %type <scm> step_number
 %type <scm> step_numbers 
 %type <scm> string
+%type <scm> function_scm_argument
 
 %type <score> score_block
 %type <score> score_body
@@ -469,7 +477,7 @@ toplevel_expression:
                scm_call_2 (proc, PARSER->self_scm (), score->self_scm ());
                score->unprotect ();
        }
-       | composite_music {
+       | toplevel_music {
                Music *music = unsmob_music ($1);
                SCM proc = PARSER->lexer_->lookup_identifier ("toplevel-music-handler");
                scm_call_2 (proc, PARSER->self_scm (), music->self_scm ());
@@ -494,8 +502,13 @@ toplevel_expression:
        }
        ;
 
+toplevel_music:
+       composite_music {
+       }
+       ;
+
 embedded_scm:
-       SCM_TOKEN
+       SCM_T
        | SCM_IDENTIFIER
        ;
 
@@ -526,6 +539,15 @@ assignment_id:
 
 assignment:
        assignment_id '=' identifier_init  {
+               if (! is_regular_identifier ($1))
+               {
+#if 0
+                       /* no longer valid with dashes in \paper{} block. */ 
+                       @1.warning (_ ("identifier should have alphabetic characters only"));
+#endif
+               }
+
+
                PARSER->lexer_->set_identifier ($1, $3);
 
 /*
@@ -598,11 +620,11 @@ context_def_spec_block:
 context_def_spec_body:
        /**/ {
                $$ = Context_def::make_scm ();
-               unsmob_context_def ($$)->origin ()->set_spot (@$);
+               unsmob_context_def ($$)->set_spot (@$);
        }
        | CONTEXT_DEF_IDENTIFIER {
                $$ = $1;
-               unsmob_context_def ($$)->origin ()->set_spot (@$);
+               unsmob_context_def ($$)->set_spot (@$);
        }
        | context_def_spec_body GROBDESCRIPTIONS embedded_scm {
                Context_def*td = unsmob_context_def ($$);
@@ -634,15 +656,14 @@ book_block:
 book_body:
        {
                $$ = new Book;
-               $$->origin ()->set_spot (@$);
+               $$->set_spot (@$);
                $$->paper_ = dynamic_cast<Output_def*> (unsmob_output_def (PARSER->lexer_->lookup_identifier ("$defaultpaper"))->clone ());
                $$->paper_->unprotect ();
                $$->header_ = PARSER->lexer_->lookup_identifier ("$defaultheader"); 
        }
        | BOOK_IDENTIFIER {
                $$ = unsmob_book ($1);
-               $$->protect ();
-               $$->origin ()->set_spot (@$);
+               $$->set_spot (@$);
        }
        | book_body paper_block {
                $$->paper_ = $2;
@@ -683,12 +704,11 @@ score_body:
                // pass ownernship to C++ again.
                $$ = unsmob_score (score);
                $$->protect ();
-               $$->origin ()->set_spot (@$);
+               $$->set_spot (@$);
        }
        | SCORE_IDENTIFIER {
                $$ = unsmob_score ($1);
-               $$->protect ();
-               $$->origin ()->set_spot (@$);
+               $$->set_spot (@$);
        }
        | score_body object_id_setting {
                $$->user_key_ = ly_scm2string ($2);
@@ -724,7 +744,6 @@ paper_block:
                if ($$->lookup_variable (ly_symbol2scm ("is-paper")) != SCM_BOOL_T)
                {
                        PARSER->parser_error (@1, _ ("need \\paper for paper block"));
-                       $1->unprotect ();
                        $$ = get_paper (PARSER);
                }
        }
@@ -773,11 +792,9 @@ output_def_body:
        }
        | output_def_head_with_mode_switch '{' OUTPUT_DEF_IDENTIFIER    {
                $1->unprotect ();
-
                Output_def *o = unsmob_output_def ($3);
                o->input_origin_.set_spot (@$);
                $$ = o;
-               $$->protect ();
                PARSER->lexer_->remove_scope ();
                PARSER->lexer_->add_scope (o->scope_);
        }
@@ -787,6 +804,15 @@ output_def_body:
        | output_def_body context_def_spec_block        {
                assign_context_def ($$, $2);
        }
+       | output_def_body tempo_event  {
+               /*
+                       junk this ? there already is tempo stuff in
+                       music.
+               */
+               int m = scm_to_int (unsmob_music($2)->get_property ("metronome-count"));
+               Duration *d = unsmob_duration (unsmob_music($2)->get_property ("tempo-unit"));
+               set_tempo ($$, d->get_length (), m);
+       }
        | output_def_body error {
 
        }
@@ -794,8 +820,11 @@ output_def_body:
 
 tempo_event:
        TEMPO steno_duration '=' bare_unsigned  {
-               $$ = MAKE_SYNTAX ("tempo", @$, $2, scm_int2num ($4));
-       }                               
+               Music *m = MY_MAKE_MUSIC ("MetronomeChangeEvent");
+               m->set_property ("tempo-unit", $2);
+               m->set_property ("metronome-count", scm_from_int ( $4));
+               $$ = m->unprotect ();
+       }
        ;
 
 /*
@@ -873,7 +902,7 @@ simultaneous_music:
        SIMULTANEOUS '{' music_list '}'{
                $$ = MAKE_SYNTAX ("simultaneous-music", @$, scm_car ($3));
        }
-       | DOUBLE_ANGLE_OPEN music_list DOUBLE_ANGLE_CLOSE       {
+       | simul_open music_list simul_close     {
                $$ = MAKE_SYNTAX ("simultaneous-music", @$, scm_car ($2));
        }
        ;
@@ -917,50 +946,48 @@ function_scm_argument:
        | simple_string
        ;
 
-/* An argument list. If a function \foo expects scm scm music, then the lexer expands \foo into the token sequence:
- MUSIC_FUNCTION EXPECT_MUSIC EXPECT_SCM EXPECT_SCM
-and this rule returns the reversed list of arguments. */
-
-function_arglist_music_last:
-       EXPECT_MUSIC function_arglist music {
-               $$ = scm_cons ($3, $2);
+/*
+TODO: use code generation for this
+*/
+generic_prefix_music_scm:
+       MUSIC_FUNCTION {
+               $$ = scm_list_2 ($1, make_input (@$));
        }
-       ;
-
-function_arglist_nonmusic_last:
-       EXPECT_MARKUP function_arglist full_markup {
-               $$ = scm_cons ($3, $2);
+       | MUSIC_FUNCTION_SCM function_scm_argument {
+               $$ = scm_list_3 ($1, make_input (@$), $2);
        }
-       | EXPECT_SCM function_arglist function_scm_argument {
-               $$ = scm_cons ($3, $2);
+       | MUSIC_FUNCTION_MARKUP full_markup {
+               $$ = scm_list_3 ($1, make_input (@$), $2);
        }
-       ;
-
-function_arglist_nonmusic: /*empty*/ {
-               $$ = SCM_EOL;
+       | music_function_musicless_prefix music {
+               $$ = ly_append2 ($1, scm_list_1 ($2));
        }
-       | EXPECT_MARKUP function_arglist_nonmusic full_markup {
-               $$ = scm_cons ($3, $2);
+       | MUSIC_FUNCTION_SCM_SCM function_scm_argument function_scm_argument {
+               $$ = scm_list_4 ($1, make_input (@$), $2, $3);
        }
-       | EXPECT_SCM function_arglist_nonmusic function_scm_argument {
-               $$ = scm_cons ($3, $2);
+       | MUSIC_FUNCTION_SCM_SCM_SCM function_scm_argument function_scm_argument function_scm_argument {
+               $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4);
        }
-       ;
-
-function_arglist: /*empty*/ {
-               $$ = SCM_EOL;
+       | MUSIC_FUNCTION_MARKUP_MUSIC full_markup music {
+               $$ = scm_list_4 ($1, make_input (@$), $2, $3);
        }
-       | function_arglist_music_last
-       | function_arglist_nonmusic_last
-       ;
-
-generic_prefix_music_scm:
-       MUSIC_FUNCTION function_arglist {
-               $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($2, SCM_EOL));
+       | MUSIC_FUNCTION_MARKUP_MARKUP full_markup full_markup {
+               $$ = scm_list_4 ($1, make_input (@$), $2, $3);
+       }
+       | MUSIC_FUNCTION_MUSIC_MUSIC music music {
+               $$ = scm_list_4 ($1, make_input (@$), $2, $3);
+       }
+       | MUSIC_FUNCTION_SCM_MUSIC_MUSIC function_scm_argument music music {
+               $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4);
+       }
+       | MUSIC_FUNCTION_SCM_SCM_MUSIC_MUSIC function_scm_argument function_scm_argument music music {
+               $$ = scm_list_n ($1, make_input (@$), $2, $3, $4, $5, SCM_UNDEFINED);
+       }
+       | MUSIC_FUNCTION_MARKUP_MUSIC_MUSIC full_markup music music {
+               $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4);
        }
        ;
 
-
 optional_id:
        /**/ { $$ = SCM_EOL; }
        | '=' simple_string {
@@ -1304,8 +1331,20 @@ note_chord_element:
        }
        ;
 
+chord_open: '<'
+       ;
+
+chord_close: '>'
+       ;
+
+simul_open: DOUBLE_ANGLE_OPEN
+       ;
+
+simul_close: DOUBLE_ANGLE_CLOSE
+       ;
+
 chord_body:
-       ANGLE_OPEN chord_body_elements ANGLE_CLOSE
+       chord_open chord_body_elements chord_close
        {
                $$ = MAKE_SYNTAX ("event-chord", @$, scm_reverse_x ($2, SCM_EOL));
        }
@@ -1363,39 +1402,43 @@ chord_body_element:
        }
        ;
 
-music_function_identifier_musicless_prefix: MUSIC_FUNCTION {
-               SCM sig = scm_object_property (yylval.scm, ly_symbol2scm ("music-function-signature"));
-               if (scm_is_pair (sig) && to_boolean (scm_memq (ly_music_p_proc, scm_cdr (scm_reverse (sig)))))
-               {
-                       PARSER->parser_error (@$, "Music function applied to event may not have a Music argument, except as the last argument.");
-               }
-       }
-       ;
-
 music_function_chord_body:
-       /* We could allow chord functions to have multiple music arguments,
-          but it's more consistent with music_function_event if we
-          prohibit it here too */
-       music_function_identifier_musicless_prefix EXPECT_MUSIC function_arglist_nonmusic chord_body_element {
-               $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($3, scm_list_1 ($4)));
+       MUSIC_FUNCTION {
+               $$ = scm_list_2 ($1, make_input (@$));
        }
-       | music_function_identifier_musicless_prefix function_arglist_nonmusic {
-               $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($2, SCM_EOL));
+       | music_function_musicless_prefix chord_body_element {
+               $$ = ly_append2 ($1, scm_list_1 ($2));
        }
        ;
 
 music_function_event:
-       /* Post-events can only have the last argument as music, without this
-          restriction we get a shift/reduce conflict from e.g.
-          c8-\partcombine c8 -. */
-       music_function_identifier_musicless_prefix EXPECT_MUSIC function_arglist_nonmusic post_event {
-               $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($3, scm_list_1 ($4)));
+       music_function_musicless_prefix post_event {
+               $$ = ly_append2 ($1, scm_list_1 ($2));
        }
-       | music_function_identifier_musicless_prefix function_arglist_nonmusic {
-               $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($2, SCM_EOL));
+       ;
+
+/*
+TODO: use code generation for this
+*/
+music_function_musicless_prefix:
+       MUSIC_FUNCTION_MUSIC {
+               $$ = scm_list_2 ($1, make_input (@$));
+       }
+       | MUSIC_FUNCTION_SCM_MUSIC function_scm_argument { 
+               $$ = scm_list_3 ($1, make_input (@$), $2);
+       }
+       | MUSIC_FUNCTION_SCM_SCM_MUSIC function_scm_argument function_scm_argument {
+               $$ = scm_list_4 ($1, make_input (@$), $2, $3);
+       }
+       | MUSIC_FUNCTION_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument {
+               $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4);
+       }
+       | MUSIC_FUNCTION_SCM_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument function_scm_argument {
+               $$ = scm_list_n ($1, make_input (@$), $2, $3, $4, $5, SCM_UNDEFINED);
        }
        ;
 
+
 command_element:
        command_event {
                $$ = $1;
@@ -1432,6 +1475,11 @@ command_element:
                        $$ = MAKE_SYNTAX ("bar-check", @$, SCM_UNDEFINED);
 
        }
+       | TRANSPOSITION pitch {
+               Pitch middle_c;
+               Pitch sounds_as_c = pitch_interval (*unsmob_pitch ($2), middle_c);
+               $$ = MAKE_SYNTAX ("property-operation", @$, SCM_BOOL_F, ly_symbol2scm ("Staff"), ly_symbol2scm ("PropertySet"), ly_symbol2scm ("instrumentTransposition"), sounds_as_c.smobbed_copy ());
+       }
        | PARTIAL duration_length       {
                Moment m = - unsmob_duration ($2)->get_length ();
                $$ = MAKE_SYNTAX ("property-operation", @$, SCM_BOOL_F, ly_symbol2scm ("Timing"), ly_symbol2scm ("PropertySet"), ly_symbol2scm ("measurePosition"), m.smobbed_copy ());
@@ -1698,7 +1746,7 @@ gen_text_def:
                $$ = t->unprotect ();
        }
        | DIGIT {
-               Music *t = MY_MAKE_MUSIC ("FingeringEvent");
+               Music *t = MY_MAKE_MUSIC ("FingerEvent");
                t->set_property ("digit", scm_from_int ($1));
                t->set_spot (@$);
                $$ = t->unprotect ();
@@ -1718,7 +1766,7 @@ script_abbreviation:
        | '|'           {
                $$ = scm_makfrom0str ("Bar");
        }
-       | ANGLE_CLOSE   {
+       | '>'           {
                $$ = scm_makfrom0str ("Larger");
        }
        | '.'           {
@@ -2305,9 +2353,11 @@ markup:
 %%
 
 void
-Lily_parser::set_yydebug (bool x)
+Lily_parser::set_yydebug (bool )
 {
-       yydebug = x;
+#if 0
+       yydebug = 1;
+#endif
 }
 
 void
@@ -2333,26 +2383,17 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
                *destination = sid;
                return STRING_IDENTIFIER;
        } else if (unsmob_book (sid)) {
-               Book *book =  unsmob_book (sid)->clone ();
-               *destination = book->self_scm ();
-               book->unprotect ();
-
+               *destination = unsmob_book (sid)->clone ()->self_scm ();
                return BOOK_IDENTIFIER;
        } else if (scm_is_number (sid)) {
                *destination = sid;
                return NUMBER_IDENTIFIER;
        } else if (unsmob_context_def (sid)) {
-               Context_def *def= unsmob_context_def (sid)->clone ();
-
-               *destination = def->self_scm ();
-               def->unprotect ();
-               
+               *destination = unsmob_context_def (sid)->clone_scm ();
                return CONTEXT_DEF_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 ();
@@ -2363,7 +2404,6 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
                bool is_event = scm_memq (ly_symbol2scm ("event"), mus->get_property ("types"))
                        != SCM_BOOL_F;
 
-               mus->unprotect ();
                return is_event ? EVENT_IDENTIFIER : MUSIC_IDENTIFIER;
        } else if (unsmob_duration (sid)) {
                *destination = unsmob_duration (sid)->smobbed_copy ();
@@ -2371,9 +2411,8 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
        } else if (unsmob_output_def (sid)) {
                Output_def *p = unsmob_output_def (sid);
                p = p->clone ();
-       
+
                *destination = p->self_scm ();
-               p->unprotect ();
                return OUTPUT_DEF_IDENTIFIER;
        } else if (Text_interface::is_markup (sid)) {
                *destination = sid;
@@ -2471,7 +2510,7 @@ void
 set_music_properties (Music *p, SCM a)
 {
   for (SCM k = a; scm_is_pair (k); k = scm_cdr (k))
-       p->set_property (scm_caar (k), scm_cdar (k));
+       p->internal_set_property (scm_caar (k), scm_cdar (k));
 }