From eec794f5b0c2906066d7dd76d5961a01b03e8f70 Mon Sep 17 00:00:00 2001
From: janneke <janneke>
Date: Sun, 18 Apr 2004 08:23:45 +0000
Subject: [PATCH] * lily/lexer.ll: * lily/parser.yy: In lyrics mode, return
 LYRICS_STRING.  Use notes mode at start of maininput.  Grok toplevel
 composite music expression, put in score and book.

---
 ChangeLog                      |   7 ++
 Documentation/user/GNUmakefile |   6 +-
 lily/includable-lexer.cc       |  10 +--
 lily/include/my-lily-lexer.hh  |   5 +-
 lily/lexer.ll                  |  78 ++++++++++++++----
 lily/parser.yy                 | 143 ++++++++++++++++++++++++++-------
 6 files changed, 195 insertions(+), 54 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 404639174c..aafb8041ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-04-18  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* lily/lexer.ll:
+	* lily/parser.yy: In lyrics mode, return LYRICS_STRING.  Use notes
+	mode at start of maininput.  Grok toplevel composite music
+	expression, put in score and book.
+
 2004-04-16  Han-Wen Nienhuys   <hanwen@xs4all.nl>
 
 	* lily/parser.yy: rename NEWADDLYRICS to LYRICSTO. Thanks to Erik
diff --git a/Documentation/user/GNUmakefile b/Documentation/user/GNUmakefile
index 0b818d9638..27b5e6d53b 100644
--- a/Documentation/user/GNUmakefile
+++ b/Documentation/user/GNUmakefile
@@ -188,5 +188,9 @@ endif
 local-clean: local-delete
 
 local-delete:
-	-rm -f $(outdir)/lily-1*
+	-for i in $$(seq 0 9); do \
+		for j in dvi eps eps.bbox eps.trans log png tex; do \
+			rm -f $(outdir)/lily-$$i*$$j; \
+		done; \
+	done
 	-rm -f $(outdir)/*
diff --git a/lily/includable-lexer.cc b/lily/includable-lexer.cc
index 0d420616aa..587eefbba1 100644
--- a/lily/includable-lexer.cc
+++ b/lily/includable-lexer.cc
@@ -105,7 +105,8 @@ Includable_lexer::new_input (String name, String data, Sources* sources)
 }
 
 /** pop the inputstack.  conceptually this is a destructor, but it
-  does not destruct the Source_file that Includable_lexer::new_input creates.  */
+  does not destruct the Source_file that Includable_lexer::new_input
+  creates.  */
 bool
 Includable_lexer::close_input ()
 {
@@ -124,11 +125,8 @@ Includable_lexer::close_input ()
 #endif  
       return false;
     }
-  else
-    {
-      yy_switch_to_buffer (state_stack_.pop ());
-      return true;
-    }
+  yy_switch_to_buffer (state_stack_.pop ());
+  return true;
 }
 
 char const*
diff --git a/lily/include/my-lily-lexer.hh b/lily/include/my-lily-lexer.hh
index 008f26ae91..2c115c82da 100644
--- a/lily/include/my-lily-lexer.hh
+++ b/lily/include/my-lily-lexer.hh
@@ -59,11 +59,12 @@ public:
   void start_main_input ();
 
   SCM lookup_identifier (String s);
-  void push_note_state (SCM tab);
   void push_chord_state (SCM tab);
-  void push_markup_state ();
   void push_figuredbass_state ();
   void push_lyric_state ();
+  void push_initial_state ();
+  void push_markup_state ();
+  void push_note_state (SCM tab);
   void pop_state ();
   void LexerError (char const *);
   void set_encoding (String);
diff --git a/lily/lexer.ll b/lily/lexer.ll
index cbed6fcc56..e0c9b74c34 100644
--- a/lily/lexer.ll
+++ b/lily/lexer.ll
@@ -66,6 +66,10 @@ bool is_valid_version (String s);
 	yy_push_state (quote);\
 	yylval.string = new String
 
