Almost a year ago, Pedro Kroger was working on a bnf description of
lilypond. (see  http://lists.gnu.org/archive/html/lilypond-
devel/2004-10/msg00074.html).  Han-Wen suggested hacking Bison so that
it would produce the BNF directly from the .yy file.

I went a different direction, and produced a python script that ignores
all the C++ stuff in parser.yy, resulting in a BNF description of
lilypond that is generated directly from the parser.

I've attached the script (yy2bnf.py), along with the result of running
the script on the current CVS version of parser.yy (lilypond.bnf).

I'd like to suggest that lilypond.bnf be added to the documentation, to
be automatically generated as part of the make process, using yy2bnf.py.

Thanks,

Carl Sorensen
-- 
Carl Sorensen <[EMAIL PROTECTED]>

Attachment: yy2bnf.py
Description: application/python


lilypond:       /* empty */
        | lilypond toplevel_expression 
        | lilypond assignment 
        | lilypond error 
        | lilypond INVALID      
        ;


object_id_setting:
        OBJECTID STRING  
        ;

toplevel_expression:
        lilypond_header 
        | add_quote 
        | book_block 
        | score_block 
        | toplevel_music 
        | full_markup 
        | output_def 
        ;

toplevel_music:
        Composite_music 
        ;

embedded_scm:
        SCM_T
        | SCM_IDENTIFIER
        ;


lilypond_header_body:
        
        | lilypond_header_body assignment  
        ;

lilypond_header:
        HEADER '{' lilypond_header_body '}'     
        ;

/*
        DECLARATIONS
*/
assignment_id:
        STRING          
        | LYRICS_STRING 
        ;

assignment:
        assignment_id '=' identifier_init  
        | embedded_scm 
        ;


identifier_init:
        score_block 
        | output_def 
        | context_def_spec_block 
        | Music  
        | post_event 
        | number_expression 
        | string 
        | embedded_scm 
        | full_markup 
        | DIGIT 
        ;

context_def_spec_block:
        CONTEXT '{' context_def_spec_body '}'
                
        ;

context_def_spec_body:
        /**/ 
        | CONTEXT_DEF_IDENTIFIER 
        | context_def_spec_body GROBDESCRIPTIONS embedded_scm 
        | context_def_spec_body context_mod 
        ;



book_block:
        BOOK '{' book_body '}'  
        ;

/* FIXME:
   * Use 'handlers' like for toplevel-* stuff?
   * grok \layout and \midi?  */
book_body:
        
        | book_body paper_block 
        | book_body score_block 
        | book_body full_markup 
        | book_body lilypond_header 
        | book_body error 
        | book_body object_id_setting 
        ;

score_block:
        SCORE '{' score_body '}'        
        ;

score_body:
        Music 
        | SCORE_IDENTIFIER 
        | score_body object_id_setting 
        | score_body lilypond_header    
        | score_body output_def 
        | score_body error 
        ;


/*
        OUTPUT DEF
*/

paper_block:
        output_def 
        ;


output_def:
        output_def_body '}' 
        ;

output_def_head:
        PAPER 
        | MIDI    
        | LAYOUT        
        ;


output_def_body:
        output_def_head '{' 
        | output_def_head '{' OUTPUT_DEF_IDENTIFIER     
        | output_def_body assignment  
        | output_def_body context_def_spec_block        
        | output_def_body tempo_event  
        | output_def_body error 
        ;

tempo_event:
        TEMPO steno_duration '=' bare_unsigned  
        ;

/*
The representation of a  list is the

  (LIST . LAST-CONS)

 to have efficient append.  */

Music_list:
        /* empty */ 
        | Music_list Music 
        | Music_list embedded_scm 
        | Music_list error 
        ;

Music:
        Simple_music
        | Composite_music
        ;

Alternative_music:
        /* empty */ 
        | ALTERNATIVE '{' Music_list '}' 
        ;


Repeated_music:
        REPEAT simple_string bare_unsigned Music Alternative_music
        
        ;

Sequential_music:
        SEQUENTIAL '{' Music_list '}'           
        | '{' Music_list '}'            
        ;

Simultaneous_music:
        SIMULTANEOUS '{' Music_list '}'
        | simul_open Music_list simul_close     
        ;

Simple_music:
        event_chord             
        | MUSIC_IDENTIFIER 
        | music_property_def
        | context_change
        ;


