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