+#define start_lyric_quote()	\
+	yy_push_state (lyric_quote);\
+	yylval.string = new String
+
 #define yylval \
 	(*(YYSTYPE*)lexval)
 
@@ -93,17 +97,18 @@ SCM (* scm_parse_error_handler) (void *);
 %option never-interactive 
 %option warn
 
-%x encoding
-%x renameinput
-%x version
 %x chords
+%x encoding
+%x figures
 %x incl
 %x lyrics
-%x notes
-%x figures
-%x quote
+%x lyric_quote
 %x longcomment
 %x markup 
+%x notes
+%x quote
+%x renameinput
+%x version
 
 A		[a-zA-Z]
 AA		{A}|_
@@ -228,6 +233,8 @@ HYPHEN		--
 	{
 		start_main_input ();
 		main_input_b_ = true;
+		SCM nn = lookup_identifier ("pitchnames");
+		push_note_state (alist_to_hashq (nn));
 	}
 	else
 		error (_ ("\\maininput not allowed outside init files"));
@@ -237,6 +244,7 @@ HYPHEN		--
 	yy_push_state (incl);
 }
 <incl>\"[^"]*\";?   { /* got the include file name */
+/* FIXME: semicolon? */
 	String s (YYText ()+1);
 	s = s.left_string (s.index_last ('"'));
 
@@ -244,6 +252,7 @@ HYPHEN		--
 	yy_pop_state ();
 }
 <incl>\\{BLACK}*;?{WHITE} { /* got the include identifier */
+/* FIXME: semicolon? */
 	String s = YYText () + 1;
 	strip_trailing_white (s);
 	if (s.length () && (s[s.length () - 1] == ';'))
@@ -377,10 +386,31 @@ HYPHEN		--
 		*yylval.string += YYText ();
 	}
 }
+<lyric_quote>{
+	\\{ESCAPED}	{
+		*yylval.string += to_string (escaped_char (YYText ()[1]));
+	}
+	[^\\"]+	{
+		*yylval.string += YYText ();
+	}
+	\"	{
+
+		yy_pop_state ();
+
+		/* yylval is union. Must remember STRING before setting SCM*/
+		String *sp = yylval.string;
+		yylval.scm = scm_makfrom0str (sp->to_str0 ());
+		delete sp;
+		return LYRICS_STRING;
+	}
+	.	{
+		*yylval.string += YYText ();
+	}
+}
 
 <lyrics>{
 	\" {
-		start_quote ();
+		start_lyric_quote ();
 	}
 	{FRACTION}	{
 		yylval.scm =  scan_fraction (YYText ());
@@ -409,7 +439,7 @@ HYPHEN		--
 		yylval.scm = scm_makfrom0str (s.to_str0 ());
 
 
-		return STRING;
+		return LYRICS_STRING;
 	}
 	. {
 		return YYText ()[0];
@@ -519,10 +549,17 @@ HYPHEN		--
 }
 
 <<EOF>> {
-	main_input_b_ = false;
-	if (! close_input ()) { 
- 	  yyterminate (); // can't move this, since it actually rets a YY_NULL
+	if (main_input_b_)
+	{
+		main_input_b_ = false;
+		if (!close_input ())
+ 	        /* Returns YY_NULL */
+			yyterminate ();
+		return EOI;
 	}
+	else if (!close_input ())
+ 	        /* Returns YY_NULL */
+ 	  	yyterminate ();
 }
 
 
@@ -598,22 +635,22 @@ HYPHEN		--
 %%
 
 void
-My_lily_lexer::push_note_state (SCM tab)
+My_lily_lexer::push_chord_state (SCM tab)
 {
 	pitchname_tab_stack_ = scm_cons (tab, pitchname_tab_stack_);
-	yy_push_state (notes);
+	yy_push_state (chords);
 }
 
 void
-My_lily_lexer::push_figuredbass_state()
+My_lily_lexer::push_figuredbass_state ()
 {
 	yy_push_state (figures);
 }
+
 void
-My_lily_lexer::push_chord_state (SCM tab)
+My_lily_lexer::push_initial_state ()
 {
-	pitchname_tab_stack_ = scm_cons (tab, pitchname_tab_stack_);
-	yy_push_state (chords);
+	yy_push_state (INITIAL);
 }
 
 void
@@ -628,6 +665,13 @@ My_lily_lexer::push_markup_state ()
 	yy_push_state (markup);
 }
 
