]> git.donarmstrong.com Git - lilypond.git/blobdiff - src/parser.y
release: 0.0.25
[lilypond.git] / src / parser.y
index 691d306e7889420a610941a1fdee33ccb05ea437..aa3b4f2f3792cbd560a1ed1d302f779972845955 100644 (file)
@@ -1,13 +1,14 @@
 %{ // -*-Fundamental-*-
 #include <iostream.h>
 
+#include "lookup.hh"
+#include "misc.hh"
 #include "lexer.hh"
 #include "paper.hh"
-#include "staff.hh"
-#include "score.hh"
+#include "inputscore.hh"
 #include "main.hh"
 #include "keyword.hh"
-#include "scommands.hh"
+#include "inputcommand.hh"
 #include "debug.hh"
 #include "parseconstruct.hh"
 #include "dimen.hh"
 #define YYDEBUG 1
 #endif
 
-svec<Request*> pre_reqs, post_reqs;
+Array<Request*> pre_reqs, post_reqs;
+sstack<String> define_spots;
+
+Paperdef*default_paper();
 %}
 
 
-%union {    
+%union {
+    Request * request;
     Real real;
-    Command *command;
+    Input_command *command;
     Identifier *id;    
-    Score_commands *scommands;
     Voice *voice;    
     Voice_element *el; 
-    Staff *staff;    
     String *string;
-    Score *score;
     const char *consstr;
     Paperdef *paper;
-    Request* request;
+    Input_music *music;
+    Music_general_chord *chord;
+    Music_voice *mvoice; 
     int i;
     char c;
+    int ii[10];
+       Moment *moment;
+
+    Array<String> * strvec;
+    Array<Input_command*> *commandvec;
+    Array<int> *intvec;
+
+    Input_staff *staff;    
+    Input_score *score;
+    Symtables * symtables;
+    Symtable * symtable;
+    Symbol * symbol;
+    Lookup*lookup;
+    Interval *interval;
+    Box *box;
+    Notename_tab *notename_tab;
+    Script_def * script;
+    Text_def * textdef;
 }
 
-%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
-%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
-%token MELODICSTAFF GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
+%token VOICE STAFF SCORE TITLE  BAR NOTENAME OUTPUT
+%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS COMMAND
+%token GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
+o%token KEY CLEF MULTI TABLE CHORD VOICES
+%token PARTIAL RHYTHMIC MELODIC MUSIC LYRIC GROUPING CADENZA
+%token END SYMBOLTABLES TEXID TABLE NOTENAMES SCRIPT TEXTSTYLE PLET
+%token MARK GOTO
 
 %token <id>  IDENTIFIER
 %token <string> NEWIDENTIFIER 
-%token <string> PITCH DURATION RESTNAME
+%token <string> PITCHMOD DURATION RESTNAME
+%token <ii> NOTENAME 
 %token <real> REAL
 %token <string> STRING
-%token <i> OPEN_REQUEST_PARENS CLOSE_REQUEST_PARENS
-
 
+%token <i> DOTS INT
 %type <consstr> unit
-
-%type <id> declaration 
+%type <intvec> pitch_list
+%type <c> open_request_parens close_request_parens
+%type <id> declaration
+%type <string> declarable_identifier
 %type <paper> paper_block paper_body
 %type <real> dim
-%type <voice> voice_block voice_body voice_elts voice_elts_dollar
-%type <el> voice_elt
-%type <command> score_command
+%type <ii> duration
+%type <moment> duration_length
+%type <el> voice_elt full_element lyrics_elt
+%type <command> score_command staff_command position_command
 %type <score> score_block score_body
-%type <staff> staff_block  rhythmstaff_block rhythmstaff_body
-%type <staff> melodicstaff_block melodicstaff_body staffdecl
+%type <staff> staff_block staff_init staff_body
 %type <i> int
-%type <scommands> score_commands_block score_commands_body
-%type <request> post_request pre_request
+%type <intvec> int_list
+%type <commandvec> score_commands_block score_commands_body
+%type <commandvec> staff_commands_block staff_commands_body
+%type <request> post_request pre_request 
+%type <string> pitchmod
+%type <music> music 
+%type <chord> music_chord music_chord_body
+
+%type <mvoice>  music_voice_body music_voice 
+
+%type <interval> dinterval
+%type <box> box
+%type <symtable> symtable symtable_body
+%type <lookup> symtables symtables_body
+%type <symbol> symboldef
+%type <notename_tab> notename_tab notename_tab_body
+%type <i> script_dir
+%type <script> script_definition script_body mudela_script
+%type <request> script_req textscript_req
+%type <textdef> mudela_text
 
 
 %%
@@ -72,133 +118,298 @@ mudela:  /* empty */
        | mudela score_block { 
                add_score($2);
        }
-       | mudela add_declaration {      }
+       | mudela add_declaration { }
+       | mudela mudela_command  {}
        ;
 
+mudela_command:
+       notename_tab                    { lexer->set($1); }
+       ;
+
+/*
+       DECLARATIONS
+*/
 add_declaration: declaration   {
-               add_identifier($1);
+               lexer->add_identifier($1);
        }
        ;
 
+declarable_identifier:
+       NEWIDENTIFIER { $$ = $1; }
+       | IDENTIFIER { $$ = new String($1->name); }
+       ;
+
 declaration:
-       NEWIDENTIFIER '=' staff_block  {
+       declarable_identifier '=' staff_block  {
                $$ = new Staff_id(*$1, $3);
                delete $1; // this sux
        }
-       | NEWIDENTIFIER '=' voice_block {
-               $$ = new Voice_id(*$1, $3);
+       | declarable_identifier '=' music_voice {
+               $$ = new M_voice_id(*$1, $3);
+               delete $1;
+       }
+       | declarable_identifier '=' script_definition {
+               $$ = new Script_id(*$1, $3);
+               delete $1;
+       }
+       | declarable_identifier '=' music_chord  {
+               $$ = new M_chord_id(*$1, $3);
+               delete $1;
+       }
+       | declarable_identifier '=' symtables {
+               $$ = new Lookup_id(*$1, $3);
+               delete $1;
+       }
+       | declarable_identifier '=' notename_tab {
+               $$ = new Notetab_id(*$1, $3);
                delete $1;
        }
        ;
 
+notename_tab:
+       NOTENAMES '{' notename_tab_body '}'     { $$ = $3; }
+       ;
+
+notename_tab_body:                             {
+               $$ = new Notename_tab;
+       }
+       | IDENTIFIER                            {
+               $$ = $1->notename_tab(true);
+       }
+       | notename_tab_body STRING int int                      {
+               $$->set($3, $4, *$2);
+               delete $2;
+       }
+       ;
 
-score_block: SCORE '{' score_body '}'  { $$ = $3; }
+/*
+       SCORE
+*/
+score_block: SCORE 
+               { define_spots.push(lexer->spot()); }
+       '{' score_body '}'      {
+               $$ = $4;
+               $$->define_spot_str_ = define_spots.pop();
+               if (!$$->paper_)
+                       $$->paper_ = default_paper();
+       }
        ;
 
-score_body:            { $$ = new Score; } 
+score_body:            { $$ = new Input_score; }
        | score_body staff_block        { $$->add($2); }
-       | score_body score_commands_block       { $$->set($2); }
+       | score_body score_commands_block       {
+               $$->add(*$2);
+               delete $2;
+       }
        | score_body paper_block                { $$->set($2);  }
        ;
+/*
+       COMMANDS
+*/
 score_commands_block:
        COMMANDS '{' score_commands_body '}' { $$ =$3;}
        ;
 
-score_commands_body:                   { $$ = new Score_commands; }
+score_commands_body:                   { $$ = new Array<Input_command*>; }
        | score_commands_body score_command             {
-               $$->parser_add($2);
+               $$->add($2);
+       }
+       | score_commands_body position_command          {
+               $$->add($2);
+       }
+       ;
+
+staff_commands_block: COMMANDS '{' staff_commands_body '}'     {       
+               $$ = $3; }
+       ;
+
+staff_commands_body:
+       /* empty */                     { $$ = new Array<Input_command*>; }
+       | staff_commands_body staff_command     {
+               $$->add($2);
+       }
+       | staff_commands_body position_command  {
+               $$->add($2);
+       }
+       ;
+
+staff_command:
+       KEY pitch_list  {/*UGH*/
+               $$ = get_key_interpret_command(*$2);
+               delete $2;
+       }
+       | CLEF STRING                   {
+               $$ = get_clef_interpret_command(*$2);
+               delete $2;
+       }
+       ;
+
+duration_length:       
+       duration                {
+               $$ = new Moment(wholes($1[0], $1[1]));
+       }
+       |int '*' duration       {
+               $$ = new Moment($1 * wholes($3[0], $3[1]));
+       }
+       ;
+
+position_command:
+       SKIP int ':' duration_length            {
+               $$ = get_skip_command($2, *$4);
+               delete $4;
+       }
+       | GOTO STRING   {
+               $$ = get_goto_command(*$2);
+               delete $2;
+       }
+       ;
+
+score_command:
+       BAR STRING                      {
+               $$ = get_bar_command(*$2);
+               delete $2;
+       }
+       | METER  int '*' int            {
+               $$ = get_meterchange_command($2, $4);
+       }
+       | PARTIAL duration_length               {
+               $$ = get_partial_command(*$2);
+               delete $2;
+       }
+       | GROUPING int_list             {
+               $$ = get_grouping_command(*$2);
+               delete $2;
+       }
+       | CADENZA int   {
+               $$ = get_cadenza_toggle($2);
        }
        ;
 
+
+
+/*
+       PAPER
+*/
 paper_block:
-       PAPER '{' paper_body '}'        { $$ = $3; }
+       PAPER
+
+       '{' paper_body '}'      { $$ = $3; }
        ;
 
 paper_body:
-       /* empty */                     { $$ = new Paperdef; }
+       /* empty */                     {
+               $$ = default_paper();
+       }
        | paper_body WIDTH dim          { $$->linewidth = $3;}
        | paper_body OUTPUT STRING      { $$->outfile = *$3;
                delete $3;
        }
+       | paper_body symtables          { $$->set($2); }
        | paper_body UNITSPACE dim      { $$->whole_width = $3; }
        | paper_body GEOMETRIC REAL     { $$->geometric_ = $3; }
        ;
 
-dim:
-       REAL unit       { $$ = convert_dimen($1,$2); }
-       ;
-
-
-unit:  CM              { $$ = "cm"; }
-       |IN             { $$ = "in"; }
-       |MM             { $$ = "mm"; }
-       |PT             { $$ = "pt"; }
-       ;
-       
 /*
-       staff
+       STAFFs
 */
 staff_block:
-       staffdecl
-       | rhythmstaff_block
-       | melodicstaff_block
-       ;
-
-staffdecl: STAFF '{' IDENTIFIER '}' { $$ = $3->staff()->clone(); }
+       STAFF   { define_spots.push(lexer->spot()); }
+/*cont*/       '{' staff_body '}'      {
+               $$ = $4; 
+               $$->define_spot_str_ = define_spots.pop();
+       }
        ;
 
-rhythmstaff_block:
-       RHYTHMSTAFF '{' rhythmstaff_body '}'    { $$ = $3; }
-       ;
 
-rhythmstaff_body:
-       /* empty */                     { $$ = get_new_rhythmstaff(); }
-       | rhythmstaff_body voice_block  { $$->add_voice($2); }  
-       ;
 
-melodicstaff_block:
-       MELODICSTAFF '{' melodicstaff_body '}'  { $$ = $3; }
+staff_init:
+       IDENTIFIER              { $$ = $1->staff(true); }
+       | RHYTHMIC              {
+               $$ = new Input_staff("rhythmic");
+       }
+       | MELODIC               {
+               $$ = new Input_staff( "melodic");
+       }
+       | LYRIC                 {
+               $$ = new Input_staff( "lyric");
+       }
        ;
 
-melodicstaff_body:
-       /* empty */                     { $$ = get_new_melodicstaff(); }
-       | melodicstaff_body voice_block         { $$->add_voice($2); }  
+staff_body:
+       staff_init
+       | staff_body music      {
+               $$->add($2);
+       }
+       | staff_body staff_commands_block {
+               $$->add(*$2);
+               delete $2;
+       }
        ;
 
 /*
-       voice
+       MUSIC
 */
-voice_block:
-       VOICE '{' voice_body '}'        { $$ = $3; }
+music:
+       music_voice     { $$ = $1; }
+       | music_chord   { $$ = $1; }
        ;
 
+music_voice:  MUSIC '{' music_voice_body '}'   { $$ = $3; }
+       ;
 
-voice_body:
-       IDENTIFIER              { $$ = new Voice(*$1->voice()); }
-       | voice_elts_dollar     { $$ = $1; }
-       | voice_body START_T REAL { $$->start = $3; }
+music_voice_body:                      {
+               $$ = new Music_voice;
+       }
+       | music_voice_body IDENTIFIER {
+               $$->concatenate($2->mvoice());
+       }
+       | music_voice_body full_element {
+               $$->add_elt($2);
+       }
+       | music_voice_body voice_command {
+       }
+       | music_voice_body music        {
+               $$->add($2);
+       }
        ;
 
+music_chord:  '{' music_chord_body '}' { $$ = $2; }
+       ;
 
-       
+music_chord_body:              {
+               $$ = new Music_general_chord;
+       }
+       | music_chord_body IDENTIFIER {
+               $$->concatenate($2->mchord());
+       }
+       | music_chord_body music {
+               $$ -> add($2);
+       }
+       | music_chord_body full_element {
+               $$ ->add_elt($2);
+       }
+       ;
 
-voice_elts_dollar:
-       '$' voice_elts '$'  { $$ = $2; }
-       ;
 
-voice_elts:
-       /* empty */             {
-            $$ = new Voice;
-        }
-        | voice_elts pre_requests voice_elt post_requests {
-               add_requests($3, pre_reqs);
-               add_requests($3, post_reqs);
-               $$->add($3);
-        }
 
-       | voice_elts voice_command { }
+/*
+       VOICE ELEMENTS
+*/
+full_element:  pre_requests voice_elt post_requests {
+               add_requests($2, pre_reqs);
+               add_requests($2, post_reqs);
+               $$ = $2;
+       }
+       | MARK STRING   {
+               $$ = get_mark_element(*$2);
+               delete $2;
+       }
+       | COMMAND '{' staff_command '}' { $$=get_command_element($3); }
+       | COMMAND '{' score_command '}' { $$=get_command_element($3); }
+       | '|'                           { $$ = get_barcheck_element(); }
+       | lyrics_elt
        ;
-
+               
 post_requests:
        {
                assert(post_reqs.empty());
@@ -209,69 +420,234 @@ post_requests:
        ;
 
 post_request:
-       CLOSE_REQUEST_PARENS            { $$ = get_request($1); }
+       close_request_parens            { $$ = get_request($1); }
+       | script_req
+       | textscript_req
+       ;
+close_request_parens:
+       '('     { $$='('; }
+       |']'    { $$ = ']' }
+       ;
+
+open_request_parens:
+       ')'     {$$=')'}
+       |'['    {$$='['}
+       ;
+
+script_definition:
+       SCRIPT '{' script_body '}'      { $$ = $3; }
+       ;
+
+script_body:
+       STRING int int int              {
+               $$ = new Script_def(*$1,$2, $3,$4);
+               delete $1;
+       }       
+       ;
+
+textscript_req:
+       script_dir mudela_text          { $$ = get_text_req($1,$2); }
+       ;
+
+mudela_text:
+       STRING                  { $$ = get_text(*$1); delete $1; }
        ;
 
-pre_requests:   
+script_req:
+       script_dir mudela_script        { $$ = get_script_req($1, $2); }
+       ;
+
+mudela_script:
+       IDENTIFIER              { $$ = $1->script(true); }
+       | script_definition             { $$ = $1; }
+       | '^'           { $$ = get_scriptdef('^'); }
+       | '+'           { $$ = get_scriptdef('+'); }
+       | '-'           { $$ = get_scriptdef('-'); }
+       | '|'           { $$ = get_scriptdef('|'); }
+       | 'o'           { $$ = get_scriptdef('o'); }
+       | '>'           { $$ = get_scriptdef('>'); }
+       | '.'           { $$ = get_scriptdef('.'); }
+       | DOTS          {
+               if ($1>1) error("too many staccato reqs");
+               $$ = get_scriptdef('.');
+       }
+       ;
+
+script_dir:
+       '_'     { $$ = -1; }
+       |'^'    { $$ = 1; }
+       |'-'    { $$ = 0; }
+       ;
+
+pre_requests:
        | pre_requests pre_request {
                pre_reqs.add($2);
        }
        ;
 
 pre_request: 
-       OPEN_REQUEST_PARENS             { $$ = get_request($1); }
+       open_request_parens             { $$ = get_request($1); }
        ;
-/*
-*/
+
+
+
 voice_command:
-       DURATIONCOMMAND DURATION        {
-               set_default_duration(*$2);
-               delete $2;
+       PLET    '{' INT '/' INT '}'             {
+               set_plet($3,$5);
+       }
+       | DURATIONCOMMAND '{' duration '}'      {
+               set_default_duration($3);
        }
-       | OCTAVECOMMAND PITCH   {
-               set_default_pitch(*$2);
+       | OCTAVECOMMAND '{' pitchmod '}'        {
+               set_default_octave(*$3);
+               delete $3;
+       }
+       | TEXTSTYLE STRING      {
+               set_text_style(*$2);
                delete $2;
        }
        ;
 
-voice_elt:
-       PITCH  DURATION                         {
-               $$ = get_note_element(*$1, *$2);
-               delete $1;
-               delete $2;
+duration:              {
+               get_default_duration($$);
        }
-       |  RESTNAME DURATION            {
-               $$ = get_rest_element(*$1, *$2);
-               delete $1;
-               delete $2;
+       | int           {
+               get_default_duration($$);
+               $$[0] = $1;
+               $$[1] = 0;
        }
-       | PITCH                         { $$ = get_note_element(*$1, "");
+       | int DOTS      {
+               $$[0] = $1;
+               $$[1] = $2;
+       }
+       | DOTS  {
+                get_default_duration($$);
+                $$[1] = $1;
+       }
+       ;
+
+pitchmod:              { $$ = new String; }
+       |PITCHMOD       
+       ;
+
+voice_elt:
+       pitchmod NOTENAME duration                      {
+               $$ = get_note_element(*$1, $2, $3);
                delete $1;
        }
-       |  RESTNAME             { $$ = get_rest_element(*$1, "");
+       | RESTNAME duration             {
+               $$ = get_rest_element(*$1, $2);
                delete $1;
+
        }
        ;
 
-score_command:
-       SKIP int ':' REAL               {
-               $$ = get_skip_command($2, $4);
+lyrics_elt:
+       mudela_text duration                    {
+               $$ = get_word_element($1, $2);
+       };
+
+/*
+       UTILITIES
+*/
+pitch_list:                    {
+               $$ = new Array<int>;
        }
-       | METER  int int                {
-               $$ = get_meterchange_command($2, $3);
+       | pitch_list NOTENAME   {
+               $$->add($2[0]);
+               $$->add($2[1]);         
        }
-/*     | PARTIALMEASURE REAL           {
-               $$ = get_partial_command($2);
-       }*/
        ;
-       
 
 int:
        REAL                    {
                $$ = int($1);
-               if (ABS($1-Real(int($$))) > 1e-8)
-                       yyerror("expecting integer number");
-               
+               if ( distance($1,Real(int($$)) ) > 1e-8)
+                       error("expecting integer number");
+       }
+       | INT
+       ;
+
+int_list:
+       /* */           {
+               $$ = new Array<int>;
+       }
+       | int_list int          {
+               $$->add($2);
+       }
+       ;
+
+dim:
+       REAL unit       { $$ = convert_dimen($1,$2); }
+       ;
+
+
+unit:  CM              { $$ = "cm"; }
+       |IN             { $$ = "in"; }
+       |MM             { $$ = "mm"; }
+       |PT             { $$ = "pt"; }
+       ;
+       
+/*
+       symbol tables
+*/
+symtables:
+       SYMBOLTABLES '{' symtables_body '}'     { $$ = $3; }
+       ;
+
+symtables_body:
+                       {
+               $$ = new Lookup;
+       }
+       | IDENTIFIER            {
+               $$ = new Lookup(*$1->lookup(true));
+       }
+       | symtables_body TEXID STRING           {
+               $$->texsetting = *$3;
+               delete $3;
+       }
+       | symtables_body STRING '=' symtable            {
+               $$->add(*$2, $4);
+               delete $2;
+       }
+       ;
+
+symtable:
+       TABLE '{' symtable_body '}' { $$ = $3; }
+       ;
+
+symtable_body:
+                               { $$ = new Symtable; }
+       | symtable_body STRING  symboldef {
+               $$->add(*$2, *$3);
+               delete $2;
+               delete $3;
+       }
+       ;
+
+symboldef:
+       STRING  box             {
+               $$ = new Symbol(*$1, *$2);
+               delete $1;
+               delete $2;
+       }
+       | STRING {
+               Box b;
+               $$ = new Symbol(*$1, b);
+               delete $1;
+       }
+       ;
+
+box:
+       dinterval dinterval     {
+               $$ = new Box(*$1, *$2);
+               delete $1;
+               delete $2;
+       }
+       ;
+
+dinterval: dim dim             {
+               $$ = new Interval($1, $2);      
        }
        ;
 
@@ -281,12 +657,30 @@ void
 parse_file(String s)
 {
    *mlog << "Parsing ... ";
+
 #ifdef YYDEBUG
-   yydebug = !monitor.silence("Parser");
+   yydebug = !monitor.silence("InitParser") && check_debug;
 #endif
-   new_input(s);
+
+   set_lexer();
+   lexer->new_input("symbol.ini");
+   yyparse();
+
+#ifdef YYDEBUG
+   yydebug = !monitor.silence("Parser") && check_debug;
+#endif
+
+   lexer->new_input(s);
    yyparse();
-   delete_identifiers();
    kill_lexer();
-   *mlog << "\n";
+   assert(define_spots.empty());
+}
+
+Paperdef*
+default_paper()
+{
+    return new Paperdef(
+       lexer->lookup_identifier("default_table")->lookup(true));
 }
+
+