]> git.donarmstrong.com Git - lilypond.git/blob - lily/lily-lexer.cc
release commit
[lilypond.git] / lily / lily-lexer.cc
1 /*
2   lily-lexer.cc -- implement Lily_lexer
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include <ctype.h>
10 #include <sstream>
11
12 #include "lily-proto.hh"
13 #include "scm-hash.hh"
14 #include "interval.hh"
15 #include "lily-guile.hh"
16 #include "parser.hh"
17 #include "keyword.hh"
18 #include "lily-lexer.hh"
19 #include "warn.hh"
20 #include "source-file.hh"
21 #include "main.hh"
22 #include "input.hh"
23 #include "moment.hh"
24 #include "ly-module.hh"
25
26
27 static Keyword_ent the_key_tab[] = {
28   {"accepts", ACCEPTS},
29   {"addquote", ADDQUOTE},
30   {"addlyrics", ADDLYRICS},
31   {"alias", ALIAS},
32   {"alternative", ALTERNATIVE},
33   {"bar", BAR},
34   {"book", BOOK},
35   {"bookpaper", BOOKPAPER},
36   {"change", CHANGE},
37   {"chords", CHORDS},
38   {"chordmode", CHORDMODE},
39   {"clef", CLEF},
40   {"consists", CONSISTS},
41   {"context", CONTEXT},
42   {"default", DEFAULT},
43   {"denies", DENIES},
44   {"drummode", DRUMMODE},
45   {"drums", DRUMS},
46   {"description", DESCRIPTION},
47   {"figures",FIGURES},
48   {"figuremode",FIGUREMODE},
49   {"grobdescriptions", GROBDESCRIPTIONS},
50   {"header", HEADER},
51   {"key", KEY},
52   {"lyricmode", LYRICMODE},
53   {"lyricsto", LYRICSTO},
54   {"lyrics", LYRICS},
55   {"mark", MARK},
56   {"markup", MARKUP},
57   {"midi", MIDI},
58   {"name", NAME},
59   {"new", NEWCONTEXT},
60   {"notemode", NOTEMODE},
61   {"octave", OCTAVE},
62   {"once", ONCE},
63   {"override", OVERRIDE},
64   {"paper", PAPER},
65   {"partial", PARTIAL},
66   {"quote", QUOTE},
67   {"relative", RELATIVE},
68   {"remove", REMOVE},
69   {"repeat", REPEAT},
70   {"rest", REST},
71   {"revert", REVERT},
72   {"score", SCORE},
73   {"sequential", SEQUENTIAL},
74   {"set", SET},
75   {"simultaneous", SIMULTANEOUS},
76   {"skip", SKIP},
77   {"tag", TAG},
78   {"tempo", TEMPO},
79   {"time", TIME_T},
80   {"times", TIMES},
81   {"transpose", TRANSPOSE},
82   {"transposition", TRANSPOSITION},
83   {"type", TYPE},
84   {"unset", UNSET},
85   {"with", WITH},
86   {0, 0}
87 };
88
89
90 Lily_lexer::Lily_lexer (Sources *sources)
91 {
92   keytable_ = new Keyword_table (the_key_tab);
93   encoding_ = SCM_EOL;
94   chordmodifier_tab_ = SCM_EOL;
95   pitchname_tab_stack_ = SCM_EOL; 
96   sources_ = sources;
97   scopes_ = SCM_EOL;
98   error_level_ = 0; 
99   main_input_b_ = false;
100
101   smobify_self ();
102   
103   add_scope (ly_make_anonymous_module (false));
104   push_note_state (scm_c_make_hash_table (0));
105   chordmodifier_tab_ = scm_make_vector (scm_int2num (1), SCM_EOL);
106 }
107
108 Lily_lexer::Lily_lexer (Lily_lexer const &src)
109   : Includable_lexer ()
110 {
111   keytable_ = (src.keytable_) ? new Keyword_table (*src.keytable_) : 0;
112   encoding_ = src.encoding_;
113   chordmodifier_tab_ = src.chordmodifier_tab_;
114   pitchname_tab_stack_ = src.pitchname_tab_stack_;
115   sources_ = src.sources_;
116   
117   error_level_ = src.error_level_; 
118   main_input_b_ = src.main_input_b_;
119
120   scopes_ = SCM_EOL;
121   
122   smobify_self ();
123   
124   SCM scopes = SCM_EOL;
125   SCM *tail = &scopes;
126   for (SCM s = src.scopes_; scm_is_pair (s); s = ly_cdr (s))
127     {
128       SCM newmod = ly_make_anonymous_module (false);
129       ly_import_module (newmod, ly_car (s));
130       *tail = scm_cons (newmod, SCM_EOL);
131       tail = SCM_CDRLOC (*tail);
132     }
133   
134   scopes_ =  scopes;
135   push_note_state (scm_c_make_hash_table (0));
136 }
137
138 Lily_lexer::~Lily_lexer ()
139 {
140   delete keytable_;
141 }
142
143 SCM
144 Lily_lexer::encoding () const
145 {
146   return encoding_ ;
147 }
148
149
150 void
151 Lily_lexer::add_scope (SCM module)
152 {
153   ly_reexport_module (scm_current_module ());
154   scm_set_current_module (module);
155   for (SCM s = scopes_; scm_is_pair (s); s = ly_cdr (s))
156     {
157       ly_use_module (module, ly_car (s));
158     }
159   scopes_ = scm_cons (module, scopes_);
160 }
161
162 SCM
163 Lily_lexer::remove_scope ()
164 {
165   SCM sc = ly_car (scopes_);
166   scopes_ = ly_cdr (scopes_);
167   scm_set_current_module (ly_car (scopes_));
168
169   return sc;
170 }
171
172
173 int
174 Lily_lexer::lookup_keyword (String s)
175 {
176   return keytable_->lookup (s.to_str0 ());
177 }
178
179 SCM
180 Lily_lexer::lookup_identifier_symbol (SCM sym)
181 {
182   for (SCM s = scopes_; scm_is_pair (s); s = ly_cdr (s))
183     {
184       SCM var = ly_module_lookup (ly_car (s), sym);
185       if (var != SCM_BOOL_F)
186         return scm_variable_ref (var);
187     }
188
189   return SCM_UNDEFINED;
190 }
191
192 SCM
193 Lily_lexer::lookup_identifier (String name)
194 {
195   return lookup_identifier_symbol (ly_symbol2scm (name.to_str0 ()));
196 }
197
198 void
199 Lily_lexer::start_main_input ()
200 {
201   // yy_flex_debug = 1;
202   new_input (main_input_name_, sources_);
203   
204   /* Do not allow \include in --safe-mode */
205   allow_includes_b_ = allow_includes_b_ && !safe_global_b;
206
207   scm_module_define (ly_car (scopes_),
208                      ly_symbol2scm ("input-file-name"),
209                      scm_makfrom0str (main_input_name_.to_str0 ()));
210 }
211
212 void
213 Lily_lexer::set_identifier (SCM name, SCM s)
214 {
215   SCM sym = name;
216   if (scm_is_string (name))
217     sym =  scm_string_to_symbol (name);
218   
219   if (scm_is_symbol (sym))
220     {
221       if (lookup_keyword (ly_symbol2string (sym)) >= 0)
222         {
223           String symstr = ly_symbol2string (sym); 
224           warning (_f ("Identifier name is a keyword: `%s'", symstr.to_str0()));
225         }
226
227       SCM mod = ly_car (scopes_);
228
229       scm_module_define (mod, sym, s);
230     }
231   else
232     {
233       programming_error ("Identifier is not a symbol.");
234     }
235 }
236
237 void
238 Lily_lexer::LexerError (char const *s)
239 {
240   if (include_stack_.is_empty ())
241     progress_indication (_f ("error at EOF: %s", s) + String ("\n"));
242   else
243     {
244       error_level_ |= 1;
245       Input spot (get_source_file (), here_str0 ());
246       spot.error (s);
247     }
248 }
249
250 char
251 Lily_lexer::escaped_char (char c) const
252 {
253   switch (c)
254     {
255     case 'n':
256       return '\n';
257     case 't':
258       return '\t';
259     case '\'':
260     case '\"':
261     case '\\':
262       return c;
263     }
264   return 0;
265 }
266
267 Input
268 Lily_lexer::here_input () const
269 {
270   Source_file * f= get_source_file ();
271   return Input (f, (char*)here_str0 ());
272 }
273
274 void
275 Lily_lexer::prepare_for_next_token ()
276 {
277   last_input_ = here_input ();
278 }
279
280 void
281 Lily_lexer::set_encoding (String s)
282 {
283   if (s.length ())
284     encoding_ = ly_symbol2scm (s.to_str0 ());
285   else
286     encoding_ = SCM_EOL;
287 }
288
289 #include "ly-smobs.icc"
290
291 IMPLEMENT_SMOBS (Lily_lexer);
292 IMPLEMENT_TYPE_P (Lily_lexer, "ly:lily-lexer?");
293 IMPLEMENT_DEFAULT_EQUAL_P (Lily_lexer);
294
295 SCM
296 Lily_lexer::mark_smob (SCM s)
297 {
298   Lily_lexer *lexer = (Lily_lexer*) ly_cdr (s);
299
300   scm_gc_mark (lexer->chordmodifier_tab_);
301   scm_gc_mark (lexer->pitchname_tab_stack_);
302   scm_gc_mark (lexer->scopes_);
303   return lexer->encoding_;
304 }
305
306 int
307 Lily_lexer::print_smob (SCM, SCM port, scm_print_state*)
308 {
309   scm_puts ("#<Lily_lexer ", port);
310   scm_puts (" >", port);
311   return 1;
312 }