+void
+My_lily_lexer::push_note_state (SCM tab)
+{
+	pitchname_tab_stack_ = scm_cons (tab, pitchname_tab_stack_);
+	yy_push_state (notes);
+}
+
 void
 My_lily_lexer::pop_state ()
 {
diff --git a/lily/parser.yy b/lily/parser.yy
index e0f512186f..1382e8ae1b 100644
--- a/lily/parser.yy
+++ b/lily/parser.yy
@@ -259,6 +259,7 @@ or
 %token DEFAULT
 %token DENIES
 %token DESCRIPTION
+%token EOI
 %token EXTENDER
 %token FIGURES FIGURE_OPEN FIGURE_CLOSE
 %token FIGURE_BRACKET_CLOSE FIGURE_BRACKET_OPEN
@@ -271,6 +272,7 @@ or
 %token INVALID
 %token KEY
 %token LYRICS
+%token LYRICS_STRING
 %token MARK
 %token MIDI
 %token MULTI_MEASURE_REST
@@ -356,16 +358,19 @@ or
 %type <scm> markup markup_line markup_list  markup_list_body full_markup
 
 %type <outputdef> output_def
-%type <scm> 	lilypond_header lilypond_header_body
+%type <scm>	lilypond_header lilypond_header_body
 %type <music>	open_event close_event
 %type <i>	sub_quotes sup_quotes
-%type <music>	simple_element  event_chord command_element Simple_music  Composite_music
+%type <music>	toplevel_music
+%type <music>	simple_element event_chord command_element
+%type <music>	Composite_music Simple_music
 %type <music>	Repeated_music
 %type <scm>     Alternative_music
 %type <i>	tremolo_type
 %type <i>	bare_int  bare_unsigned
 %type <i>	script_dir
 %type <scm>	identifier_init
+%type <scm>	simple_string
 
 %type <music> note_chord_element chord_body chord_body_element
 %type <scm>  chord_body_elements
@@ -409,6 +414,7 @@ prec levels in different prods */
 %%
 
 lilypond:	/* empty */
+	| lilypond EOI
 	| lilypond toplevel_expression {}
 	| lilypond assignment  { }
 	| lilypond error {
@@ -423,7 +429,37 @@ toplevel_expression:
 	lilypond_header {
 		THIS->header_ = $1;
 	}
+	| toplevel_music EOI {
+		Score *score = new Score;
+		SCM s = $1->self_scm ();
+
+		/* URG? */
+		SCM check_funcs
+			= ly_scheme_function ("toplevel-music-functions");
+		for (; ly_c_pair_p (check_funcs);
+		       check_funcs = ly_cdr (check_funcs))
+			s = scm_call_1 (ly_car (check_funcs), s);
+		score->music_ = s;
+
+		Book *book = new Book;
+		book->scores_.push (score);
+
+ 		scm_gc_unprotect_object (score->self_scm ());
+		
+		SCM header = THIS->header_;
+		Path outname = split_path (THIS->output_basename_);
+		int *c = &THIS->book_count_;
+		if (*c)
+ 			outname.base += "-" + to_string (*c);
+		(*c)++;
+ 		Music_output_def *dp = unsmob_music_output_def
+			(THIS->lexer_->lookup_identifier ("$defaultpaper"));
+ 		book->process (outname.to_string (),
+			dp ? dp->clone () : new Paper_def, header);
+ 		scm_gc_unprotect_object (book->self_scm ());
+	}
 	| add_quote {
+	
 	}
 	| book_block {
 		Book *book = $1;
@@ -440,8 +476,10 @@ toplevel_expression:
  		scm_gc_unprotect_object (book->self_scm ());
 	}
 	| score_block {
-		Score *sc = $1;
-		SCM head = is_module (sc->header_) ? sc->header_
+	  	/* TODO: implicit book, depending on --no-book/--no-page-layout
+		   option? */
+		Score *score = $1;
+		SCM head = is_module (score->header_) ? score->header_
 			: THIS->header_.to_SCM ();
 
 		Path p = split_path (THIS->output_basename_);
@@ -452,21 +490,21 @@ toplevel_expression:
 		(*c)++;
 		SCM outname = scm_makfrom0str (p.to_string ().to_str0());
 
-		for (int i = 0; i < sc->defs_.size (); i++)
-			default_rendering (sc->music_,
-					   sc->defs_[i]->self_scm (), head,
+		for (int i = 0; i < score->defs_.size (); i++)
+			default_rendering (score->music_,
+					   score->defs_[i]->self_scm (), head,
 					   outname);
 
-		if (sc->defs_.is_empty ())
+		if (score->defs_.is_empty ())
 		{
 		   Music_output_def *id = unsmob_music_output_def
 			(THIS->lexer_->lookup_identifier ("$defaultpaper"));
 		   id = id ? id->clone () : new Paper_def;
-		   default_rendering (sc->music_, id->self_scm (), head,
+		   default_rendering (score->music_, id->self_scm (), head,
  			outname);
  		   scm_gc_unprotect_object (id->self_scm ());
 		}
- 		scm_gc_unprotect_object (sc->self_scm ());
+ 		scm_gc_unprotect_object (score->self_scm ());
 	}
 	| output_def {
 		SCM id = SCM_EOL;
@@ -479,6 +517,43 @@ toplevel_expression:
 	}
 	;
 
+/* FIXME: Experimental kludge for automatic relative music
+          This will change or go away.  */
+language: '@'
+	| '@' STRING {
+		/* FIXME? */
+		THIS->lexer_->push_initial_state ();
+		THIS->lexer_->new_input (ly_scm2string ($2) + ".ly",
+					 THIS->lexer_->sources_);
+		THIS->lexer_->pop_state ();
+	}
+	;
+
+toplevel_music:
+	Composite_music {
+	}
+	/* FIXME: Experimental kludge for automatic relative music
+	          This will change or go away.
+		  
+		  How to introduce: [\notes]\relative 'c { } in an
+		  implicit or otherwise intuitive way? */
+	| language Music_list {
+	  	SCM lst = $2;
+		Music *m = MY_MAKE_MUSIC ("SequentialMusic");
+		m->set_property ("elements", ly_car (lst));
+		m->set_spot (THIS->here_input ());
+		
+		Pitch middle_c;
+		$$ = MY_MAKE_MUSIC ("RelativeOctaveMusic");
+		$$->set_property ("element", m->self_scm ());
+
+		Pitch last = m->to_relative_octave (middle_c);
+		if (lily_1_8_relative)
+			$$->set_property ("last-pitch", last.smobbed_copy ());
+
+		scm_gc_unprotect_object (m->self_scm ());
+	}
+	;
 
 embedded_scm:
 	SCM_T
@@ -677,7 +752,8 @@ score_body:
 output_def:
 	music_output_def_body '}' {
 		$$ = $1;
-		THIS-> lexer_-> remove_scope ();
+		THIS->lexer_->remove_scope ();
+		THIS->lexer_->pop_state ();
 	}
 	;
 
@@ -713,7 +789,7 @@ music_output_def_body:
 	music_output_def_head '{' {
 		$$ = $1;
 		$$->input_origin_. set_spot (THIS->here_input ());
-		
+		THIS->lexer_->push_initial_state ();
 	}
 	| music_output_def_head '{' MUSIC_OUTPUT_DEF_IDENTIFIER 	{
 		scm_gc_unprotect_object ($1->self_scm ());
@@ -722,6 +798,7 @@ music_output_def_body:
 		$$ = o;
 		THIS->lexer_->remove_scope ();
 		THIS->lexer_->add_scope (o->scope_);
+		THIS->lexer_->push_initial_state ();
 	}
 	| music_output_def_body assignment  {
 
@@ -997,7 +1074,7 @@ basic music objects too, since the meaning is different.
 		$$ = context_spec_music ($2, $4, $6, $5);
 
 	}
-	| CONTEXT STRING optional_context_mod Music {
+	| CONTEXT simple_string optional_context_mod Music {
 		$$ = context_spec_music ($2, SCM_UNDEFINED, $4, $3);
 	}
 	| NEWCONTEXT string optional_context_mod Music {
@@ -1122,10 +1199,9 @@ relative_music:
 		$$->set_property ("element", p->self_scm ());
 		scm_gc_unprotect_object (p->self_scm ());
 
-
-		Pitch retpitch = p->to_relative_octave (pit);
+		Pitch last = p->to_relative_octave (pit);
 		if (lily_1_8_relative)
-			$$->set_property ("last-pitch", retpitch.smobbed_copy ());
+			$$->set_property ("last-pitch", last.smobbed_copy ());
 	}
 	;
 
@@ -1157,20 +1233,26 @@ context_change:
 	}
 	;
 
+simple_string: STRING {
+	   }
+	| LYRICS_STRING {
+	}
+	;
+
 property_operation:
-	STRING '='  scalar {
+	STRING '=' scalar {
 		$$ = scm_list_3 (ly_symbol2scm ("assign"),
 			scm_string_to_symbol ($1), $3);
 	}
-	| UNSET STRING {
+	| UNSET simple_string {
 		$$ = scm_list_2 (ly_symbol2scm ("unset"),
 			scm_string_to_symbol ($2));
 	}
-	| OVERRIDE STRING embedded_scm '=' embedded_scm {
+	| OVERRIDE simple_string embedded_scm '=' embedded_scm {
 		$$ = scm_list_4 (ly_symbol2scm ("push"),
 			scm_string_to_symbol ($2), $3, $5);
 	}
-	| REVERT STRING embedded_scm {
+	| REVERT simple_string embedded_scm {
 		$$ = scm_list_3 (ly_symbol2scm ("pop"),
 			scm_string_to_symbol ($2), $3);
 	}
@@ -1198,11 +1280,13 @@ context_mod:
 	;
 
 context_prop_spec:
-	STRING  {
-		$$ = scm_list_2 (ly_symbol2scm ("Bottom"), scm_string_to_symbol ($1));
+	simple_string {
+		$$ = scm_list_2 (ly_symbol2scm ("Bottom"),
+			scm_string_to_symbol ($1));
 	}
-	| STRING '.' STRING {
-		$$ = scm_list_2 (scm_string_to_symbol ($1), scm_string_to_symbol ($3));
+	| simple_string '.' simple_string {
+		$$ = scm_list_2 (scm_string_to_symbol ($1),
+			scm_string_to_symbol ($3));
 	}
 	;
 
@@ -2122,8 +2206,11 @@ simple_element:
 	;
 
 lyric_element:
-	full_markup { $$ = $1; }
-	| STRING { $$ = $1; }
+	/* FIXME: lyric flavoured markup would be better */
+	full_markup {
+	}
+	| LYRICS_STRING {
+	}
 	;
 
 new_chord:
@@ -2438,8 +2525,8 @@ My_lily_lexer::try_special_identifiers (SCM *destination, SCM sid)
 		*destination = unsmob_context_def (sid)->clone_scm ();
 		return CONTEXT_DEF_IDENTIFIER;
 	} else if (unsmob_score (sid)) {
-		Score *sc = new Score (*unsmob_score (sid));
-		*destination = sc->self_scm ();
+		Score *score = new Score (*unsmob_score (sid));
+		*destination = score->self_scm ();
 		return SCORE_IDENTIFIER;
 	} else if (Music *mus = unsmob_music (sid)) {
 		mus = mus->clone ();
-- 
2.39.5