optional_context_mod:
        /**/ 
        | WITH 
        '{' context_mod_list '}'
        
        ;

context_mod_list:
        /* */  
        | context_mod_list context_mod  
        ;


Composite_music:
        Prefix_composite_music 
        | Grouped_music_list 
        ;

Grouped_music_list:
        Simultaneous_music              
        | Sequential_music              
        ;

Generic_prefix_music_scm:
        MUSIC_FUNCTION 
        | MUSIC_FUNCTION_SCM embedded_scm 
        | MUSIC_FUNCTION_MARKUP full_markup 
        | MUSIC_FUNCTION_MUSIC Music 
        | MUSIC_FUNCTION_SCM_MUSIC embedded_scm Music 
        | MUSIC_FUNCTION_SCM_SCM embedded_scm embedded_scm 
        | MUSIC_FUNCTION_SCM_SCM_MUSIC embedded_scm embedded_scm Music 
        | MUSIC_FUNCTION_MARKUP_MUSIC full_markup Music 
        | MUSIC_FUNCTION_MARKUP_MARKUP full_markup full_markup 
        | MUSIC_FUNCTION_MUSIC_MUSIC Music Music 
        | MUSIC_FUNCTION_SCM_MUSIC_MUSIC embedded_scm Music Music 
        | MUSIC_FUNCTION_MARKUP_MUSIC_MUSIC full_markup Music Music 
        ;

Generic_prefix_music:
        Generic_prefix_music_scm 
        ;


Prefix_composite_music:
        Generic_prefix_music 
        | CONTEXT simple_string '=' simple_string optional_context_mod Music 
        | CONTEXT simple_string optional_context_mod Music 
        | NEWCONTEXT simple_string optional_context_mod Music 

        | TIMES fraction Music  

        
        | Repeated_music                
        | TRANSPOSE pitch_also_in_chords pitch_also_in_chords Music 
        | mode_changing_head Grouped_music_list 
        | mode_changing_head_with_context optional_context_mod 
Grouped_music_list 
        | relative_music        
        | re_rhythmed_music     
        | TAG embedded_scm Music 
        ;

mode_changing_head: 
        NOTEMODE 
        | DRUMMODE 
                
        | FIGUREMODE 
        | CHORDMODE 
        | LYRICMODE
                
        ;

mode_changing_head_with_context: 
        DRUMS 
        | FIGURES 
        | CHORDS 
        | LYRICS
                
        ;


relative_music:
        RELATIVE absolute_pitch Music 
        | RELATIVE Composite_music 
        ;

new_lyrics:
        ADDLYRICS 
        /*cont */
        Grouped_music_list 
        | new_lyrics ADDLYRICS  Grouped_music_list 
        ;

re_rhythmed_music:
        Grouped_music_list new_lyrics 
        | LYRICSTO simple_string  Music 
        ;

context_change:
        CHANGE STRING '=' STRING  
        ;

property_operation:
        STRING '=' scalar 
        | UNSET simple_string 
        | OVERRIDE simple_string embedded_scm '=' embedded_scm 
        | REVERT simple_string embedded_scm 
        ;

context_def_mod:
        CONSISTS 
        | REMOVE 

        | ACCEPTS 
        | DEFAULTCHILD 
        | DENIES 

        | ALIAS 
        | TYPE 
        | DESCRIPTION 
        | NAME 
        ;

context_mod:
        property_operation 
        | context_def_mod STRING 
        ;

context_prop_spec:
        simple_string 
        | simple_string '.' simple_string 
        ;

music_property_def:
        OVERRIDE context_prop_spec embedded_scm '=' scalar 
        | REVERT context_prop_spec embedded_scm 
        | SET context_prop_spec '=' scalar 
        | UNSET context_prop_spec 
        | ONCE music_property_def 
        ;


string:
        STRING 
        | STRING_IDENTIFIER 
        | string '+' string 
        ;

simple_string: STRING 
        | LYRICS_STRING 
        ;

scalar: string 
        | LYRICS_STRING 
        | bare_number 
        | embedded_scm 
        | full_markup 
        | DIGIT 
        ;

/*

pre_events doesn't contain anything. It is a trick:

Adding pre_events to the simple_element
makes the choice between

  string:  STRING

and

  simple_element: STRING

a single shift/reduction conflict.

nevertheless, this is not very clean, and we should find a different
solution.

*/
pre_events: /* empty */
        ;

