[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Denemo-devel] status report
From: |
Richard Shann |
Subject: |
Re: [Denemo-devel] status report |
Date: |
Tue, 22 Jul 2008 20:47:49 +0100 |
Thanks for the files - I would like to check them in, if it is all right
with you.
I have a couple of additions: protection against a crash when the parse
does not work, and parsing LilyPond directives. And, of course,
restoration of the .ly load option.
I think this is plenty for the release, so if I don't hear back, I'll
get this checked in and we can go.
Thanks very much for this great piece of work.
Richard
On Tue, 2008-07-22 at 23:02 +1000, Roy Rankin wrote:
> Richard,
>
> Here are my files and a quick summary of the changes
> exportlilypond.c
> 1> always write /context to help parsing and supply voice name
> 2> voice name - name-movement rather than movement-name to aid parsing
> of name
> 3> midi instruments again output
>
> lyparser.y
> 1> do not generate error for case score_body lilypond_header
> 2> be more specific for some parsing error
> 3> clear some pointers for score - note your suggestions caused troubles
> for me
>
> lyparserfuncs.c
> 1> rewrite break_into_measure to handle recursive identifier
> 2> generate_chords_and_sequentials handles identifiers
> 3> name of first voice is set (old bug)
> 4> added some debugging
>
> This code is working for my simple tests of both old and new versions of
> Denemo. I think this gives about the same level of functionality as the
> lilypond read on the old version, but many valid syntaxes that can be
> handled by Denemo fail.
>
> regards,
> Roy Rankin
>
> Richard Shann wrote:
> > On Tue, 2008-07-22 at 09:01 +1000, Roy Rankin wrote:
> >> I am currently dumping and reading back simple LilyPond files from
> >> Denemo. However, I still have a few issues to cleanup, but if I do not
> >> manage to get this done tonight, my next chunk of free time will be
> >> early next week.
> > I have also been getting a chance to look over this, and I think I
> > understand the code as at present.
> > Could you just email me the lyparser.* lyparserfuncs.* files that you
> > have, so that I can understand where you have got to? (Don't email them
> > to the list, as it blocks (large?) attachemts, send them direct or post
> > them up somewhere).
> > I would like to read over what you have done, to see how it fits in to
> > my understanding of the code. It doesn't need to be compilable or
> > anything, just readable.
> >
> > As the code no longer needs to keep the input LilyPond as strings for
> > output (which was the purpose of the old code) I think it can be
> > simplified and made more able to cope with LilyPond from a variety of
> > sources.
> >
> > In the slightly longer term, I hope be able to select some LilyPond text
> > in a foreign text file (viz. a block of music) and paste it directly
> > into Denemo, using the lyparser (essentially, by surrounding it with
> > \score{ .... } and then parsing it in to a clipboard score).
> >
> > Best regards,
> >
> > Richard
> >
> >> Of course at this point the code is most likely not bullet proof.
> >>
> >> Regards,
> >> Roy Rankin
> >>
> >>
> >> Richard Shann wrote:
> >>> On Sun, 2008-07-20 at 22:15 -0500, Jeremiah Benham wrote:
> >>>> What is left on the TODO list for the release?
> >>> Well, no one has actually said that they think the release should
> >>> contain a fix for LilyPond import, but Roy is keen that it should be
> >>> possible to load back simple Denemo files saved in LilyPond format, and
> >>> I am keen that it should load some LilyPond files (for which fixes are
> >>> available). I have been getting to grips with the LilyPond load for this
> >>> purpose, but I can't say quite how long it may take.
> >>> It is one of the curses of projects like this that no one says they need
> >>> something until we announce a release, and then it drags on and on. I
> >>> think we should set deadlines for feature requests, announce a schedule
> >>> and, barring showstopping bugs, stick to it.
> >>>
> >>>> I do not want to make any
> >>>> changes to importMidi until the next release. I think I will check out
> >>>> the docs and see what I update. When we make a release it may be
> >>>> embarrassing if the docs are behind. I will look over them and have them
> >>>> update sometime tomorrow.
> >>> That sounds good, the Print Excerpt has no documentation, I think. There
> >>> is an email from you which I didn't respond to (sorry) about this: the
> >>> situation is that if you have a selection, you probably want that as the
> >>> excerpt, or you may want the whole piece of music as a .png (which is
> >>> only properly supported if it fits on one page, else the user has to dig
> >>> the rest out from .denemo/denemoprint*<n>*.png for n pages), (or even to
> >>> select measures by start measure number/end measure number). The
> >>> interface is supposed to support all this, (but is a bit cheap and
> >>> cheerful?).
> >>>
> >>> Richard
> >>>
> >>>
> >>>
> >>>
> >>>
> >>> _______________________________________________
> >>> Denemo-devel mailing list
> >>> address@hidden
> >>> http://lists.gnu.org/mailman/listinfo/denemo-devel
> >>>
> >>
> >> _______________________________________________
> >> Denemo-devel mailing list
> >> address@hidden
> >> http://lists.gnu.org/mailman/listinfo/denemo-devel
> >
> >
> >
> > _______________________________________________
> > Denemo-devel mailing list
> > address@hidden
> > http://lists.gnu.org/mailman/listinfo/denemo-devel
> >
> plain text document attachment (lyparser.y)
> %{ // -*-Fundamental-*-
>
> /*
> adapted from
> parser.yy -- Bison/C++ parser for lilypond
>
> source file of the GNU LilyPond music typesetter
>
> (c) 1997--2001 Han-Wen Nienhuys <address@hidden>
> Jan Nieuwenhuizen <address@hidden>
> adapted for lilyfront (c) Richard Shann 2003
>
> The result of parsing is a GList starting at lily_file
> The data elements of the GList are node* where node is a structure with type,
> user_string and a union.
> Each node in the list represents the result of some rule below, with the
> user_string containing the part of the input file that parsed to that node.
> The nodes are a simple list except
> 1) assignment statements where the assignee is a separate list entered in a
> symbol table.
> 2) SIMULTANEOUS blocks which are nodes pointing to a list for their contents
> 3) \score blocks which are nodes pointing to a list for their contents
> After parsing the function create_score() is run on each score block. This
> creates a staff structure for each \context Staff encountered. The
> staff->measures field is pointed to the start of the block enclosed by the
> \context Staff. This block is traversed and the durations calculated to break
> the list into measures which are linked into the staff->measures list.
> After editing graphically denemo stype the whole list is traversed writing
> out the user_string fields or (where they are NULL) re-creating them from
> the data in the DenemoObject concerned.
> Note that the structure node is arranged to have the same first fields as
> DenemoObject so that either type can appear in the parse tree.
>
> */
> #define YYDEBUG 1
> #define YYPRINT fprintf
> //#define DEBUG 1
> #define YYTOKEN_TABLE 1
> #include <string.h> /*for memcpy */
> #include <stdlib.h> /* for system() */
> #include <denemo/denemo.h>
> #include "view.h" /* this includes many others - many are not
> protected against double inclusion */
> #include "chordops.h"
> #include "objops.h"
> #include "twoints.h"
> #include "processstaffname.h"
> #include "tupletops.h"
> #include "graceops.h"
>
> #include <ctype.h>
>
> #include "lyparserfuncs.h"
> void lyrestart( FILE *new_file );
> extern int lylineno;
> static int parser_error_linenum = 0;
> static gchar *parser_error_message = NULL; /* NULL for no parse error */
> nodemin endcontextnode={endcontext,NULL}; /*the only instantiation of this
> node, used as a marker */
>
>
> #define stradd(m,n) if(n.user_string){m.user_string = \
> g_strconcat(m.user_string,n.user_string, NULL);}
>
> #define LATER_MESSAGE(line) \
> call_parser_error("later at %d\n", __LINE__, line);return EOF
>
>
> static GtkWidget *parser_error_dialog;
> static int error_level_;
> /* lexer states FIXME */
> void push_note_state(void);
> void push_figuredbass_state(void);
> void push_chord_state(void);
> void push_lyric_state(void);
> void pop_state(void);
> gboolean note_state_b(void);
>
>
> int lylex(void);
> static void lyerror(char *);
>
> static void call_parser_error(gchar *text, int lineno, int input_line_number)
> {
> g_print("The parser needs finishing a lyparser.y:%d for this idiom"
> " to be usable\nThe problem occured at line number %d of the"
> " lily input", lineno, input_line_number);
> parser_error("Edit or comment out the offending idiom if possible\n",
> input_line_number);
> }
>
> static GList *lily_file = NULL; /* the entire data generated by the parse */
> /* before EOF there may be white space which won't
> * be collected by any rule - the lexer passes it
> * using set_trailing_white_space()
> */
> static gchar *trailing_white_space = NULL;
>
> GHashTable* name_value_pairs=NULL;
> GHashTable* scm_identifiers=NULL;
>
> #if 0
> #define MALLOC_NODE(n, a) nodegeneric*n = \
> (nodegeneric*)g_malloc0(sizeof(nodegeneric));\
> memcpy(n, &a, sizeof(a));
> #else
> #define MALLOC_NODE(n, a) nodegeneric*n = \
> (nodegeneric*)g_malloc0(sizeof(nodegeneric));\
> n->type=a.type;n->user_string = a.user_string;
> #endif
>
>
> static void set_identifier (char* name, nodeglist *value) {
> if(!name_value_pairs)
> name_value_pairs = g_hash_table_new (g_str_hash, g_str_equal);
> g_hash_table_insert (name_value_pairs, (gpointer)name, (gpointer)value);
> #if DEBUG
> //g_warning("Set identifier %s to value %p\n",name, value);
> g_print("Set identifier %s to value %s\n",name, u_str(value->branch));
> #endif
> }
>
> static nodeglist * typed_glist (GList *g, guint t) {
> nodeglist *nodeg = (nodeglist *)g_malloc0(sizeof(nodeglist));
> nodeg->type = t;
> nodeg->branch = g;
> return nodeg;
> }
>
> #ifdef YYPRINT
> static gchar * type_name(gint type);
> #endif
>
> gboolean
> regular_identifier_b (char *s)
> {
> gboolean v = TRUE;
> while (*s && v)
> {
> v = v && isalpha (*s);
> s++;
> }
> return v;
> }
>
>
>
> static int intlog2(int t) {
> int i=1, n=0;
> while ( (i<<n)<t) n++;
> return n;
> }
>
> gboolean
> is_duration_b (int t)
> {
> return t && t == 1 << intlog2 (t);
> }
>
> node4i default_duration_;
>
> static gchar * keytoname(gint pitch, gint enshift) {
> gchar *ret;
> ret = g_strdup("a");
> *ret += pitch;
> for(;enshift>0;enshift--) ret = g_strconcat(ret,"is",NULL);
> for(;enshift<0;enshift++) ret = g_strconcat(ret,"es",NULL);/*tricksy -
> only one happens */
> return ret;
> }
>
> // needed for bison.simple's malloc () and free ()
>
> #include <malloc.h>
> #include <stdlib.h>
> #include <stdio.h>
>
> #define YYERROR_VERBOSE 1
>
>
>
>
> static void lyerror(char *s) {
> parser_error(s, lylineno);
> }
>
>
>
>
> %}
>
> /* We use SCMs to do strings, because it saves us the trouble of
> deleting them. Let's hope that a stack overflow doesnt trigger a move
> of the parse stack onto the heap. */
>
>
> %{
>
>
>
>
> %}
>
>
> %union {
> nodemin minimal;
> nodegeneric generic;
> nodec c;
> nodei i;
> node2i t;
> node4i f;
> nodeb b;
> noden n;
> nodeid id;
>
> nodegstr gstr;
> nodemus music;
> noder r;
>
>
> nodeglist *branch;
> GList *scm;
> }
>
> /* denemo special tokens */
> %token DENEMO_MEASURES
> /* make a distinction for initial and other clef changes etc for denemo
> which would otherwise issue a change of clef etc at the start of each
> staff */
> %token <generic> TEXT
> %token <gstr> staffcontext voicecontext lyricscontext figuredbasscontext
> %token endcontext
>
>
> %token<gstr> MUSICMODE
> %token<gstr> TONEOPTION
>
>
> %token<gstr> DYNAMICMARK
>
>
>
>
>
>
> /* tokens which are not keywords */
> %token <generic> AUTOCHANGE
> %token <generic> ALIAS
> %token <generic> APPLY
> %token <generic> ARPEGGIO
> %token <generic> DYNAMICSCRIPT
> %token <generic> ACCEPTS
> %token <generic> ALTERNATIVE
> %token <generic> BAR
> %token <generic> BREAK
> %token <generic> BREATHE
> %token <generic> CHORDMODIFIERS
> %token <generic> CHORDS
> %token <generic> CHAR_T
> %token <generic> CLEF_
> %token <generic> CM_T
> %token <generic> CONSISTS
> %token <generic> SEQUENTIAL
> %token <generic> SIMULTANEOUS
> %token <generic> GROBDESCRIPTIONS
> %token <generic> CONSISTSEND
> %token <generic> DENIES
> %token <generic> DURATION
> %token <generic> EXTENDER
> %token <generic> FIGURES FIGURE_OPEN FIGURE_CLOSE
> %token <generic> FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
> %token <generic> GLISSANDO
> %token <generic> GRACE
> %token <generic> HEADER
> %token <generic> HYPHEN
> %token <generic> IN_T
> %token <generic> INVALID
> %token <generic> KEY
> %token <generic> LYRICS
> %token <generic> MARK
> %token <generic> MARKUP
> %token <generic> MULTI_MEASURE_REST
> %token <generic> MIDI
> %token <generic> MM_T
> %token <generic> PITCH
> %token <generic> DEFAULT
> %token <generic> NAME
> %token <generic> PITCHNAMES
> %token <generic> NOTES
> %token <generic> PAPER
> %token <generic> PARTIAL_
> %token <generic> PENALTY
> %token <generic> PROPERTY
> %token <generic> OVERRIDE SET REVERT
> %token <generic> PT_T
> %token <generic> RELATIVE
> %token <generic> REMOVE
> %token <generic> REPEAT
> %token <generic> ADDLYRICS
> %token <generic> PARTCOMBINE
> %token <generic> SCORE
> %token <generic> SCRIPT
> %token <generic> SKIP
> %token <generic> SPANREQUEST
> %token <generic> STYLESHEET
> %token <generic> COMMANDSPANREQUEST
> %token <generic> TEMPO
> %token <generic> OUTPUTPROPERTY
> %token <generic> TIME_T
> %token <generic> TIMES
> %token <generic> TRANSLATOR
> %token <generic> TRANSPOSE
> %token <generic> TYPE
> %token <generic> UNSET
> %token <minimal> CONTEXT
> %token <generic> LAYOUT
> %token <generic> LYRICSTO
> %token <generic> LYRICMODE
> %token <generic> NEWCONTEXT
> %token <generic> LILYVERSION
> %token <generic> DRUM_PITCH
> %token <generic> MUSIC_FUNCTION
> %token <i> REST
>
> %token DOUBLE_ANGLE_CLOSE ">>"
> %token DOUBLE_ANGLE_OPEN "<<"
>
>
> /* escaped */
> %token <generic> E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
> %token E_LEFTSQUARE E_RIGHTSQUARE E_TILDE
> %token E_BACKSLASH
> %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
> %token <generic> FIGURE_SPACE
>
>
> %type <i> exclamations questions dots optional_rest
> %type <i> bass_number bass_mod
> %type <generic> br_bass_figure bass_figure figure_list figure_spec
>
> %token <generic> '='
> %token <generic> '{'
> %token <generic> '<'
> %token <generic> '}'
> %token <generic> '>'
> %token <generic> '|'
> %token <generic> '/'
> %token <generic> '*'
> %token <generic> '('
> %token <generic> ')'
> %token <generic> '~'
> %token <generic> '['
> %token <generic> ']'
> //%token <generic> ">>"
> //%token <generic> "<<"
>
> %token <i> '.'
> %token <i> '?'
> %token <i> '!'
>
> %token <i> '\''
> %token <i> ','
>
>
> %token <i> DIGIT
> %token <t> NOTENAME_PITCH
> %token <t> TONICNAME_PITCH
> %token <t> CHORDMODIFIER_PITCH
> %token <id> DURATION_IDENTIFIER
> %token <t> FRACTION
> %token <id> IDENTIFIER
>
>
> %token <id> SCORE_IDENTIFIER
> %token <id> MUSIC_OUTPUT_DEF_IDENTIFIER
>
> %token <id> NUMBER_IDENTIFIER
> %token <id> REQUEST_IDENTIFIER
> %token <id> MUSIC_IDENTIFIER TRANSLATOR_IDENTIFIER
> %token <id> STRING_IDENTIFIER
> %token <gstr> SCM_IDENTIFIER
> %token <generic> RESTNAME
> %token <generic> SKIPNAME
> %token <gstr> STRING_
> %token <generic> SCM_T
> %token <i> UNSIGNED
> %token <r> REAL
>
> %type <scm> output_def
> %type <scm> lilypond_header lilypond_header_body toplevel_expression
> assignment score_block
> %type <scm> direction_less_char direction_less_event direction_reqd_event
> %type <i> sub_quotes sup_quotes
> %type <scm> simple_element event_chord command_element Simple_music
> Composite_music
> %type <scm> chord_body
> %type <scm> chord_body_element
> %type <scm> music_function_chord_body
> %type <scm> chord_body_elements
> %type <scm> Repeated_music
> %type <scm> Alternative_music
> %type <i> tremolo_type
> %type <i> bare_int bare_unsigned
> %type <i> script_dir
> %type <i> octave_check
>
> %type <branch> identifier_init
>
> %type <f> steno_duration
> %type <f> optional_notemode_duration multiplied_duration
> %type <f> verbose_duration
>
> %type <scm> post_events
> %type <scm> note_chord_element
> %type <scm> gen_text_def
> %type <scm> full_markup
> %type <n> steno_pitch pitch absolute_pitch
> %type <n> explicit_pitch steno_tonic_pitch
>
> %type <scm> chord_additions chord_subtractions chord_notes chord_step
> %type <music> chord
> %type <scm> chord_note chord_inversion chord_bass
> %type <f> duration_length
> %type <t> fraction
>
> %type <scm> embedded_scm scalar
> %type <scm> Music Sequential_music Simultaneous_music
> %type <scm> relative_music re_rhythmed_music part_combined_music
> %type <scm> property_def translator_change
> %type <scm> Music_list
> %type <scm> music_output_def_body
> %type <scm> shorthand_command_req
> %type <scm> post_event
> %type <scm> command_req verbose_command_req
> %type <scm> extender_req
> %type <scm> hyphen_req
> %type <gstr> string
> %type <scm> bare_number number_expression number_term number_factor
>
> %type <scm> score_body
>
> %type <scm> translator_spec_block translator_spec_body
> %type <scm> tempo_event tempo_optional
> %type <scm> notenames_body notenames_block chordmodifiers_block
> %type <scm> script_abbreviation
>
>
>
> %left '-' '+'
>
> /* We don't assign precedence to / and *, because we might need varied
> prec levels in different prods */
>
> %left UNARY_MINUS
>
> %%
>
> lilypond: /* empty */
> | lilypond toplevel_expression {
> if(lily_file) {
> GList *ret;
> ret = g_list_concat (lily_file, $2);
> } else {
> lily_file = $2;
> }
> }
> | lilypond assignment {
> if(lily_file) {
> GList *ret;
> ret = g_list_concat(lily_file, $2);
> } else {
> lily_file = $2;
> }
> }
> | lilypond error {
> error_level_ = 1;
> }
> | lilypond INVALID {
> error_level_ = 1;
> }
> ;
>
> toplevel_expression:
> notenames_block
> { /* this is the \pitchnames thing in the include files - we will
> perhaps leave this out for now - see below for where the
> include file is parsed for the pitchname table - we have to
> recognize at least one set of pitchnames of course ...*/
> $$ = g_list_append(NULL, $1);
> /* creates a new mudelaobj structure comprising the token TEXT,
> and the Gstring pointed to by input_text, which is reset to NULL.
> We ignore the value of notename_block since we don't interpret
> it further */
> }
> | chordmodifiers_block {
> $$ = $1;
> }
> | lilypond_header {
> $$ = $1;
> }
> | score_block {
> $$ = $1;/* add this score to the root data list lily_file */
> }
> | output_def {
> $$ = $1;
> }
> | embedded_scm {
> $$ = $1;
> }
> ;
>
>
> embedded_scm:
> SCM_T {
> MALLOC_NODE(n, $1);
> $$ = g_list_append(NULL,n);
> }
> | SCM_IDENTIFIER {
> MALLOC_NODE(n, $1);
> ((nodegstr*)n)->gstr = $1.gstr;
> $$ = g_list_append(NULL, n);
> }
> ;
>
>
> chordmodifiers_block:
> CHORDMODIFIERS notenames_body { $$ = $2;
> /* intercept this at lexical level*/
> }
> ;
>
> notenames_block:
> PITCHNAMES notenames_body { $$ = $2; }
> ;
>
> notenames_body:
> embedded_scm {
> $$ = $1;
> }
> ;
>
> lilypond_header_body:
> {
> $$ = NULL;
> }
> | lilypond_header_body assignment {
> if($1) {
> $$ = g_list_concat($1, $2);
> }
> else
> $$ = $2;
> }
> ;
>
> lilypond_header:
> HEADER '{' lilypond_header_body '}' {
> MALLOC_NODE(n1, $1);
> MALLOC_NODE(n4, $4);
> n1->user_string = g_strconcat($1.user_string, $2.user_string, NULL);
> $$ = g_list_append(NULL,n1);
> $$ = g_list_concat($$,$3);
> $$ = g_list_append($$, n4);
> }
> |
> LILYVERSION STRING_
> {
> MALLOC_NODE(n,$1);
> g_free(n->user_string);
> n->user_string = $2.gstr->str;
> set_identifier("lilyversion", typed_glist (g_list_append(NULL,n),
> STRING_IDENTIFIER));
> $$ = NULL;
> }
> ;
>
>
> /*
> DECLARATIONS
> */
> assignment:
> STRING_ '=' identifier_init {
> GList *ret;
> MALLOC_NODE (n1, $1);
> MALLOC_NODE (n2, $2);
> if (! regular_identifier_b ($1.gstr->str))
> {
> g_warning (_("Identifier should have alphabetic characters"
> " only please"));
> }
> #if DEBUG
> g_print("got to assignment with %s %s ",$1.gstr->str,
> $2.user_string);
> if ($3->type == STRING_IDENTIFIER)
> g_print("%s\n", u_str($3->branch));
> else
> g_print("type %d\n", $3->type);
> #endif
> /* $3 because mid rule action deleted */
> set_identifier ($1.gstr->str, $3);
>
> ((nodeglist*)n2)->branch = $3->branch;
> ret = g_list_append(NULL, n2);
> $$ = g_list_prepend(ret, n1);
> /*
> TODO: devise standard for protection in parser.
>
> The parser stack lives on the C-stack, which means that
> all objects can be unprotected as soon as they're here.
>
> */
> }
> ;
>
>
> identifier_init:
> score_block { /* I don't think this can ever get used, once defined! */
> $$ = typed_glist ($1, SCORE_IDENTIFIER);
> }
> | output_def {
> $$ = typed_glist ($1, MUSIC_OUTPUT_DEF_IDENTIFIER);
> }
> | translator_spec_block {
> $$ = typed_glist (g_list_append(NULL,$1),
> TRANSLATOR_IDENTIFIER);
> }
> | Music {
> $$ = typed_glist ($1, MUSIC_IDENTIFIER);
> }
> | post_event {
> $$ = typed_glist ($1, REQUEST_IDENTIFIER);
> }
> | verbose_duration {
> MALLOC_NODE(n,$1);
> $$ = typed_glist (g_list_append(NULL,n), DURATION_IDENTIFIER);
> }
> | number_expression {
> $$ = typed_glist ($1, STRING_IDENTIFIER);
> }
> | string {
> nodegeneric x;
> x.type = STRING_IDENTIFIER;
> x.user_string = strdup($1.gstr->str);
> MALLOC_NODE(n,x);
> $$ = typed_glist (g_list_append(NULL,n), STRING_IDENTIFIER);
> }
> | embedded_scm {
> $$ = typed_glist ($1, SCM_IDENTIFIER);
> }
>
> ;
>
> translator_spec_block:
> TRANSLATOR '{' translator_spec_body '}'
> {
> $$ = $3;
> }
> ;
>
> translator_spec_body:
> TRANSLATOR_IDENTIFIER {
> }
> ;
>
> /*
> SCORE
> */
> score_block:
> SCORE '{' score_body '}' {
> MALLOC_NODE(n,$1);
> n->user_string = g_strconcat($1.user_string, "{" , NULL);
> /*FIXME memory leak of $1,2 */
> ((nodeglist*)n)->post_user_string = "}";
> ((nodeglist*)n)->branch = $3;
> $$ = g_list_append(NULL, n);
> }
> ;
>
> score_body:
> Music {
>
> $$ = $1;
> }
> | SCORE_IDENTIFIER {
> $$ = g_list_append(NULL, $1.id);
> }
> | score_body lilypond_header {
> // lyerror ("parser should have caught this score header");
> /*intercept this at lexical level*/
> }
> | score_body output_def {
> //lyerror ("parser should have caught this");
> /*intercept this at lexical level*/
> }
> | score_body error {
> lyerror("score_body error");
> }
> ;
>
>
> /*
> MIDI
> */
> output_def:
> music_output_def_body '}' {
> MALLOC_NODE(n2, $2)
> $$ = g_list_append($1, n2);
>
> /* THIS-> lexer_-> scopes_.pop ();*/
> }
> ;
>
>
> music_output_def_body:
> MIDI '{' tempo_optional {
> set_identifier("midi_tempo", typed_glist ($3,
> STRING_IDENTIFIER));
> $$ = $3;
> }
> | PAPER '{' {
> /* caught by lexer - does not occur*/
> lyerror ("parser should have caught this-paper");
> }
> | LAYOUT '{' {
> /* caught by lexer - does not occur*/
> lyerror ("parser should have caught this - layout");
> }
> | music_output_def_body error {
> lyerror("music_output_def_body error");
> }
> ;
>
> tempo_optional:
> /* empty */ {
> $$ = NULL;
> }
> | tempo_event {
> $$ = $1;
> }
> ;
>
> tempo_event:
> TEMPO steno_duration '=' bare_unsigned {
> MALLOC_NODE(n, $4);
> ((nodei*)n)->i = $4.i;
> $$ = g_list_append(NULL, n);
> }
> ;
>
> /*
> The representation of a list is the
>
> (LIST . LAST-CONS)
>
> to have efficient append.
> */
> Music_list: /* empty */ {
> $$ = NULL;
> }
> | Music_list Music {
> if($1)
> {
> #if DEBUG
> g_print("building up a music list now from %s to %s\n", u_str($1),
> u_str($2));
> #endif
> $$ = g_list_concat($1, $2);
> }
> else
> $$ = $2;
> }
> /*
> | Music_list embedded_scm {
>
> }
> */
> | Music_list error {
> }
> ;
>
>
> Music:
> Simple_music
> | Composite_music
> {
> $$ = $1;
> }
> ;
>
> Alternative_music:
> /* empty */ {
> $$ = NULL;
> }
> | ALTERNATIVE '{' Music_list '}' {
> GList* ret;
> MALLOC_NODE(n1, $1);
> MALLOC_NODE(n4, $4);
> stradd($1, $2);
> ret = g_list_append(NULL, n1);
> ret = g_list_concat(ret, $3);
> $$ = g_list_append(ret, n4);
> }
> ;
>
> Repeated_music:
> REPEAT string bare_unsigned Music Alternative_music
> {
> GList* ret;
> MALLOC_NODE(n1, $1);
> stradd($1, $2);
> stradd($1, $3);
> ret = g_list_append(NULL, n1);
> ret = g_list_concat(ret, $4);
> if($5)
> ret = g_list_concat(ret, $5);
> $$ = ret;
>
> #if 0
>
> $$ = new_data_el (REPEAT,); FINISH THIS
> $$ = g_list_append ($$, new_data_el (STRINGL)....need to have
> the input strings
> for each token available - use a struct in yylval.
> #endif
> }
> ;
>
> Sequential_music:
> SEQUENTIAL '{' Music_list '}' {
> MALLOC_NODE(n1, $1);
> n1->user_string = g_strconcat($1.user_string, "{", NULL);
> /*FIXME memory leak $1,2 and $4*/
> ((nodeglist*)n1)->post_user_string = "}" ;
> ((nodeglist*)n1)->branch = $3;
> $$ = g_list_prepend(NULL, n1);
> }
> | '{' Music_list '}' {
> MALLOC_NODE(n1, $1);
> n1->user_string = "{";
> ((nodeglist*)n1)->post_user_string = "}";
> /* FIXME memory leak of $3 */
> ((nodeglist*)n1)->type = SEQUENTIAL;
> ((nodeglist*)n1)->branch = $2;
> $$ = g_list_prepend(NULL, n1);
> }
> ;
>
> Simultaneous_music:
> SIMULTANEOUS '{' Music_list '}'{
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> $$ = new Simultaneous_music (SCM_EOL);
> $$->set_mus_property ("elements", ly_car ($3));
> $$->set_spot(THIS->here_input());
> #endif
> }
> | simul_open Music_list simul_close {
> /* we don't try to disambiguate chords on one stave from
> notes one to a staff here
> that is done in generate_chords() called by create_score() */
> // RRR MALLOC_NODE(n1, $2);
> nodegeneric*n1 = (nodegeneric*)g_malloc0(sizeof(nodegeneric));
> n1->user_string = "<<";
> ((nodeglist*)n1)->post_user_string = ">>";
> /* FIXME memory leak of $3 */
> ((nodeglist*)n1)->type = SIMULTANEOUS;
> ((nodeglist*)n1)->branch = $2;
> $$ = g_list_prepend(NULL, n1);
> }
> ;
>
> Simple_music:
> event_chord { $$ = $1; }
> | OUTPUTPROPERTY embedded_scm embedded_scm '=' embedded_scm {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> SCM pred = $2;
> if (!gh_symbol_p ($3))
> {
> THIS->parser_error (_ ("Second argument must be a symbol"));
> }
> /* Should check # args */
> if (!gh_procedure_p (pred))
> {
> THIS->parser_error (_ ("First argument must be a procedure"
> " taking one argument"));
> }
>
> Music *m = new Music (SCM_EOL);
> m->set_mus_property ("predicate", pred);
> m->set_mus_property ("grob-property", $3);
> m->set_mus_property ("grob-value", $5);
> m->set_mus_property ("iterator-ctor",
> Output_property_music_iterator::constructor_cxx_function);
>
> $$ = m;
> #endif
> }
> | MUSIC_IDENTIFIER { /* this may be ok now ... */
> /* has to be big enough for DenemoObject access
> eg when writing start_ticks in break into measures... */
> nodeid *n = (nodeid*)g_malloc0(sizeof(nodegeneric));
> n->type = $1.type;
> n->user_string = $1.user_string;
> n->id = $1.id;
> $$ = g_list_append(NULL, n);
>
> }
> | property_def {
>
> $$ = $1;
> /* FIXME - we really don't want to put all these nodes into
> the music, as denemo will have to go over them -
> amalgamate the strings into a TEXT node */
>
>
> }
> | translator_change {
> LATER_MESSAGE(@$.first_line);
> }
> ;
>
>
> Composite_music:
> CONTEXT STRING_ Music {
> MALLOC_NODE (n1, $1);
> if(!strcmp("Staff",$2.gstr->str))
> n1->type = staffcontext;
> else if(!strcmp("Voice",$2.gstr->str))
> n1->type = voicecontext;
> else if(!strcmp("Lyrics",$2.gstr->str))
> n1->type = lyricscontext;
> else if(!strcmp("FiguredBass",$2.gstr->str))
> n1->type = figuredbasscontext;
> else
> n1->type = TEXT;/*ignore other contexts at present */
> n1->user_string = g_strconcat($1.user_string, $2.user_string,
> NULL);
> if (n1->type == TEXT)
> $$ = g_list_prepend($3, n1);
> else
> $$ = g_list_append(g_list_prepend($3, n1),
> &endcontextnode);
> /* FIXME memory leak of $2 */
> }
> | AUTOCHANGE STRING_ Music {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Music * chm = new Music_wrapper (SCM_EOL);
> chm->set_mus_property ("element", $3);
> chm->set_mus_property ("iterator-ctor",
> Auto_change_iterator::constructor_cxx_function);
>
> scm_gc_unprotect_object ($3);
> chm->set_mus_property ("what", $2);
>
> $$ = chm;
> chm->set_spot (*$3->origin ());
> #endif
> }
> | GRACE Music {
> DenemoObject *start, *end;
> start = newgracestart();
> end = newgraceend();
> start->user_string = $1.user_string;
> /* prevent denemo generating a "}" string
> this will take some effort to handle better than this hack. FIXME */
> end->user_string = g_strdup(" ");
> $$ = g_list_append(g_list_prepend ($2,start ), end);
>
> }
> | CONTEXT string '=' string Music {
> MALLOC_NODE(n1, $1);
> ((nodegstr*)n1)->gstr = $4.gstr;
> if(!strcmp("Staff",$2.gstr->str))
> n1->type = staffcontext;
> else if(!strcmp("Voice",$2.gstr->str))
> n1->type = voicecontext;
> else if(!strcmp("Lyrics",$2.gstr->str))
> n1->type = lyricscontext;
> else if(!strcmp("FiguredBass",$2.gstr->str))
> n1->type = figuredbasscontext;
> else
> n1->type = TEXT;/*ignore other contexts at present */
> n1->user_string = g_strconcat($1.user_string, $2.user_string,
> "=", $4.user_string,
> NULL);
> if (n1->type == TEXT)
> $$ = g_list_prepend($5, n1);
> else
> $$ = g_list_append(g_list_prepend($5, n1),
> &endcontextnode);
> /* FIXME memory leak $2 $3 $4 */
> }
> | NEWCONTEXT STRING_ Music {
> MALLOC_NODE (n1, $1);
> if(!strcmp("Staff",$2.gstr->str))
> n1->type = staffcontext;
> else if(!strcmp("Voice",$2.gstr->str))
> n1->type = voicecontext;
> else if(!strcmp("Lyrics",$2.gstr->str))
> {
> n1->type = lyricscontext;
> }
> else if(!strcmp("FiguredBass",$2.gstr->str))
> n1->type = figuredbasscontext;
> else
> n1->type = TEXT;/*ignore other contexts at present */
> n1->user_string = g_strconcat($1.user_string, $2.user_string,
> NULL);
> if (n1->type == TEXT)
> $$ = g_list_prepend($3, n1);
> else
> $$ = g_list_append(g_list_prepend($3, n1),
> &endcontextnode);
> }
> | TIMES fraction Music
>
> {DenemoObject *tupopen, *tupclose;
> tupopen = newtupopen ($2.t.a, $2.t.b);
> tupclose = newtupclose ();
> g_assert(ntype($3)==SEQUENTIAL);
>
> tupopen->user_string = g_strconcat($1.user_string,
> $2.user_string, u_str($3),
> NULL);
> tupclose->user_string = u_post_str($3);
> $$ = g_list_append(g_list_prepend (br($3), tupopen), tupclose);
> }
> | Repeated_music {
> $$ = $1;
> }
> | Simultaneous_music {
> $$ = $1;
> }
> | Sequential_music {
> $$ = $1;
> }
> | TRANSPOSE pitch pitch Music {
>
> /* could we try to display transposed?? later FIXME */
> GList* ret;
> MALLOC_NODE(n1, $1);
> n1->user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string,
> NULL);
> ret = g_list_append(NULL, n1);
> $$ = g_list_concat(ret, $4);
>
>
> }
> | TRANSPOSE steno_tonic_pitch Music {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> $$ = new Transposed_music (SCM_EOL);
> Music *p = $3;
> Pitch pit = *unsmob_pitch ($2);
>
> p->transpose (pit);
> $$->set_mus_property ("element", p);
> scm_gc_unprotect_object (p);
> #endif
> }
> | APPLY embedded_scm Music {
> u_str($2) = g_strconcat($1.user_string, u_str($2), NULL);
> $$ = g_list_concat($2, $3);
> }
> | NOTES
> { push_note_state (); }
> /* cont */
> Music
> {
> MALLOC_NODE(n1, $1);
> $$ = g_list_prepend($3, n1);
> pop_state();
> }
> | FIGURES
> { push_figuredbass_state (); }
> Music
> {
> MALLOC_NODE(n1, $1);
> $$ = g_list_prepend($3, n1);
> pop_state();
> }
> | CHORDS
> { push_chord_state (); }
> Music
> {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Music * chm = new Un_relativable_music ;
> chm->set_mus_property ("element", $3);
> scm_gc_unprotect_object ($3->self_scm());
> $$ = chm;
>
> THIS->lexer_->pop_state ();
> #endif
> }
> | LYRICS
> { push_lyric_state (); }
> Music
> {
> LATER_MESSAGE(@$.first_line);
> MALLOC_NODE(n, $1)
> $$ = g_list_prepend($3, n);
> pop_state();
> }
> | LYRICMODE
> { push_lyric_state (); }
> Music
> {
> MALLOC_NODE(n, $1)
> $$ = g_list_prepend($3, n);
> pop_state();
> }
> | relative_music {
> $$ = $1;
> }
> | re_rhythmed_music {
> $$ = $1;
> }
> | part_combined_music {
> $$ = $1;
> }
> ;
>
> relative_music:
> RELATIVE absolute_pitch Music {
> MALLOC_NODE(n, $1)
> g_warning("\\relative not yet handled - do not edit graphically");
> n->user_string = g_strconcat($1.user_string, $2.user_string, NULL);
> $$ = g_list_prepend($3, n);
> /* we have to record the pitch in the node and then use it to start
> relative interpretation of future CHORD nodes FIXME
> well, not really we have to record it in a variable akin to
> default_duration_ which can then be tracked to determine the
> semantics of future notes??? Or has
> Music already been interpreted when this rule is activated... */
> }
> ;
>
> re_rhythmed_music:
> ADDLYRICS Music Music {
> MALLOC_NODE(n, $1);
> ((nodeglist*)n)->branch = g_list_append(g_list_append(NULL,
> g_list_append(NULL, $2)), g_list_append(NULL, $3)); /* ADDLYRICS is a branch
> containing two GLists */
> $$ = g_list_append(NULL, n);
> }
> | LYRICSTO STRING_ Music {
> GList *g;
> MALLOC_NODE(n, $1);
> g_free(n->user_string);
> if (*$2.gstr->str == '\"')
> {
> GString * name = g_string_erase ($2.gstr, 0, 1);
> name = g_string_truncate(name, name->len - 1);
> n->user_string = name->str;
> }
> else
> n->user_string = $2.gstr->str;
> if (ntype ($3) == NEWCONTEXT)
> {
> g = $3;
> $3 = g_list_remove_link ( $3, g);
> g_list_free(g);
> }
> ((nodeglist*)n)->branch = $3;
> $$ = g_list_append(NULL, n);
> }
> ;
>
> part_combined_music:
> PARTCOMBINE STRING_ Music Music {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Part_combine_music * p = new Part_combine_music (SCM_EOL);
>
> p->set_mus_property ("what", $2);
> p->set_mus_property ("elements", gh_list ($3,$4,
> SCM_UNDEFINED));
>
> scm_gc_unprotect_object ($3);
> scm_gc_unprotect_object ($4);
>
> $$ = p;
> #endif
> }
> ;
>
> translator_change:
> TRANSLATOR STRING_ '=' STRING_ {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Music * t = new Music (SCM_EOL);
> t->set_mus_property ("iterator-ctor",
> Change_iterator::constructor_cxx_function);
> t-> set_mus_property ("change-to-type", $2);
> t-> set_mus_property ("change-to-id", $4);
>
> $$ = t;
> $$->set_spot (THIS->here_input ());
> #endif
> }
> ;
>
> property_def:
> PROPERTY STRING_ '.' STRING_ '=' scalar {
> MALLOC_NODE(n, $1)
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> ".", $4.user_string,
> "=", u_str($6), NULL);
> $$ = g_list_append(NULL, n); /* FIXME memory leak*/
> }
> | PROPERTY STRING_ '.' STRING_ UNSET {
> MALLOC_NODE(n, $1)
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, $4.user_string,
> $5.user_string, NULL);
> $$ = g_list_append(NULL, n); /* FIXME memory leak*/
> }
> | SET STRING_ '.' STRING_ '=' embedded_scm {
> MALLOC_NODE(n, $1)
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, $4.user_string,
> $5.user_string, u_str($6), NULL);
> $$ = g_list_append(NULL, n);
> }
> | SET STRING_ '.' STRING_ '=' STRING_ {
> MALLOC_NODE(n, $1)
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, $4.user_string,
> $5.user_string, $6.user_string, NULL);
> $$ = g_list_append(NULL, n);
> }
> | OVERRIDE STRING_ '.' STRING_ '=' embedded_scm {
> MALLOC_NODE(n, $1);
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, $4.user_string,
> $5.user_string, u_str($6), NULL);
> $$ = g_list_append(NULL, n);
> }
> | OVERRIDE STRING_ embedded_scm '=' embedded_scm {
> MALLOC_NODE(n, $1);
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> u_str ($3), $4.user_string,
> u_str ($5), NULL);
> $$ = g_list_append (NULL, n);
> }
> | REVERT STRING_ embedded_scm {
> MALLOC_NODE(n, $1);
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> u_str ($3), NULL);
> $$ = g_list_append (NULL, n);
> }
>
> | PROPERTY STRING_ '.' STRING_ REVERT embedded_scm {
> MALLOC_NODE(n, $1);
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, $4.user_string,
> $5.user_string, u_str ($6), NULL);
> $$ = g_list_append (NULL, n);
> }
> ;
>
>
> scalar:
> string { MALLOC_NODE(n, $1);$$ = g_list_append (NULL, n);
> /*FIXME copy value */}
> | bare_int { MALLOC_NODE(n, $1);$$ = g_list_append (NULL, n);
> /*FIXME copy value */ }
> | embedded_scm { $$ = $1; }
> ;
>
> pre_events: /* empty */
> ;
>
> event_chord:
> pre_events simple_element post_events {
> /* things like start cresc, simple_element end cresc */
>
> set_post_events ((DenemoObject *) ($2->data), u_str ($2), $3);
>
> $$ = $2;/* FIXME memory leak */
> }
> | command_element {
> $$ = $1;
> }
> | note_chord_element {
> $$ = $1;
> }
> ;
>
> note_chord_element:
> chord_body optional_notemode_duration post_events
> {
> GList *firstchord = br ($1);
> if (firstchord && firstchord->data)
> changedur ((DenemoObject *)(firstchord->data), $2.t1.a,
> $2.t1.b);
> set_post_events ((DenemoObject *) ($1->data), u_str ($1), $3);
> $$ = $1;
> }
> ;
>
>
> chord_open: '<'
> ;
>
> chord_close: '>'
> ;
>
> chord_body:
> chord_open chord_body_elements chord_close
> {
> nodegeneric*n1 = (nodegeneric*)g_malloc0(sizeof(nodegeneric));
> n1->user_string = "<";
> ((nodeglist*)n1)->post_user_string = ">";
> ((nodeglist*)n1)->type = SIMULTANEOUS;
> ((nodeglist*)n1)->branch = $2;
> $$ = g_list_prepend(NULL, n1);
> }
> ;
>
> chord_body_elements:
> /* empty */ { $$ = NULL; }
> | chord_body_elements chord_body_element {
> $$ = g_list_concat ($1, $2);
> }
> ;
>
> music_function_chord_body:
> MUSIC_FUNCTION {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_list_2 ($1, make_input (@$));
> #endif
> }
>
> ;
>
> chord_body_element:
> pitch exclamations questions octave_check post_events {
> DenemoObject *mud = newchord ( 0, 0, 0);
>
> if (!note_state_b ())
> lyerror (_ ("Have to be in Note mode for notes"));
>
> addtone ( mud, $1.n.mid_c_offset, $1.n.enshift, 0);/*FIXME
> should be
> using $1.n directly */
>
> #define no ((note*)((((chord *)mud->object)->notes)->data))
> if ($3.i % 2)
> {
> no->showaccidental = TRUE;
> ( (chord *)mud->object)->hasanacc = TRUE;
> }
> if ($2.i % 2 ) {
> no->showaccidental = TRUE;
> ( (chord *)mud->object)->hasanacc = TRUE;
> }
> #undef no
>
> mud->user_string = $1.user_string;
> if ($2.i) stradd ( (*mud),$2);
> if ($3.i) stradd ( (*mud),$3);
> //stradd ( (*mud),$4);
>
> set_post_events (mud, mud->user_string, $5);
> $$ = g_list_append (NULL,mud);
> }
> | DRUM_PITCH post_events {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Music *n = MY_MAKE_MUSIC ("NoteEvent");
> n->set_property ("duration", $2);
> n->set_property ("drum-type", $1);
> n->set_spot (@$);
>
> if (scm_is_pair ($2)) {
> SCM arts = scm_reverse_x ($2, SCM_EOL);
> n->set_property ("articulations", arts);
> }
> $$ = n;
> #endif // LATER
> }
> | music_function_chord_body {
> LATER_MESSAGE(@$.first_line);
> }
> ;
>
> command_element:
> command_req {
> $$ = $1;
> }
> | E_LEFTSQUARE {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Span_req *l = new Span_req;
> l->set_span_dir (START);
> l->set_mus_property ("span-type", scm_makfrom0str ("ligature"));
> l->set_spot (THIS->here_input ());
>
> $$ = new Request_chord (SCM_EOL);
> $$->set_mus_property ("elements", gh_cons (l, SCM_EOL));
> scm_gc_unprotect_object (l->self_scm ());
> $$->set_spot (THIS->here_input ());
> #endif
> }
> | E_RIGHTSQUARE {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Span_req *l = new Span_req;
> l->set_span_dir (STOP);
> l->set_mus_property ("span-type", scm_makfrom0str ("ligature"));
> l->set_spot (THIS->here_input ());
>
> $$ = new Request_chord (SCM_EOL);
> $$->set_mus_property ("elements", gh_cons (l, SCM_EOL));
> $$->set_spot (THIS->here_input ());
> scm_gc_unprotect_object (l->self_scm ());
> #endif
> }
> | E_BACKSLASH {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> $$ = new Music (gh_list (gh_cons (ly_symbol2scm ("name"),
> ly_symbol2scm ("separator")), SCM_UNDEFINED));
> $$->set_spot (THIS->here_input ());
> #endif
> }
> | '|' {
> MALLOC_NODE(n, $1);
> $$ = g_list_append(NULL, n); /* this node used to be used by denemo to
> split the glist into measures */
> }
> | BAR STRING_ {
> MALLOC_NODE(n, $1);
>
> n->user_string = g_strconcat($1.user_string, $2.user_string,
> NULL);/* FIXME memory leaks */
> $$ = g_list_append(NULL, n);
> }
> | PARTIAL_ duration_length {
> // g_warning ("\\partial not currently supported");
> DenemoObject *mud = newchord( $2.t1.a, $2.t1.b,0);
> mud->type = PARTIAL;
> /* FIXME - we need to store all four ints then use them to determine how much
> measure to skip */
> mud->user_string = g_strconcat($1.user_string,
> $2.user_string,NULL);
> /* FIXME memory leaks on strings concatenated */
> $$ = g_list_append(NULL,mud);
> }
> | CLEF_ STRING_ {
> DenemoObject *mud = dnm_newclefobj
> (cleftypefromname($2.gstr->str));
> mud->user_string = g_strconcat($1.user_string,
> $2.user_string,NULL);
> /* FIXME memory leaks on strings concatenated */
> $$ = g_list_append(NULL,mud);
> }
> | TIME_T fraction {
> DenemoObject *mud = dnm_newtimesigobj ($2.t.a, $2.t.b);
> mud->user_string = g_strconcat($1.user_string,
> $2.user_string,NULL);
> /* FIXME memory leaks on strings concatenated */
> $$ = g_list_append(NULL,mud);
> }
> | BREAK { /* ignore */
> $$ = NULL;
> }
> ;
>
> command_req:
> shorthand_command_req { $$ = $1; }
> | verbose_command_req { $$ = $1; }
> ;
>
> shorthand_command_req:
> extender_req {
> $$ = $1;
> }
> | hyphen_req {
> $$ = $1;
> }
> | '[' {
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);/* FIXME denemo should know about this */
> }
> | ']' {
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);/* FIXME denemo should know about this */
>
>
> }
> | BREATHE {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> $$ = new Breathing_sign_req;
> #endif
> }
> | E_TILDE {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> $$ = new Porrectus_req;
> #endif
> }
> ;
>
> verbose_command_req:
> COMMANDSPANREQUEST bare_int STRING_ { /*TODO: junkme */
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Span_req * sp = new Span_req;
> sp-> set_span_dir ( Direction ($2));
> sp->set_mus_property ("span-type",$3);
> sp->set_spot (THIS->here_input ());
> $$ = sp;
> #endif
> }
> | MARK DEFAULT {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Mark_req * m = new Mark_req;
> $$ = m;
> #endif
> }
> | MARK scalar {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Mark_req *m = new Mark_req;
> m->set_mus_property ("label", $2);
> $$ = m;
> #endif
> }
> | SKIP duration_length {
> /* denemo doesn't want to know? */
> MALLOC_NODE(n, $1)
>
> n->type=TEXT;
> n->user_string = g_strconcat($1.user_string, $2.user_string, NULL);
> $$ = g_list_append(NULL,n);
>
> #ifdef LATER
> Skip_req * skip = new Skip_req;
> skip->set_mus_property ("duration", $2);
>
> $$ = skip;
> #endif
> }
> | tempo_event {
> LATER_MESSAGE(@$.first_line);
> // $$ = $1;
> }
> | KEY DEFAULT {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
>
> Key_change_req *key= new Key_change_req;
> $$ = key;
> #endif
> }
> | KEY NOTENAME_PITCH MUSICMODE {
> gchar *keyname = keytoname($2.t.a, $2.t.b);
> DenemoObject *mud;
> /* the convoluted conversion is due to historical mismatch of
> lily and denemo*/
> if (!strcmp($3.gstr->str, "minor"))
> mud = dnm_newkeyobj(keynametonumber(keyname)-3, TRUE,
> 0);
> else
> mud = dnm_newkeyobj(keynametonumber(keyname), FALSE, 0);
> mud->user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, NULL);
> $$ = g_list_append(NULL,mud);
> }
> ;
>
> post_events:
> {
> $$ = NULL;
> }
> | post_events post_event {
> if($1) {
> $$ = g_list_concat($1, $2);
> }
> else
> $$ = $2;
> }
> ;
>
> post_event:
> direction_less_event {
> $$ = $1;
> }
> | script_dir direction_reqd_event {
> /* script_dir is an integer saying whether up down or centred
> denemo doesn't understand this yet */
> u_str($2) = g_strconcat ( $1.user_string, u_str($2), NULL);
> $$ = $2;
> }
> | script_dir direction_less_event {
> /* script_dir is an integer saying whether up down or centred
> denemo doesn't understand this yet */
> u_str($2) = g_strconcat ( $1.user_string, u_str($2), NULL);
> $$ = $2;
> }
> ;
>
>
> direction_reqd_event:
> gen_text_def {
> $$ = $1;
> }
> | script_abbreviation {
> $$ = $1;
> }
> ;
>
> octave_check:
> /**/ { }
> | '=' { $$.i = 0; }
> | '=' sub_quotes { $$ = $2; }
> | '=' sup_quotes { $$ = $2; }
> ;
>
>
> sup_quotes:
> '\'' {
> $1.i = 1;
> $$ = $1;
> }
> | sup_quotes '\'' {
> $1.i ++;
> $1.user_string = g_strconcat($1.user_string,$2.user_string,
> NULL);/*FIXME memory leak */
> $$ = $1;
> }
> ;
>
> sub_quotes:
> ',' {
> $1.i = 1;
> $$ = $1;
> }
> | sub_quotes ',' {
> $1.i ++ ;
> $1.user_string = g_strconcat($1.user_string,$2.user_string,
> NULL);/*FIXME memory leak */
> $$ = $1;
> }
> ;
>
> steno_pitch:
> NOTENAME_PITCH {
> char notename = 'a' + $1.t.a;
> int enshift = $1.t.b;
> $$.user_string = $1.user_string;
> $$.n.enshift = enshift;
> $$.n.mid_c_offset = pitchtomid_c_offset (notename, 0);
> }
> | NOTENAME_PITCH sup_quotes {
> char notename = 'a' + $1.t.a;
> int enshift = $1.t.b;
> int sups=$2.i;
> $$.user_string = g_strconcat($1.user_string, $2.user_string,
> NULL);
> $$.n.enshift = enshift;
> $$.n.mid_c_offset = pitchtomid_c_offset (notename, sups);
> }
> | NOTENAME_PITCH sub_quotes {
> char notename = 'a' + $1.t.a;
> int enshift = $1.t.b;
> int subs = -$2.i;
> $$.user_string = g_strconcat($1.user_string, $2.user_string,
> NULL);
> $$.n.enshift = enshift;
> $$.n.mid_c_offset = pitchtomid_c_offset (notename, subs);
> }
> ;
>
> /*
> ugh. duplication
> */
>
> steno_tonic_pitch:
> TONICNAME_PITCH {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $1;
> #endif
> }
> | TONICNAME_PITCH sup_quotes {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Pitch p = *unsmob_pitch ($1);
> p.octave_ += $2;
> $$ = p.smobbed_copy ();
> #endif
> }
> | TONICNAME_PITCH sub_quotes {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Pitch p =* unsmob_pitch ($1);
>
> p.octave_ += -$2;
> $$ = p.smobbed_copy ();
>
> #endif
> }
> ;
>
> pitch:
> steno_pitch {
> $$ = $1;
> }
> | explicit_pitch {
> $$ = $1;
> }
> ;
>
> explicit_pitch:
> PITCH embedded_scm {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $2;
> if (!unsmob_pitch ($2)) {
> THIS->parser_error (_f ("Expecting musical-pitch
> value", 3));
> $$ = Pitch ().smobbed_copy ();
> }
> #endif
> }
> ;
>
> verbose_duration:
> DURATION embedded_scm {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $2;
> if (!unsmob_duration ($2))
> {
> THIS->parser_error (_ ("Must have duration object"));
> $$ = Duration ().smobbed_copy ();
> }
> #endif
> }
> ;
>
> extender_req:
> EXTENDER {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> if (!THIS->lexer_->lyric_state_b ())
> THIS->parser_error (_ ("Have to be in Lyric mode for
> lyrics"));
> $$ = new Extender_req;
> #endif
> }
> ;
>
> hyphen_req:
> HYPHEN {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> if (!THIS->lexer_->lyric_state_b ())
> THIS->parser_error (_ ("Have to be in Lyric mode for
> lyrics"));
> $$ = new Hyphen_req;
> #endif
> }
> ;
>
> direction_less_event:
> direction_less_char {
> $$ = $1;
> }
> | DYNAMICMARK {
> MALLOC_NODE(n, $1);
> ((nodegstr*)n)->gstr = $1.gstr;
> $$ = g_list_append(NULL, n);
> }
> | TONEOPTION {
> MALLOC_NODE(n, $1);
> ((nodegstr*)n)->gstr = $1.gstr;
> $$ = g_list_append(NULL, n);
> }
> | tremolo_type {
> LATER_MESSAGE(@$.first_line);
> }
> ;
>
> direction_less_char:
> '(' {
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);
> }
> | ')' {
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);
> }
> | '~' { /* tie */
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);
> }
> | E_SMALLER {
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);
> }
> | E_BIGGER {
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);
> }
> | E_EXCLAMATION {
> MALLOC_NODE(n, $1)
> $$ = g_list_append(NULL, n);
> }
> | E_OPEN {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Span_req* s= new Span_req;
> $$ = s;
> s->set_mus_property ("span-type", scm_makfrom0str (
> "phrasing-slur"));
> s->set_spot (THIS->here_input());
> #endif
> }
> ;
>
> full_markup:
> MARKUP {
> LATER_MESSAGE(@$.first_line);
> }
> ;
> gen_text_def:
> full_markup {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Music *t = MY_MAKE_MUSIC ("TextScriptEvent");
> t->set_property ("text", $1);
> t->set_spot (@$);
> $$ = t;
> #endif
> }
> /* JAN
> DYNAMICMARK {
> MALLOC_NODE(n, $1);
> ((nodegstr*)n)->gstr = $1.gstr;
> $$ = g_list_append(NULL, n);
> }
> */
> | string {
> MALLOC_NODE(n, $1);
> ((nodegstr*)n)->gstr = $1.gstr;
> $$ = g_list_append(NULL, n);
> }
> | DIGIT {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> String ds = to_string ($1);
> Text_script_req* t = new Text_script_req;
> SCM finger = ly_symbol2scm ("finger");
> t->set_mus_property ("text", scm_makfrom0str (ds.to_str0 ()));
> t->set_mus_property ("text-type" , finger);
> t->set_spot (THIS->here_input ());
> $$ = t;
> #endif
> }
> ;
>
> script_abbreviation:
> '^' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_makfrom0str ("Hat");
> #endif
> }
> | '+' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_makfrom0str ("Plus");
> #endif
> }
> | '-' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_makfrom0str ("Dash");
> #endif
> }
> | '|' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_makfrom0str ("Bar");
> #endif
> }
> | '>' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_makfrom0str ("Larger");
> #endif
> }
> | '.' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_makfrom0str ("Dot");
> #endif
> }
> | '_' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_makfrom0str ("Underscore");
> #endif
> }
> ;
>
> script_dir:
> '_' { /* $$ = DOWN; */ }
> | '^' { /* $$ = UP; */ }
> | '-' { /* $$ = CENTER; */ }
> ;
>
>
> absolute_pitch:
> steno_pitch {
> $$ = $1;
> }
> ;
>
> duration_length:
> multiplied_duration {
> $$ = $1;
> }
> | verbose_duration {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $1;
> #endif
> }
> ;
>
> optional_notemode_duration:
> {
> $$ = default_duration_;
> }
> | multiplied_duration {
> $$ = $1;
> default_duration_.t1.a = $1.t1.a;
> default_duration_.t1.b = $1.t1.b;
> }
> | verbose_duration {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $1;
> THIS->default_duration_ = *unsmob_duration ($$);
> #endif
> }
> ;
>
> steno_duration:
> bare_unsigned dots {
> int l = 0;
> if (!is_duration_b ($1.i))
> lyerror ("value not a duration");/* $1.i */
> else
> l = intlog2 ($1.i);
>
> if($2.i) $$.user_string = g_strconcat($1.user_string,
> $2.user_string, NULL);
> $$.t1.a = l;
> $$.t1.b =$2.i;
> }
> | DURATION_IDENTIFIER dots {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Duration *d =unsmob_duration ($1);
> Duration k (d->duration_log (),d->dot_count () + $2);
> $$ = k.smobbed_copy ();
> #endif
> }
> ;
>
>
>
>
> multiplied_duration:
> steno_duration { /* note 4 integers are used for these */
> $1.t2.a = 1;
> $1.t2.b = 1;
> $$ = $1;
> }
> | multiplied_duration '*' bare_unsigned {/* note 4 integers are used
> for these */
> stradd($1,$2);
> stradd($1,$3);
> $1.t2.a *= $3.i;
> $$ = $1;
>
> #ifdef LATER
> $$ = unsmob_duration ($$)->compressed ( $3) .smobbed_copy ();
> #endif
> }
> | multiplied_duration '*' FRACTION {/* note 4 integers are used for
> these */
> stradd($1,$2);
> stradd($1,$3);
> $1.t2.a *= $3.t.a; /* numerator of fraction */
> $1.t2.b = $3.t.b; /* denominator of fraction */
> $$ = $1;
>
> #ifdef LATER
> Rational m (gh_scm2int (ly_car ($3)), gh_scm2int (ly_cdr
> ($3)));
>
> $$ = unsmob_duration ($$)->compressed (m).smobbed_copy ();
> #endif
> }
> ;
>
> fraction:
> FRACTION { $$ = $1; }
> | UNSIGNED '/' UNSIGNED {
>
> $$.user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, NULL);
> $$.t.a = $1.i;
> $$.t.b = $3.i;
> }
> ;
>
> dots:
> /* empty */ { $$.i = 0; }
> | dots '.' {
> if($1.i == 0){
> $$.i = 1;
> $$.user_string = $2.user_string;
> } else {
> $$.user_string = g_strconcat($1.user_string,
> $2.user_string, NULL);/* FIXME memory leak $2*/
>
> $$.i = $1.i+1;
> }
> }
> ;
>
> tremolo_type:
> ':' {
> $$.i = 0;
> }
> | ':' bare_unsigned {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> if (!is_duration_b ($2))
> THIS->parser_error (_f ("not a duration: %d", $2));
> $$ = $2;
> #endif
> }
> ;
>
>
> bass_number:
> DIGIT
> | UNSIGNED { $$ = $1;}
> ;
>
> bass_mod:
> '-' { $$.i = -1; }
> | '+' { $$.i = 1; }
> | '!' { $$.i = 0; }
> ;
>
> bass_figure:
> FIGURE_SPACE {
> $$ = $1;
> }
> | bass_number {
> $$.user_string = $1.user_string;
> }
> | bass_figure bass_mod {
> $$.user_string = g_strconcat($1.user_string, $2.user_string,
> NULL);
> }
> ;
>
> br_bass_figure:
> '[' bass_figure {
> $$ = $1;
> }
> | bass_figure {
>
> $$ = $1;
>
> }
> | br_bass_figure ']' {
> $$ = $1;
> }
> ;
>
> figure_list:
> /**/ {
>
> $$.user_string = g_strdup("");
>
> }
> | figure_list br_bass_figure {
> $$.user_string = g_strconcat($1.user_string, $2.user_string,
> NULL);
> }
> ;
>
> figure_spec:
> FIGURE_OPEN figure_list FIGURE_CLOSE {
> $$.user_string = g_strconcat($1.user_string, $2.user_string,
> $3.user_string, NULL);
> }
> ;
>
>
> optional_rest:
> /* empty */ { $$.i = 0; }
> | REST { $$.i = 1; }
> ;
>
> ;
>
> simple_element:
> pitch exclamations questions octave_check optional_notemode_duration
> optional_rest {
> /* pitch is a node* with union a denemo note,
> exclamations and questions are nodei,
> optional_notemode_duration is now a node4i,
> but I don't know how to calculate with
> the multiplier fraction in the top two ints,
> optional rest is boolean for the \rest keyword
> appearing after a note - it turns it into a rest
> the duration is on the chord structure,
> the pitch on the note structure.
> print
> *(note*)(((DenemoObject*)(((GList*)(((staff*)si->thescore->data)->measures->data))->data))->u.chordval.notes.data)
> */
> DenemoObject *mud = newchord( $5.t1.a, $5.t1.b, 0);
>
> if (!note_state_b ())
> lyerror (_ ("Have to be in Note mode for notes"));
> if ($6.i)
> /* this is a rest vertically placed at the note
> no special representation in denemo yet */;
> else {
> addtone( mud, $1.n.mid_c_offset, $1.n.enshift,
> 0);/*FIXME should be
> using $1.n directly */
>
> #define no ((note*)((((chord *)mud->object)->notes)->data))
> if ($3.i % 2) {
> no->showaccidental = TRUE;
> ((chord *)mud->object)->hasanacc = TRUE;
> }
> if ($2.i % 2 ) {
> no->showaccidental = TRUE;
> ((chord *)mud->object)->hasanacc = TRUE;
> }
> #undef no
> }
> mud->user_string = $1.user_string;
> if ($2.i) stradd ( (*mud),$2);
> if ($3.i) stradd ( (*mud),$3);
> stradd ( (*mud),$5);
> if ($6.i) stradd ( (*mud),$6); /* FIXME memory leaks on strings
> concatenated */
>
> $$ = g_list_append (NULL,mud);
> }
> | RESTNAME optional_notemode_duration {
> /* denemo wants a chord with no notes */
> DenemoObject *mud = newchord( $2.t1.a, $2.t1.b,0);
>
> mud->user_string = g_strconcat($1.user_string, $2.user_string, NULL);
> $$ = g_list_append(NULL,mud);
> }
> | SKIPNAME optional_notemode_duration {
> /* denemo wants a chord with no notes */
> DenemoObject *mud = newchord( $2.t1.a, $2.t1.b,0);
> mud->type = SKIPNAME;
> mud->user_string = g_strconcat($1.user_string, $2.user_string, NULL);
> $$ = g_list_append(NULL,mud);
> }
> | MULTI_MEASURE_REST optional_notemode_duration {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Input i = THIS->pop_spot ();
>
> Skip_req * sk = new Skip_req;
> sk->set_mus_property ("duration", $2);
> Span_req *sp1 = new Span_req;
> Span_req *sp2 = new Span_req;
> sp1-> set_span_dir ( START);
> sp2-> set_span_dir ( STOP);
> SCM r = scm_makfrom0str ("rest");
> sp1->set_mus_property ("span-type", r);
> sp2->set_mus_property ("span-type", r);
>
> Request_chord * rqc1 = new Request_chord (SCM_EOL);
> rqc1->set_mus_property ("elements", scm_list_n (sp1,
> SCM_UNDEFINED));
> Request_chord * rqc2 = new Request_chord (SCM_EOL);
> rqc2->set_mus_property ("elements", scm_list_n (sk,
> SCM_UNDEFINED));
> Request_chord * rqc3 = new Request_chord (SCM_EOL);
> rqc3->set_mus_property ("elements", scm_list_n (sp2,
> SCM_UNDEFINED));
>
> SCM ms = scm_list_n (rqc1, rqc2, rqc3, SCM_UNDEFINED);
>
> $$ = new Sequential_music (SCM_EOL);
> $$->set_mus_property ("elements", ms);
> #endif
> }
> | STRING_ optional_notemode_duration {
> DenemoObject *mud = newlyric($2.t1.a, $2.t1.b, $1.gstr->str);
> mud->user_string = $1.user_string;
> mud->type = LYRICS;
> stradd((*mud),$2);
> $$ = g_list_append(NULL,mud);
> }
> | chord {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Input i = THIS->pop_spot ();
>
> if (!THIS->lexer_->chord_state_b ())
> THIS->parser_error (_ ("Have to be in Chord mode for
> chords"));
> $$ = $1;
> #endif
> }
> ;
>
> simul_open: DOUBLE_ANGLE_OPEN
> ;
>
> simul_close: DOUBLE_ANGLE_CLOSE
> ;
>
>
> chord:
> steno_tonic_pitch optional_notemode_duration chord_additions
> chord_subtractions chord_inversion chord_bass {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = Chord::get_chord ($1, $3, $4, $5, $6, $2);
> $$->set_spot (THIS->here_input ());
> #endif
> };
>
> chord_additions:
> {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = SCM_EOL;
> #endif
> }
> | CHORD_COLON chord_notes {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $2;
> #endif
> }
> ;
>
> chord_notes:
> chord_step {
> $$ = $1;
> }
> | chord_notes '.' chord_step {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_append2 ($$, $3);
> #endif
> }
> ;
>
> chord_subtractions:
> {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = SCM_EOL;
> #endif
> }
> | CHORD_CARET chord_notes {
> $$ = $2;
> }
> ;
>
>
> chord_inversion:
> {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = SCM_EOL;
> #endif
> }
> | '/' steno_tonic_pitch {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $2;
> #endif
> }
> ;
>
> chord_bass:
> {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = SCM_EOL;
> #endif
> }
> | CHORD_BASS steno_tonic_pitch {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $2;
> #endif
> }
> ;
>
> chord_step:
> chord_note {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_cons ($1, SCM_EOL);
> #endif
> }
> | CHORDMODIFIER_PITCH {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_cons (unsmob_pitch ($1)->smobbed_copy (), SCM_EOL);
> #endif
> }
> | CHORDMODIFIER_PITCH chord_note {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> /* Ugh. */
> $$ = scm_list_n (unsmob_pitch ($1)->smobbed_copy (),
> $2, SCM_UNDEFINED);
> #endif
> }
> ;
>
> chord_note:
> bare_unsigned {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Pitch m;
> m.notename_ = ($1 - 1) % 7;
> m.octave_ = $1 > 7 ? 1 : 0;
> m.alteration_ = 0;
>
> $$ = m.smobbed_copy ();
> #endif
> }
> | bare_unsigned '+' {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Pitch m;
> m.notename_ = ($1 - 1) % 7;
> m.octave_ = $1 > 7 ? 1 : 0;
> m.alteration_ = 1;
>
>
> $$ = m.smobbed_copy ();
> #endif
> }
> | bare_unsigned CHORD_MINUS {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> Pitch m;
> m.notename_ = ($1 - 1) % 7;
> m.octave_ = $1 > 7 ? 1 : 0;
> m.alteration_ = -1;
>
> $$ = m.smobbed_copy ();
> #endif
> }
> ;
>
> /*
> UTILITIES
> */
> number_expression:
> number_expression '+' number_term {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_sum ($1, $3);
> #endif
> }
> | number_expression '-' number_term {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_difference ($1, $3);
> #endif
> }
> | number_term
> ;
>
> number_term:
> number_factor {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $1;
> #endif
> }
> | number_factor '*' number_factor {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_product ($1, $3);
> #endif
> }
> | number_factor '/' number_factor {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_divide ($1, $3);
> #endif
> }
> ;
>
> number_factor:
> '(' number_expression ')' {
> $$ = $2;
> }
> | '-' number_factor { /* %prec UNARY_MINUS */
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_difference ($2, SCM_UNDEFINED);
> #endif
> }
> | bare_number
> ;
>
>
> bare_number:
> UNSIGNED {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_int2scm ($1);
> #endif
> }
> | REAL {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $1;
> #endif
> }
> | NUMBER_IDENTIFIER {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $1;
> #endif
> }
> | REAL CM_T {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_double2scm (gh_scm2double ($1) CM );
> #endif
> }
> | REAL PT_T {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_double2scm (gh_scm2double ($1) PT);
> #endif
> }
> | REAL IN_T {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_double2scm (gh_scm2double ($1) INCH);
> #endif
> }
> | REAL MM_T {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_double2scm (gh_scm2double ($1) MM);
> #endif
> }
> | REAL CHAR_T {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = gh_double2scm (gh_scm2double ($1) CHAR);
> #endif
> }
> ;
>
>
> bare_unsigned:
> UNSIGNED {
> $$ = $1;
> }
> | DIGIT {
> $$ = $1;
> }
> ;
>
> bare_int:
> bare_number {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> if (scm_integer_p ($1) == SCM_BOOL_T)
> {
> int k = gh_scm2int ($1);
> $$ = k;
> } else
> {
> THIS->parser_error (_ ("need integer number arg"));
> $$ = 0;
> }
> #endif
> }
> | '-' bare_int {
> $$.i = -$2.i;
> }
> ;
>
>
> string:
> STRING_ {
> $$ = $1;
> }
> | STRING_IDENTIFIER {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = $1;
> #endif
> }
> | string '+' string {
> LATER_MESSAGE(@$.first_line);
> #ifdef LATER
> $$ = scm_string_append (scm_list_n ($1, $3, SCM_UNDEFINED));
> #endif
> }
> ;
>
>
> exclamations:
> /* empty */ { $$.i = 0; }
> | exclamations '!' {
> if($1.i == 0){
> $$.i = 1;
> $$.user_string = $2.user_string;
> } else {
> $$.user_string = g_strconcat($1.user_string,
> $2.user_string, NULL);/* FIXME memory leak $2*/
>
> $$.i = $1.i+1;
> }
> }
> ;
>
> questions:
> /* empty */ { $$.i = 0; }
> | questions '?' {
> if($1.i == 0){
> $$.i = 1;
> $$.user_string = $2.user_string;
> } else {
> $$.user_string = g_strconcat($1.user_string,
> $2.user_string, NULL);/* FIXME memory leak $2*/
>
> $$.i = $1.i+1;
> }
> }
> ;
>
>
> %%
>
> #if GTK_MAJOR_VERSION <= 1
> #define gtk_window_present(a)
> #endif
>
>
> static objnode *
> use_up_ticks (objnode * h, gint ticks)
> {
> DenemoObject *figmud = (DenemoObject *) h->data;
> while (ticks > 0)
> {
> h = h->next;
> figmud = h ? (DenemoObject *) h->data : NULL;
> if (!figmud)
> {
> g_warning ("Insufficient figures for bass part");
> return NULL;
> }
> ticks -= figmud->basic_durinticks;
> }
> return h;
> }
>
> static gboolean
> create_figures (GList * b, GList * f)
> {
> objnode *h = (objnode *) f->data;
> DenemoObject *figmud;
>
> for (figmud = (DenemoObject *) h->data; figmud;
> h = h->next, figmud = h ? (DenemoObject *) h->data : NULL)
> {
> if (figmud->type == CHORD)
> return FALSE; /* there are already figures present */
> }
>
>
> for (; b && b->data; b = b->next)
> {
> objnode *g = (objnode *) b->data;
> DenemoObject *mud;
> for (mud = (DenemoObject *) g->data; mud;
> g = g->next, mud = (g ? (DenemoObject *) g->data : NULL))
> {
> if (mud->type == CHORD)
> {
>
> }
>
> if (mud->type == TUPOPEN || mud->type == TUPCLOSE
> || mud->type == GRACE_START || mud->type == GRACE_END)
> {
> DenemoObject *figmud =
> (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
> memcpy (figmud, mud, sizeof (DenemoObject));
> f->data = g_list_append ((GList *) f->data, figmud);
> }
> }
> f = (f->next ? f->next : g_list_append (f, NULL));
> }
>
> return TRUE;
> }
>
> /* return next objnode of CHORD (is_figure will be true for h) type */
> static objnode *
> next_figure (objnode * h)
> {
> DenemoObject *figmud;
> for (figmud = (DenemoObject *) h->data; figmud;
> h = h->next, figmud = h ? (DenemoObject *) h->data : NULL)
> {
> if (figmud->type == CHORD)
> return h;
> }
> g_assert (h == NULL);
> return NULL;
> }
>
> /* Link each chord in BASS to a figure (CHORD) or sequence of them in
> FIGURES; create blank figures for each note present in BASS if none is
> present in
> FIGURES, abort if incomplete figures present */
> static void
> fill_in_figures (DenemoStaff * bass, DenemoStaff * figures)
> {
> GList *b = bass->measures, *f = figures->measures;
> /* if there are no figures create a set cloning the durations from bass */
> if (create_figures (b, f))
> return;
>
> for (b = bass->measures, f = figures->measures;
> b && b->data; b = b->next, f = f->next)
> {
> objnode *g = (objnode *) b->data;
> objnode *h = (objnode *) f->data;
> DenemoObject *mud;
> for (mud = (DenemoObject *) g->data; mud;
> g = g->next, mud = (g ? (DenemoObject *) g->data : NULL))
> {
>
> if (mud->type == CHORD)
> {
> if (h)
> {
> /* set figure of bass chord to the first CHORD (ie figure)
> * object in the FIGURES list starting at h.
> * Then move h on over other CHORDs (ie figures) if needed to
> * use up the duration of the mud->object.
> * If the list h has run out, abort since we don't know how
> * much is missing or why
> */
> h = (objnode *) (((chord *) mud->object)->figure);
> (((chord *) mud->object)->figure) = next_figure (h);
> if (h)
> h =
> use_up_ticks (h,
> mud->basic_durinticks -
> ((DenemoObject *) h->data)->
> basic_durinticks);
> } /* if h */
>
> if (((chord *) mud->object)->figure == NULL) /* not yet
> fixed up this CHORD in BASS */
> {
> lyerror
> ("Figures are incomplete for Bass - delete the figures or
> complete them!");
> }
> h = h ? h->next : NULL;
> } /* if mud is CHORD */
> } /* end of for each DenemoObject in the measure
> */
> } /* for each measure */
> }
>
> /* create the list of measurewidths for si, add measures to short staffs and
> run set_initial_staffcontexts() to setup the clef etc in the staff
> structures
> Fill in any figured bass staff that is short of figures with blank figures.
> */
> static void
> fixup_measure_widths_and_contexts (DenemoScore * si)
> {
> GList *g = si->thescore;
> DenemoStaff *curstaffstruct = staffstruct (g);
> int i, num_measures = 0;
> /* find num_measures of longest staff */
> for (g = si->thescore; g; g = g->next)
> {
> curstaffstruct = staffstruct (g);
> i = g_list_length (curstaffstruct->measures);
> if (num_measures < i)
> num_measures = i;
> }
> /* add measures to short staffs */
> for (g = si->thescore; g; g = g->next)
> {
> curstaffstruct = staffstruct (g);
> i = g_list_length (curstaffstruct->measures);
> while ((num_measures - i++) > 0)
> curstaffstruct->measures =
> g_list_append (curstaffstruct->measures, NULL);
> }
> /* if(g_list_length(si->measurewidths)) lyerror("si->measurewidths should
> be zero at this point");*/
> g = si->thescore;
> curstaffstruct = staffstruct (g);
> i = g_list_length (curstaffstruct->measures);
> while (i--)
> si->measurewidths =
> g_list_append (si->measurewidths, GINT_TO_POINTER (si->measurewidth));
> if (si->has_figures)
> fill_in_figures (si->has_figures->main_staff,
> si->has_figures->related_staff);
> set_initial_staffcontexts (si);
> find_leftmost_allcontexts (si);
> }
>
>
> /* these scheme identifiers are difficult to track down in lilypond's source
> tree: \major and \minor in particular I haven't found. There are a group in
> lilypond/ly/script-init.ly, and clearly the file being parsed could define
> additional ones, in general we just need to recognize them and pass on the
> user_string, except where denemo has been equipped to represent them
> graphically.
> In this last case we store a token to be returned as the lyval->type, the only
> case where this is not the same as the token the lexer returns.
> */
>
> static void
> insert_scm (int type, gchar * str)
> {
> nodegstr *n = (nodegstr *) g_malloc0 (sizeof (nodegstr));
> n->type = type;
> n->gstr = g_string_new (str);
> g_hash_table_insert (scm_identifiers, (gpointer) str, (gpointer) n);
> }
>
>
> static void
> initialize_scm_identifiers (void)
> {
> if (scm_identifiers)
> return;
> scm_identifiers = g_hash_table_new (g_str_hash, g_str_equal);
> insert_scm (MUSICMODE, "major");
> insert_scm (MUSICMODE, "minor");
>
> insert_scm (TONEOPTION, "thumb");
> insert_scm (TONEOPTION, "accent");
> insert_scm (TONEOPTION, "marcato");
> insert_scm (TONEOPTION, "staccatissimo");
> insert_scm (TONEOPTION, "portato");
> insert_scm (TONEOPTION, "fermata");
> insert_scm (TONEOPTION, "stopped");
> insert_scm (TONEOPTION, "staccato");
> insert_scm (TONEOPTION, "tenuto");
> insert_scm (TONEOPTION, "upbow");
> insert_scm (TONEOPTION, "downbow");
> insert_scm (TONEOPTION, "lheel");
> insert_scm (TONEOPTION, "rheel");
> insert_scm (TONEOPTION, "ltoe");
> insert_scm (TONEOPTION, "rtoe");
> insert_scm (TONEOPTION, "turn");
> insert_scm (TONEOPTION, "open");
> insert_scm (TONEOPTION, "flageolet");
> insert_scm (TONEOPTION, "reverseturn");
> insert_scm (TONEOPTION, "trill");
> insert_scm (TONEOPTION, "prall");
> insert_scm (TONEOPTION, "mordent");
> insert_scm (TONEOPTION, "upmordent");
> insert_scm (TONEOPTION, "downmordent");
> insert_scm (TONEOPTION, "prallprall");
> insert_scm (TONEOPTION, "prallup");
> insert_scm (TONEOPTION, "pralldown");
> insert_scm (TONEOPTION, "lineprall");
> insert_scm (TONEOPTION, "prallmordent");
> insert_scm (TONEOPTION, "upprall");
> insert_scm (TONEOPTION, "downprall");
> insert_scm (TONEOPTION, "segno");
> insert_scm (TONEOPTION, "coda");
>
>
>
> insert_scm (DYNAMICMARK, "ppp");
> insert_scm (DYNAMICMARK, "pp");
> insert_scm (DYNAMICMARK, "p");
> insert_scm (DYNAMICMARK, "mp");
> insert_scm (DYNAMICMARK, "mf");
> insert_scm (DYNAMICMARK, "f");
> insert_scm (DYNAMICMARK, "ff");
> insert_scm (DYNAMICMARK, "fff");
> insert_scm (DYNAMICMARK, "fff");
> insert_scm (DYNAMICMARK, "fp");
> insert_scm (DYNAMICMARK, "sf");
> insert_scm (DYNAMICMARK, "sff");
> insert_scm (DYNAMICMARK, "sp");
> insert_scm (DYNAMICMARK, "spp");
> insert_scm (DYNAMICMARK, "sfz");
> insert_scm (DYNAMICMARK, "rfz");
>
> insert_scm (DYNAMICMARK, "cr");
> insert_scm (DYNAMICMARK, "rc");
>
> insert_scm (DYNAMICMARK, "decr");
> insert_scm (DYNAMICMARK, "rced");
>
>
>
> }
>
>
> /* set parser_error_linenum
> set parser_error_message, linenum .
> if EDITOR environment variable not set
> show a dialog giving TEXT and and offering to exit application
> or return (for editing the whole file in gui). */
>
> void
> parser_error (gchar * text, int line_number)
> {
>
> GtkWidget *label;
> GtkWidget *editbutton;
> GtkWidget *exitbutton;
> if( (parser_error_message == NULL) ) {
> parser_error_message = strdup(text);
> parser_error_linenum = line_number;
> }
>
> if (!getenv ("EDITOR"))
> {
> if (!parser_error_dialog)
> {
> /*warningdialog("Unable to load this file - quitting");*/
> return(-1);
> }
> }
> else
> {
> g_print ("\nAssociated message: %s at line %d\n", text, line_number);
>
> }
>
> }
>
>
>
> /* called by lexer at EOF */
> void set_trailing_white_space (gchar *trailing) {
> trailing_white_space = g_strdup (trailing);
> }
>
> static void attach_trailing_white_space (GList *top) {
> GList *g = g_list_last (top);
> u_str(g) = g_strconcat(u_str(g), trailing_white_space,NULL);
> g_free(trailing_white_space);
> trailing_white_space = NULL;
> }
>
> char *
> header_str(char *key)
> {
> nodeglist *x;
> char *pt = NULL;
> int n;
>
> x = (nodeglist *) g_hash_table_lookup (name_value_pairs, key);
> if (x)
> {
> pt = u_str(x->branch);
> if (*pt == '"') pt++;
> n = strlen(pt) - 1;
> if (*(pt+n) == '"') *(pt+n) = 0;
> }
> return(pt);
> }
> static void
> score_prop_from_lily (DenemoGUI *gui)
> {
> DenemoScore *si = gui->si;
> char *pt;
> GList *scm;
>
> if ((pt = header_str("midi_tempo")))
> {
> si->tempo = atoi(pt);
> }
> if ((pt = header_str("lilyversion")))
> {
> gui->lilycontrol.lilyversion = g_string_new(pt);
> }
> if (findtok (lily_file, HEADER))
> {
> if ((pt = header_str ("title")))
> g_string_assign (si->headerinfo.title, pt);
> if ((pt = header_str ("subtitle")))
> g_string_assign (si->headerinfo.subtitle, pt);
> if ((pt = header_str ("poet")))
> g_string_assign (si->headerinfo.poet, pt);
> if ((pt = header_str ("composer")))
> g_string_assign (si->headerinfo.composer, pt);
> if ((pt = header_str ("meter")))
> g_string_assign (si->headerinfo.meter, pt);
> if ((pt = header_str ("opus")))
> g_string_assign (si->headerinfo.opus, pt);
> if ((pt = header_str ("arranger")))
> g_string_assign (si->headerinfo.arranger, pt);
> if ((pt = header_str ("instrument")))
> g_string_assign (si->headerinfo.instrument, pt);
> if ((pt = header_str ("dedication")))
> g_string_assign (si->headerinfo.dedication, pt);
> if ((pt = header_str ("piece")))
> g_string_assign (si->headerinfo.piece, pt);
> if ((pt = header_str ("head")))
> g_string_assign (si->headerinfo.head, pt);
> if ((pt = header_str ("copyright")))
> g_string_assign (si->headerinfo.copyright, pt);
> if ((pt = header_str ("footer")))
> g_string_assign (si->headerinfo.footer, pt);
> if ((pt = header_str ("tagline")))
> g_string_assign (si->headerinfo.tagline, pt);
> }
> for(scm = findtok (lily_file, SCM_T); scm ; scm = scm->next)
> {
> if ((pt = strstr (u_str (scm), "set-global-staff-size")))
> {
> int font;
> if (sscanf (pt+21, " %d", &font) == 1)
> {
> gui->lilycontrol.fontsize = font;
> }
> else
> g_warning("%s no font", pt);
> }
> if ((pt = strstr (u_str (scm), "set-default-paper-size")))
> {
> char *tmp;
> char *pt2 = strchr(pt, '\"');
> if (pt2)
> {
> tmp = g_strdup(pt2+1);
> pt2 = strchr(tmp, '\"');
> if (pt2)
> {
> *pt2 = 0;
> // g_print ("Paper size %s\n", tmp);
> g_string_assign (gui->lilycontrol.papersize, tmp);
> *tmp = 0;
> g_free (tmp);
> }
> }
> if (!pt2)
> g_warning("%s paper size error", pt);
> }
> }
> }
>
>
> /* from denemo's easylyparser.y
> note that this function generates a list
> of DenemoScore structures (one for each \score{} block
> in the lilypond file, returning the current one (as set in
> si->theFile->current_scoreblock). This rather clumsy
> arrangement is historical from when si was the root data
> structure: see denemo.h
> */
> int
> lyinput (gchar * filename, DenemoGUI *gui)
> {
> FILE *lyin;
> GList *score_block_list = NULL;
> initialize_scm_identifiers ();
> name_value_pairs = g_hash_table_new (g_str_hash, g_str_equal);/* FIXME
> memory leak */
> default_duration_.t1.a = 2;
> default_duration_.t1.b = 0;
>
> init_crescendo_state();
> DenemoScore *si = gui->si;
>
> while (1)
> { /* keep trying to open the file */
> if ((lyin = fopen (filename, "r")) == NULL)
> {
> fprintf (stderr, "Cannot open the file: %s\n", filename);
> return -1;
> }
> else
> { /* file is opened */
> /* any old lily parse tree (ie si->lily_file) is already demolished */
> lily_file = NULL;
> parser_error_dialog = NULL;
> parser_error_message = NULL;
> /* free_score (si); CHANGE THIS TO FREE ALL THE si in
> si->thefile->currentDenemoScore list... */
>
>
> // Calling init_score here would cause piece in header to set to
> "Movement 2"
> si->measurewidths = NULL;
> si->thescore = NULL;
>
>
> /* in case we are re-entering via reload after error */
> lyrestart (lyin);
>
> lylineno = 1; /* not done by lexer for some reason */
> push_note_state ();
>
> while (!feof (lyin))
> {
> lyparse ();
> if (parser_error_message) {
> fprintf(stderr,"%s\n", parser_error_message);
> warningdialog("Unable to cope with this file");
> return -1;
> }
> }
> if (parser_error_message == NULL)
> {
> GList *score = findtok (lily_file, SCORE);
> if (score)
> {
> if (create_score_from_lily (si, br (score)) == 0)
> {
> GList *top;
> nodemin *n = (nodemin *) g_malloc0 (sizeof (nodemin));
> score_prop_from_lily(gui);
>
> while (score && score->next)
> {
> score = findtok (score->next, SCORE);
> if (score)
> {
> DenemoScore *nextsi =
> (DenemoScore *) g_malloc0 (sizeof (DenemoScore));
> init_score (nextsi, gui);
> create_score_from_lily (nextsi, br (score));
> score_block_list =
> g_list_append (score_block_list, nextsi);
> }
> }
>
> n->type = TEXT;
> /* must be g_free-able pointer */
> n->user_string = g_strdup ("");
> top = g_list_append (NULL, n);
> /* simplify the tree into TEXT and DENEMO_MEASURES nodes */
> #ifdef LILYEDIT
> lily_write_out (top, lily_file, TO_NODE);
> #endif
> attach_trailing_white_space (top);
> si->lily_file = top;
> si->lily_file = NULL; // stop lilypond file edit
> restrictions- RRR
> fixup_measure_widths_and_contexts (si);
> #ifdef LILYEDIT
> /* write out the text to editable display */
> create_text_display (gui);
> #if GTK_MAJOR_VERSION > 1
> /* so that the following toggle starts the scorearea display */
> gtk_widget_hide (si->scorearea);
> toggle_top_node (NULL, gui);
> /* present denemo's graphical window first */
> gtk_window_present ((GtkWindow *) gui->window);
> #endif
>
> if (g_list_length (score_block_list) > 0)
> {
> GList *g;
> DenemoScore *nextsi;
> for (g = score_block_list; g; g = g->next)
> {
> nextsi = (DenemoScore *) g->data;
> fixup_measure_widths_and_contexts (nextsi);
> nextsi->window = si->window;
> nextsi->scorearea = si->scorearea;
> nextsi->pixmap = si->pixmap;
> nextsi->vadjustment = si->vadjustment;
> nextsi->vscrollbar = si->vscrollbar;
> nextsi->hadjustment = si->hadjustment;
> nextsi->hscrollbar = si->hscrollbar;
> nextsi->menubar = si->menubar;
> nextsi->textbuffer = si->textbuffer;
> nextsi->textwindow = si->textwindow;
> nextsi->textview = si->textview;
> nextsi->musicdatabutton = si->musicdatabutton;
> nextsi->sigid = si->sigid;
> nextsi->curlilynode = si->curlilynode;
> nextsi->lily_file = si->lily_file;
> nextsi->prefs = si->prefs;
> /* certain fields are not really score specific - they are file specific -
> share these */
>
>
> /* but we have no way of sharing has_changed yet FIXmME */
>
> }
>
> /* append a copy of the score block si (the one that
> the display is hardwired to)
> to the list of score_blocks, so that the display can
> be cycled around by copying
> from score_block_list to si */
> nextsi = (DenemoScore *) g_malloc0 (sizeof
> (DenemoScore));
> memcpy (nextsi, si, sizeof (DenemoScore));
> score_block_list =
> g_list_append (score_block_list, nextsi);
> si->scoreblocks = score_block_list;
> }
>
> #endif // LILYEDIT
>
>
> return 0;
> }
> } /* if successful lily parse */
> else
> {
> fprintf(stderr, "Parse Error Line %d: %s\n",
> parser_error_linenum, parser_error_message);
> return(1);
> }
> }
>
> }
> reset_initial_lexer_state ();
> g_assert (lily_file);
> #ifdef LILYEDIT
> if (!getenv ("EDITOR"))
> {
> long len;
> gchar *filecontents;
> fseek (lyin, 0L, SEEK_END);
> len = ftell (lyin);
> filecontents = (gchar *) g_malloc (len + 1); /* +1 for NULL
> terminator */
> rewind (lyin);
> fread (filecontents, len, 1, lyin);
> *(filecontents + len) = '\0';
> fclose (lyin);
> u_str (lily_file) = filecontents;
> lily_file->next = NULL;
> si->lily_file = lily_file;
> si->curlilynode = lily_file;
> if (si->textwindow)
> lily_text_change (si);
> else
> create_text_display (si);
> gui->filename = g_string_new (filename);
> gtk_widget_set_sensitive (si->textview, TRUE);
> gtk_widget_set_sensitive (si->scorearea, FALSE);
>
> /* put dialog on top - it would be nice to use gtk_dialog_run() but
> how do you use it? */
> if (parser_error_dialog)
> gtk_window_present ((GtkWindow *) parser_error_dialog);
> return -1;
> }
> else
> { /* use external editor */
> GString *cmd;
> int ret;
> fclose (lyin);
> cmd = g_string_new (getenv ("EDITOR"));
> g_string_append_printf (cmd, " +%d %s", parser_error_linenum,
> filename);
> g_warning
> ("Using environment variable $EDITOR calling system with %s\n",
> cmd->str);
> ret = system (cmd->str);
> #if 0
> if (WIFIGNALED (ret) &&
> (WTERMSIG (ret) == SIGINT || WTERMSIG (ret) == SIGQUIT))
> break;
> #endif
> if (ret)
> break;
> }
> #endif //LILYEDIT
> lyerror ("File load failed\n");
> return -1;
> } /* forever */
> lyerror ("File load failed\n");
> return -1; /* there is no handler for this yet - never has
> been! */
> }
> #ifdef YYPRINT
>
> static gchar *
> type_name(gint type)
> {
> gint i;
> for(i=0; yytoknum[i] != type; i++)
> {
> if (i > YYNTOKENS)
> return("");
> }
> return yytname[i];
> }
>
> #endif