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