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 ; %%