2 my-lily-parser.cc -- implement My_lily_parser
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 Jan Nieuwenhuizen <janneke@gnu.org>
10 #include "file-path.hh"
11 #include "lily-version.hh"
12 #include "ly-module.hh"
13 #include "ly-module.hh"
16 #include "my-lily-lexer.hh"
17 #include "my-lily-parser.hh"
18 #include "my-lily-parser.hh"
19 #include "paper-def.hh"
22 #include "scm-hash.hh"
23 #include "scm-hash.hh"
30 My_lily_parser::My_lily_parser (Sources * sources)
36 default_duration_ = Duration (2,0);
38 last_beam_start_ = SCM_EOL;
40 header_ = ly_make_anonymous_module ();
43 My_lily_parser::~My_lily_parser ()
48 /* Process one .ly file, or book. */
50 My_lily_parser::parse_file (String init, String in_file, String out_file)
52 lexer_ = new My_lily_lexer (sources_);
53 output_basename_ = out_file;
55 lexer_->main_input_name_ = in_file;
57 progress_indication (_ ("Parsing..."));
58 progress_indication ("\n");
61 lexer_->new_input (init, sources_);
63 /* Read .ly IN_FILE, lex, parse, write \score blocks from IN_FILE to
64 OUT_FILE (unless IN_FILE redefines output file name). */
67 if (!define_spots_.is_empty ())
69 define_spots_.top ().warning (_ ("Braces don't match"));
73 // fixme: dependencies
74 //input_file_->inclusion_names_ = lexer_->filename_strings_;
76 error_level_ = error_level_ | lexer_->errorlevel_; // ugh naming.
80 My_lily_parser::push_spot ()
82 define_spots_.push (here_input ());
86 My_lily_parser::here_str0 () const
88 return lexer_->here_str0 ();
92 My_lily_parser::parser_error (String s)
94 here_input ().error (s);
101 My_lily_parser::pop_spot ()
103 return define_spots_.pop ();
107 My_lily_parser::here_input () const
110 Parsing looks ahead , so we really want the previous location of the
111 lexer, not lexer_->here_input ().
114 Actually, that gets very icky when there are white space, because
115 the line-numbers are all wrong. Let's try the character before
116 the current token. That gets the right result for
117 note/duration stuff, but doesn't mess up for errors in the 1st token of the line.
120 Input hi (lexer_->here_input ());
122 char const * bla = hi.defined_str0_;
123 if (hi.line_number () > 1
124 || hi.column_number () > 1)
127 return Input (hi.source_file_, bla);
131 /****************************************************************/
137 bool store_locations_global_b;
140 no ! suffix since it doesn't modify 1st argument.
142 LY_DEFINE (ly_set_point_and_click, "ly:set-point-and-click", 1, 0, 0,
144 "Set the options for Point-and-click source specials output. The\n"
145 "argument is a symbol. Possible options are @code{none} (no source specials),\n"
146 "@code{line} and @code{line-column}")
151 SCM val = SCM_BOOL_F;
152 if (ly_symbol2scm ("line-column") == what)
153 val = scm_c_eval_string ("line-column-location");
154 else if (what == ly_symbol2scm ("line"))
155 val = scm_c_eval_string ("line-location");
157 scm_module_define (global_lily_module, ly_symbol2scm ("point-and-click"), val);
158 store_locations_global_b = is_procedure (val);
159 return SCM_UNSPECIFIED;
163 /* Distill full input file name from command argument. PATH describes
164 file name with added default extension, ".ly" if none. "-" is
167 distill_inname (String str)
169 Path p = split_path (str);
170 if (str.is_empty () || str == "-")
174 String orig_ext = p.ext;
175 char const *extensions[] = {"ly", "", 0};
176 for (int i = 0; extensions[i]; i++)
179 if (*extensions[i] && !p.ext.is_empty ())
181 p.ext += extensions[i];
182 if (!global_path.find (p.to_string ()).is_empty ())
185 /* Reshuffle extension */
186 p = split_path (p.to_string ());
191 LY_DEFINE(ly_parse_file, "ly:parse-file",
194 "Parse a single @code{.ly} file. If this fails, then throw @code{ly-file-failed} key. "
197 SCM_ASSERT_TYPE (is_string (name), name, SCM_ARG1, __FUNCTION__, "string");
198 char const *file = SCM_STRING_CHARS(name);
200 String infile (file);
201 Path inpath = distill_inname (infile);
203 /* By default, use base name of input file for output file name */
204 Path outpath = inpath;
205 if (inpath.to_string () != "-")
206 outpath.ext = output_format_global;
208 /* By default, write output to cwd; do not copy directory part
209 of input file name */
213 if (!output_name_global.is_empty ())
214 outpath = split_path (output_name_global);
217 if (!init_name_global.is_empty ())
218 init = init_name_global;
222 String in_file = inpath.to_string ();
223 String out_file = outpath.to_string ();
226 if (init.length () && global_path.find (init).is_empty ())
228 warning (_f ("can't find init file: `%s'", init));
229 warning (_f ("(search path: `%s')", global_path.to_string ().to_str0 ()));
233 if ((in_file != "-") && global_path.find (in_file).is_empty ())
235 warning (_f ("can't find file: `%s'", in_file));
236 scm_throw (ly_symbol2scm ("ly-file-failed"), scm_list_1 (scm_makfrom0str (in_file.to_str0 ())));
241 sources.set_path (&global_path);
243 progress_indication (_f ("Now processing `%s'", in_file.to_str0 ()));
244 progress_indication ("\n");
246 My_lily_parser parser (&sources);
247 parser.parse_file (init, in_file, out_file);
249 if (parser.error_level_)
252 TODO: pass renamed input file too.
254 scm_throw (ly_symbol2scm ("ly-file-failed"), scm_list_1 (scm_makfrom0str (in_file.to_str0 ())));
257 return SCM_UNSPECIFIED;