event_chord:
        pre_events simple_element post_events   
        | command_element
        | note_chord_element
        ;


note_chord_element:
        chord_body optional_notemode_duration post_events
        
        ;

chord_open: '<'
        ;

chord_close: '>'
        ;

simul_open: DOUBLE_ANGLE_OPEN
        ;

simul_close: DOUBLE_ANGLE_CLOSE
        ;

chord_body:
        chord_open chord_body_elements chord_close
        
        ;

chord_body_elements:
        /* empty */             
        | chord_body_elements chord_body_element 
        ;

chord_body_element:
        pitch exclamations questions octave_check post_events
        
        | DRUM_PITCH post_events 
        ;

add_quote:
        ADDQUOTE string Music 
        ;

command_element:
        command_event 
        | SKIP duration_length 
        | OCTAVE pitch 
        | E_BRACKET_OPEN 
        | E_BRACKET_CLOSE 
        | E_BACKSLASH 
        | '|'      
        | TRANSPOSITION pitch 
        | BAR STRING                    
        | PARTIAL duration_length       
        | CLEF STRING  
        | TIME_T fraction  
        | MARK scalar 
        ;

command_event:
        E_TILDE 
        | MARK DEFAULT  
        | tempo_event 
        | KEY DEFAULT 
        | KEY NOTENAME_PITCH SCM_IDENTIFIER     
        ;


post_events:
        /* empty */ 
        | post_events post_event 
        | post_events tagged_post_event 
        ;


tagged_post_event:
        '-' TAG embedded_scm post_event 
        ;


post_event:
        direction_less_event 
        | HYPHEN 
        | EXTENDER 
        | script_dir direction_reqd_event 
        | script_dir direction_less_event 
        | string_number_event
        ;

string_number_event:
        E_UNSIGNED 
        ;

direction_less_char:
        '['  
        | ']'  
        | '~'  
        | '('  
        | ')'  
        | E_EXCLAMATION  
        | E_OPEN  
        | E_CLOSE  
        | E_ANGLE_CLOSE  
        | E_ANGLE_OPEN  
        ;

direction_less_event:
        direction_less_char 
        | EVENT_IDENTIFIER      
        | tremolo_type  
        ;       
        
direction_reqd_event:
        gen_text_def 
        | script_abbreviation 
        ;

octave_check:
        /**/ 
        | '='  
        | '=' sub_quotes 
        | '=' sup_quotes 
        ;

sup_quotes:
        '\'' 
        | sup_quotes '\'' 
        ;

sub_quotes:
        ',' 
        | sub_quotes ',' 
        ;

steno_pitch:
        NOTENAME_PITCH  
        | NOTENAME_PITCH sup_quotes     
        | NOTENAME_PITCH sub_quotes      
        ;

/*
ugh. duplication
*/

steno_tonic_pitch:
        TONICNAME_PITCH 
        | TONICNAME_PITCH sup_quotes    
        | TONICNAME_PITCH sub_quotes     
        ;

pitch:
        steno_pitch 
        ;

pitch_also_in_chords:
        pitch
        | steno_tonic_pitch
        ;

gen_text_def:
        full_markup 
        | string 
        | DIGIT 
        ;

script_abbreviation:
        '^'             
        | '+'           
        | '-'           
        | '|'           
        | '>'           
        | '.'           
        | '_' 
        ;

script_dir:
        '_'     
        | '^'   
        | '-'   
        ;


absolute_pitch:
        steno_pitch     
        ;

duration_length:
        multiplied_duration 
        ;

optional_notemode_duration:
        
        | multiplied_duration   
        ;

steno_duration:
        bare_unsigned dots              
        | DURATION_IDENTIFIER dots      
        ;

multiplied_duration:
        steno_duration 
        | multiplied_duration '*' bare_unsigned 
        | multiplied_duration '*' FRACTION 
        ;

fraction:
        FRACTION 
        | UNSIGNED '/' UNSIGNED 
        ;

dots:
        /* empty */     
        | dots '.' 
        ;

tremolo_type:
        ':'     
        | ':' bare_unsigned 
        ;

bass_number:
        DIGIT   
        | UNSIGNED 
        | STRING 
        | full_markup 
        ;

bass_mod:
        '-'     
        | '+'   
        | '!'   
        ;

bass_figure:
        FIGURE_SPACE 
        | bass_number  
        | bass_figure bass_mod 
        ;

