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