]> git.donarmstrong.com Git - lilypond.git/blob - lily/lexer.l
72ab455a2633b1f156f3e5b8f39532f9655e638c
[lilypond.git] / lily / lexer.l
1 %{ // -*-Fundamental-*-
2 /*
3   lexer.l -- implement the Flex lexer
4
5   source file of the LilyPond music typesetter
6
7   (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
8 */
9
10
11 /*
12   backup rules
13
14   after making a change to the lexer rules, run 
15       flex -b <this lexer file>
16   and make sure that 
17       lex.backup
18   contains no backup states, but only the reminder
19       Compressed tables always back up.
20   (don-t forget to rm lex.yy.cc :-)
21  */
22
23
24 #include <stdio.h>
25
26 #include "string.hh"
27 #include "string-convert.hh"
28 #include "my-lily-lexer.hh"
29 #include "varray.hh"
30 #include "parser.hh"
31 #include "debug.hh"
32 #include "input-score.hh"
33 #include "parseconstruct.hh"
34 #include "main.hh"
35 #include "identifier.hh"
36
37 #define start_quote()   \
38         yy_push_state(quote);\
39         yylval.string = new String
40
41 #define yylval (*(YYSTYPE*)lexval_l)
42
43 #define YY_USER_ACTION  add_lexed_char(YYLeng());
44 %}
45
46 %option c++
47 %option noyywrap
48 %option nodefault
49 %option debug
50 %option yyclass="My_lily_lexer"
51 %option stack
52 %option never-interactive 
53 %option warn
54
55 %x incl
56 %x lyrics
57 %x notes
58 %x quote
59 %x longcomment
60
61
62 A               [a-zA-Z]
63 AA              {A}|_
64 N               [0-9]
65 AN              {AA}|{N}
66 PUNCT           [?!,.:;']
67 ACCENT          \\[`'"^]
68 NATIONAL        [\241-\377]
69 TEX             {AA}|-|{PUNCT}|{ACCENT}|{NATIONAL}
70
71 WORD            {A}{AN}*
72 ALPHAWORD       {A}+
73 INT             -?{N}+
74 REAL            {INT}?(\.{N}+)?
75 KEYWORD         \\{WORD}
76 WHITE           [ \n\t\f]
77 BLACK           [^ \n\t\f]
78 RESTNAME        [rs]
79 NOTECOMMAND     \\{A}+
80 DOTS            \.+
81 LYRICS          ({AA}|{NATIONAL})[^0-9 \t\n\f]*
82
83 %%
84
85
86 <notes,incl,INITIAL,lyrics>{
87   "%{"  {
88         yy_push_state(longcomment);
89   }
90   %[^{\n].*\n   {
91   }
92   %[^{\n]       { // backup rule
93   }
94   %\n   {
95   }
96   %[^{\n].*     {
97   }
98   {WHITE}+      {
99         
100   }
101 }
102
103 <longcomment>{
104         [^\%]*          {
105         }
106         \%*[^}%]*               {
107
108         }
109         "%"+"}"         {
110                 yy_pop_state();
111         }
112 }
113 <longcomment><<EOF>> {
114         LexerError("EOF found inside a comment");
115         if (! close_input()) { 
116           yyterminate(); // can't move this, since it actually rets a YY_NULL
117         }
118 }
119 <notes,INITIAL,lyrics>
120 \\include           {
121         yy_push_state(incl);
122 }
123 <incl>\"[^"]*\"   { /* got the include file name */
124         String s (YYText()+1);
125         s = s.left_str(s.length_i()-1);
126         mtor << "#include `" << s << "\'\n";
127         new_input(s,source_l_g);
128         yy_pop_state();
129 }
130 <incl>\"[^"]*   { // backup rule
131         cerr << "missing end quote" << endl;
132         exit( 1 );
133 }
134 <notes>{RESTNAME}       {
135         const char *s = YYText();
136         yylval.string = new String (s); 
137         mtor << "rest:"<< yylval.string;
138         return RESTNAME;
139 }
140 <INITIAL,lyrics,notes>\\\${BLACK}*{WHITE}       {
141         String s=YYText() + 2;
142         s=s.left_str(s.length_i() - 1);
143         return scan_escaped_word(s);
144 }
145 <INITIAL,lyrics,notes>\${BLACK}*{WHITE}         {
146         String s=YYText() + 1;
147         s=s.left_str(s.length_i() - 1);
148         return scan_bare_word(s);
149 }
150 <INITIAL,lyrics,notes>\\\${BLACK}*              { // backup rule
151         cerr << "white expected" << endl;
152         exit( 1 );
153 }
154 <INITIAL,lyrics,notes>\${BLACK}*                { // backup rule
155         cerr << "white expected" << endl;
156         exit( 1 );
157 }
158 <notes>{
159         {ALPHAWORD}/\'  {
160                 post_quotes_b_ = true;
161                 return scan_bare_word(YYText());
162         }
163         \'+             {
164                 yylval.i = YYLeng();
165                 if (post_quotes_b_) {
166                         post_quotes_b_ = false;
167                         return POST_QUOTES;
168                 } else
169                         return PRE_QUOTES;
170         }
171         {ALPHAWORD}     {
172                 return scan_bare_word(YYText());
173
174         }
175
176         {NOTECOMMAND}   {
177                 return scan_escaped_word(YYText()+1);
178         }
179
180         {DOTS}          {
181                 yylval.i = strlen(YYText());
182                 return DOTS;
183         }
184         {INT}           {
185                 yylval.i = String_convert::dec2_i( String( YYText() ) );
186                 return INT;
187         }
188
189         \+\+            {
190                 return CONCAT;
191         }
192         \" {
193                 start_quote();
194         }
195 }
196
197 \"              {
198         start_quote();
199 }
200 <quote>{
201         \\\\    {
202                 *yylval.string += '\\';
203         }
204         \\\"    {
205                 *yylval.string +='\"';
206         }
207         [^"]+   {
208                 *yylval.string += YYText();
209         }
210         \"      {
211                 mtor << "quoted string: `" << *yylval.string << "'\n";
212                 yy_pop_state();
213                 return STRING;
214         }
215 }
216
217 <lyrics>{
218
219         \" {
220                 start_quote();
221         }
222         {DOTS}          {
223                 yylval.i = strlen(YYText());
224                 return DOTS;
225         }
226         {INT}           {
227                 yylval.i = String_convert::dec2_i( String( YYText() ) );
228                 return INT;
229         }
230         {NOTECOMMAND}   {
231                 return scan_escaped_word(YYText()+1);
232         }
233         {LYRICS} {
234                 /* ugr. This sux. */
235                 String s (YYText()); 
236                 int i = 0;
237                 while ((i=s.index_i("_")) != -1) // change word binding "_" to " "
238                         *(s.ch_l() + i) = ' ';
239                 if ((i=s.index_i("\\,")) != -1)   // change "\," to TeX's "\c "
240                         {
241                         *(s.ch_l() + i + 1) = 'c';
242                         s = s.left_str(i+2) + " " + s.right_str(s.length_i()-i-2);
243                         }
244                 yylval.string = new String(s);
245                 mtor << "lyric : `" << s << "'\n";
246                 return STRING;
247         }
248         . {
249                 return yylval.c = YYText()[0];
250         }
251 }
252
253 <<EOF>> {
254         mtor << "<<eof>>";
255
256         if (! close_input()) { 
257           yyterminate(); // can't move this, since it actually rets a YY_NULL
258         }
259 }
260 {WORD}  {
261         return scan_bare_word(YYText());
262 }
263 {KEYWORD}       {
264         return scan_escaped_word(YYText()+1);
265 }
266 {REAL}          {
267         Real r;
268         int cnv=sscanf (YYText(), "%lf", &r);
269         assert(cnv == 1);
270         mtor  << "REAL" << r<<'\n';
271         yylval.real = r;
272         return REAL;
273 }
274
275 {INT}\. { // backup rule
276         cerr << "int. encountered" << endl;
277         exit( 1 );
278 }
279
280 [{}]    {
281
282         mtor << "parens\n";
283         return YYText()[0];
284 }
285 [*:=]           {
286         char c = YYText()[0];
287         mtor << "misc char" <<c<<"\n";
288         return c;
289 }
290
291 <INITIAL,notes>.        {
292         return yylval.c = YYText()[0];
293 }
294
295 <INITIAL,lyrics,notes>\\. {
296     char c= YYText()[1];
297     yylval.c = c;
298     switch (c) {
299     case '>':
300         return E_BIGGER;
301     case '<':
302         return E_SMALLER;
303     case '!':
304         return E_EXCLAMATION;
305     default:
306         return E_CHAR;
307     }
308 }
309
310 <*>.            {
311         LexerError( String( "illegal character: " ) +String( YYText()[0] ));
312         return YYText()[0];
313 }
314
315 %%
316
317 void
318 My_lily_lexer::push_note_state()
319 {
320         yy_push_state(notes);
321 }
322
323 void
324 My_lily_lexer::push_lyric_state()
325 {
326         yy_push_state(lyrics);
327 }
328 void
329 My_lily_lexer::pop_state()
330 {
331         yy_pop_state();
332 }
333
334 int
335 My_lily_lexer::scan_escaped_word(String str)
336 {       
337         mtor << "\\word: `" << str<<"'\n";
338         int l = lookup_keyword(str);
339         if (l != -1) {
340                 mtor << "(keyword)\n";
341                 return l;
342         }
343         Identifier * id = lookup_identifier(str);
344         if (id) {
345                 mtor << "(identifier)\n";
346                 yylval.id = id;
347                 return id->token_code_i_;
348         }
349         mtor << "(string)";
350         String *sp = new String( str);
351         yylval.string=sp;
352         return STRING;
353 }
354
355 int
356 My_lily_lexer::scan_bare_word(String str)
357 {
358         mtor << "word: `" << str<< "'\n";       
359         if (YYSTATE == notes){
360                 Melodic_req * mel_l = lookup_melodic_req_l(str);
361                 if (mel_l) {
362                     mtor << "(notename)\n";
363                     yylval.melreq = mel_l;
364                     return NOTENAME_ID;
365                 }
366         }
367         if (YYSTATE != notes) {
368                 // ugr. Should do this in note mode?
369                 Identifier * id = lookup_identifier(str);
370                 if (id) {
371                         mtor << "(identifier)\n";
372                         yylval.id = id;
373                         return id->token_code_i_;
374                 }
375         }
376         yylval.string=new String( str );
377         return STRING;
378 }
379
380 bool
381 My_lily_lexer::note_state_b() const
382 {
383         return YY_START == notes;
384 }
385
386 bool
387 My_lily_lexer::lyric_state_b() const
388 {
389         return YY_START == lyrics;
390 }