br_bass_figure:
        '[' bass_figure 
        | bass_figure   
        | br_bass_figure ']' 
        ;

figure_list:
        /**/            
        | figure_list br_bass_figure 
        ;

figure_spec:
        FIGURE_OPEN figure_list FIGURE_CLOSE 
        ;


optional_rest:
        /**/   
        | REST 
        ;

simple_element:
        pitch exclamations questions octave_check optional_notemode_duration 
optional_rest 
        | DRUM_PITCH optional_notemode_duration 
        | figure_spec optional_notemode_duration        
        | RESTNAME optional_notemode_duration           
        | MULTI_MEASURE_REST optional_notemode_duration         
        
        | lyric_element optional_notemode_duration      
        | new_chord 
        ;

lyric_element:
        lyric_markup 
        | LYRICS_STRING 
        ;

new_chord:
        steno_tonic_pitch optional_notemode_duration   
        | steno_tonic_pitch optional_notemode_duration chord_separator 
chord_items 
        ;

chord_items:
        /**/ 
        | chord_items chord_item 
        ;

chord_separator:
        CHORD_COLON 
        | CHORD_CARET 
        | CHORD_SLASH steno_tonic_pitch 
        | CHORD_BASS steno_tonic_pitch 
        ;

chord_item:
        chord_separator 
        | step_numbers 
        | CHORD_MODIFIER  
        ;

step_numbers:
        step_number 
        | step_numbers '.' step_number 
        ;

step_number:
        bare_unsigned 
        | bare_unsigned '+' 
        | bare_unsigned CHORD_MINUS 
        ;       

/*
        UTILITIES

TODO: should deprecate in favor of Scheme?

 */
number_expression:
        number_expression '+' number_term 
        | number_expression '-' number_term 
        | number_term
        ;

number_term:
        number_factor 
        | number_factor '*' number_factor 
        | number_factor '/' number_factor 
        ;

number_factor:
        '-'  number_factor 
        | bare_number
        ;


bare_number:
        UNSIGNED        
        | REAL          
        | NUMBER_IDENTIFIER             
        | REAL NUMBER_IDENTIFIER        
        | UNSIGNED NUMBER_IDENTIFIER    
        ;


bare_unsigned:
        UNSIGNED 
        | DIGIT 
        ;

exclamations:
                
        | exclamations '!'      
        ;

questions:
                
        | questions '?' 
        ;

/*
This should be done more dynamically if possible.
*/

lyric_markup:
        LYRIC_MARKUP_IDENTIFIER 
        | LYRIC_MARKUP
                
        markup_top 
        ;

full_markup:
        MARKUP_IDENTIFIER 
        | MARKUP
                
        markup_top 
        ;

markup_top:
        markup_list 
        | markup_head_1_list simple_markup      
        | simple_markup 
        ;

markup_list:
        markup_composed_list 
        | markup_braced_list 
        ;

markup_composed_list:
        markup_head_1_list markup_braced_list 
        ;

markup_braced_list:
        '{' markup_braced_list_body '}' 
        ;

markup_braced_list_body:
        /* empty */     
        | markup_braced_list_body markup 
        | markup_braced_list_body markup_list 
        ;

markup_head_1_item:
        MARKUP_HEAD_MARKUP0     
        | MARKUP_HEAD_SCM0_MARKUP1 embedded_scm 
        | MARKUP_HEAD_SCM0_SCM1_MARKUP2 embedded_scm embedded_scm       
        ;

markup_head_1_list:
        markup_head_1_item      
        | markup_head_1_list markup_head_1_item 
        ;

simple_markup:
        STRING 
        | MARKUP_IDENTIFIER 
        | LYRIC_MARKUP_IDENTIFIER 
        | STRING_IDENTIFIER 
        | SCORE  '{' score_body '}' 
        | MARKUP_HEAD_SCM0 embedded_scm 
        | MARKUP_HEAD_SCM0_SCM1_SCM2 embedded_scm embedded_scm embedded_scm 
        | MARKUP_HEAD_SCM0_SCM1 embedded_scm embedded_scm 
        | MARKUP_HEAD_EMPTY 
        | MARKUP_HEAD_LIST0 markup_list 
        | MARKUP_HEAD_MARKUP0_MARKUP1 markup markup 
        ;
        
markup:
        markup_head_1_list simple_markup        
        | simple_markup 
        ;

%%
_______________________________________________
lilypond-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to