]> git.donarmstrong.com Git - lilypond.git/blob - mi2mu/midi-lexer.l
release: 0.0.65
[lilypond.git] / mi2mu / midi-lexer.l
1 %{//-*-Fundamental-*-
2 // midi-lexer.l
3
4 /* 
5   yes, i know that midi is not really a (n evolving?) language,
6   and that using lex/yacc to parse midi is overkill, as well as
7   a grand example of misuse and asking for performance loss.
8
9   it is, however, quite robust, simple, and very easy to extend
10   incrementally.
11  */
12
13 /*
14   backup rules
15
16   after making a change to the lexer rules, run 
17       flex -b <this lexer file>
18   and make sure that 
19       lex.backup
20   contains no backup states, but only the reminder
21       Compressed tables always back up.
22   (don-t forget to rm lex.yy.cc :-)
23  */
24
25 #include "mi2mu.hh"
26 #include "midi-parser.hh"
27
28 #define YY_USER_ACTION char_count_ += YYLeng(); // ugh
29 %}
30
31 %option c++
32 %option noyywrap
33 %option nodefault
34 %option debug
35 %option yyclass="My_midi_lexer"
36 %option stack
37
38 %x data
39 %x event
40 %x i8
41 %x u8
42 %x int16
43 %x int32
44 %x meta_event
45 %x track
46
47 U8              [\x00-\xff]
48 I8              {U8}
49 INT16           {U8}{U8}
50 BACKUP_INT16_0  {U8}
51 INT32           {INT16}{INT16}
52 BACKUP_INT32_0  {U8}
53 BACKUP_INT32_1  {U8}{U8}
54 BACKUP_INT32_2  {INT16}{U8}
55 INT7_8UNSET     [\x00-\x7f]
56 INT7_8SET       [\x80-\xff]
57 VARINT          {INT7_8SET}{0,3}{INT7_8UNSET}
58 BACKUP_VARINT_0 {INT7_8SET}
59 BACKUP_VARINT_1 {INT7_8SET}{INT7_8SET}
60 BACKUP_VARINT_2 {INT7_8SET}{INT7_8SET}{INT7_8SET}
61
62 HEADER          MThd
63 TRACK           MTrk
64 BACKUP_TOP_0    MT
65 BACKUP_TOP_1    MTh
66 BACKUP_TOP_2    MTr
67
68 XRUNNING_STATUS [\x30-\x4f]
69 RUNNING_STATUS  [\x00-\x5f]
70 DATA_ENTRY      [\x60-\x79]
71 ALL_NOTES_OFF   [\x7a-\x7f]
72 NOTE_OFF        [\x80-\x8f]
73 NOTE_ON         [\x90-\x9f]
74 POLYPHONIC_AFTERTOUCH   [\xa0-\xaf]
75 CONTROLMODE_CHANGE      [\xb0-\xbf]
76 PROGRAM_CHANGE  [\xc0-\xcf]
77 CHANNEL_AFTERTOUCH      [\xd0-\xdf]
78 PITCHWHEEL_RANGE        [\xe0-\xef]
79
80 SYSEX_EVENT1    [\xf0]
81 SYSEX_EVENT2    [\xf7]
82
83 META_EVENT      [\xff]
84
85 SEQUENCE        [\x00][\x02]
86 YYTEXT          [\x01] 
87 YYCOPYRIGHT     [\x02]
88 YYTRACK_NAME    [\x03]
89 YYINSTRUMENT_NAME       [\x04]
90 YYLYRIC         [\x05]
91 YYMARKER                [\x06]
92 YYCUE_POINT     [\x07]
93
94 END_OF_TRACK    [\x2f][\x00]
95 TEMPO           [\x51][\x03]
96 SMPTE_OFFSET    [\x54][\x05]
97 TIME            [\x58][\x04]
98 KEY             [\x59][\x02]
99 SSME            [\0x7f][\x03]
100
101 %%
102
103 {HEADER} { // huh? using {HEADER}/{INT32}; longer match than {INT32}
104         tor( DEBUG_ver ) << "lex: header" << endl;
105         yy_push_state( int16 ); 
106         yy_push_state( int16 ); 
107         yy_push_state( int16 ); 
108         yy_push_state( int32 ); 
109         return HEADER;
110 }
111
112 {TRACK} { // huh? using {TRACK}/{INT32}; longer match than {INT32}
113         tor( DEBUG_ver ) << "lex: track" << endl;
114         yy_push_state( track ); 
115         yy_push_state( int32 ); 
116         return TRACK;
117 }
118 {U8}    {
119         error( String( "top level: header expected: " )
120                 + String_convert::bin2hex_str( String( *YYText() ) ) );
121         exit( 1 );
122 }
123 {BACKUP_TOP_0} {
124         error( String( "top level: header expected: " )
125                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
126         exit( 1 );
127 }
128 {BACKUP_TOP_1} {
129         error( String( "top level: header expected: " )
130                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
131         exit( 1 );
132 }
133 {BACKUP_TOP_2} {
134         error( String( "top level: header expected: " )
135                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
136         exit( 1 );
137 }
138 <int32>{INT32}  { // really signed? 
139         tor( DEBUG_ver ) << "lex: int32" << endl;
140         assert( YYLeng() == 4 );
141         String str( (Byte const*)YYText(), YYLeng() );
142         yylval.i = String_convert::bin2_i( str );
143         yy_pop_state();
144         return INT32;
145 }
146 <int32>{BACKUP_INT32_0} {
147         error( String( "int32: int32 expected: " )
148                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
149         exit( 1 );
150 }
151 <int32>{BACKUP_INT32_1} {
152         error( String( "int32: int32 expected: " )
153                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
154         exit( 1 );
155 }
156 <int32>{BACKUP_INT32_2} {
157         error( String( "int32: int32 expected: " )
158                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
159         exit( 1 );
160 }
161 <int16>{INT16}  { // really signed?
162         tor( DEBUG_ver ) << "lex: int16" << endl;
163         assert( YYLeng() == 2 );
164         String str( (Byte const*)YYText(), YYLeng() );
165         yylval.i = (short)String_convert::bin2_i( str );
166         yy_pop_state();
167         return INT16;
168 }
169 <int16>{BACKUP_INT16_0} {
170         error( String( "int16: int16 expected: " )
171                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
172         exit( 1 );
173 }
174 <i8>{I8}        {
175         tor( DEBUG_ver ) << "lex: i8" << endl;
176         assert( YYLeng() == 1 );
177 //      yylval.byte = *(signed char*)YYText();
178         yylval.i = *(signed char*)YYText();
179         yy_pop_state(); 
180         return I8;
181 }
182 <u8>{U8}        {
183         tor( DEBUG_ver ) << "lex: u8" << endl;
184         assert( YYLeng() == 1 );
185 //      yylval.byte = *(Byte*)YYText();
186         yylval.i = *(Byte*)YYText();
187         yy_pop_state(); 
188         return U8;
189 }
190
191 <track>{VARINT} {
192         String str( (Byte const*)YYText(), YYLeng() );
193         yylval.i = My_midi_lexer::varint2_i( str );
194         tor( DEBUG_ver ) << String( "lex: track: varint(" ) 
195                 + String( yylval.i ) + "): "
196                 + String_convert::bin2hex_str( str ) << endl;
197         yy_push_state( event ); 
198         return VARINT;
199 }
200 <track>{U8}     {
201         error( String( "track: illegal byte: " ) 
202                 + String_convert::bin2hex_str( String( *YYText() ) ) );
203         exit( 1 );
204 }
205 <track>{BACKUP_VARINT_0}{U8} {
206         error( String( "track: varint expected: " )
207                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
208         exit( 1 );
209 }
210 <track>{BACKUP_VARINT_1}{U8} {
211         error( String( "track: varint expected: " )
212                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
213         exit( 1 );
214 }
215 <track>{BACKUP_VARINT_2}{U8} {
216         error( String( "track: varint expected: " )
217                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
218         exit( 1 );
219 }
220 <event>{RUNNING_STATUS} {
221 //      yylval.byte = *(Byte*)YYText();
222         yylval.i = *(Byte*)YYText();
223         tor( DEBUG_ver ) << String ( "lex: running status: " ) + String( yylval.i ) << endl;
224         yy_pop_state(); 
225 //      yy_push_state( u8 );
226         yy_push_state( u8 );
227         return RUNNING_STATUS;
228 }
229 <event>{DATA_ENTRY}     {
230 //      yylval.byte = *(Byte*)YYText();
231         yylval.i = *(Byte*)YYText();
232         tor( DEBUG_ver ) << String ( "lex: undefined data entry: " ) + String( yylval.i ) << endl;
233         yy_pop_state(); 
234         yy_push_state( u8 );
235         return DATA_ENTRY;
236 }
237 <event>{ALL_NOTES_OFF}  {
238         tor( DEBUG_ver ) << "lex: all note off" << endl;
239 //      yylval.byte = *(Byte*)YYText();
240         yylval.i = *(Byte*)YYText();
241         tor( DEBUG_ver ) << String ( "lex: all notes off: " ) + String( yylval.i ) << endl;
242         yy_pop_state(); 
243         yy_push_state( u8 );
244         yy_push_state( u8 );
245         return ALL_NOTES_OFF;
246 }
247 <event>{NOTE_OFF}       {
248         tor( DEBUG_ver ) << "lex: note off" << endl;
249 //      yylval.byte = *(Byte*)YYText();
250         yylval.i = *(Byte*)YYText();
251         yy_pop_state(); 
252         yy_push_state( u8 );
253         yy_push_state( u8 );
254         return NOTE_OFF;
255 }
256 <event>{NOTE_ON}        {
257         tor( DEBUG_ver ) << "lex: note on" << endl;
258 //      yylval.byte = *(Byte*)YYText();
259         yylval.i = *(Byte*)YYText();
260         yy_pop_state(); 
261         yy_push_state( u8 );
262         yy_push_state( u8 );
263         return NOTE_ON;
264 }
265 <event>{POLYPHONIC_AFTERTOUCH}  {
266         tor( DEBUG_ver ) << "lex: polyphonic aftertouch" << endl;
267 //      yylval.byte = *(Byte*)YYText();
268         yylval.i = *(Byte*)YYText();
269         yy_pop_state(); 
270         yy_push_state( u8 );
271         yy_push_state( u8 );
272         return POLYPHONIC_AFTERTOUCH;
273 }
274 <event>{CONTROLMODE_CHANGE}     {
275         tor( DEBUG_ver ) << "lex: controlmode change" << endl;
276 //      yylval.byte = *(Byte*)YYText();
277         yylval.i = *(Byte*)YYText();
278         yy_pop_state(); 
279         yy_push_state( u8 );
280         yy_push_state( u8 );
281         return CONTROLMODE_CHANGE;
282 }
283 <event>{PROGRAM_CHANGE} {
284         tor( DEBUG_ver ) << "lex: program change" << endl;
285 //      yylval.byte = *(Byte*)YYText();
286         yylval.i = *(Byte*)YYText();
287         yy_pop_state(); 
288         yy_push_state( u8 );
289         return PROGRAM_CHANGE;
290 }
291 <event>{CHANNEL_AFTERTOUCH}     {
292         tor( DEBUG_ver ) << "lex: channel aftertouch" << endl;
293 //      yylval.byte = *(Byte*)YYText();
294         yylval.i = *(Byte*)YYText();
295         yy_pop_state(); 
296         yy_push_state( u8 );
297         yy_push_state( u8 );
298         return CHANNEL_AFTERTOUCH;
299 }
300 <event>{PITCHWHEEL_RANGE} {
301         tor( DEBUG_ver ) << "lex: pitchwheel range" << endl;
302 //      yylval.byte = *(Byte*)YYText();
303         yylval.i = *(Byte*)YYText();
304         yy_pop_state(); 
305         yy_push_state( u8 );
306         yy_push_state( u8 );
307         return PITCHWHEEL_RANGE;
308 }
309 <event>{SYSEX_EVENT1} { // len data
310         tor( DEBUG_ver ) << "lex: sysex1" << endl;
311         yy_pop_state(); 
312         yy_push_state( data );
313         return SYSEX_EVENT1;
314 }
315 <event>{SYSEX_EVENT2} { // len data
316         tor( DEBUG_ver ) << "lex: sysex2" << endl;
317         yy_pop_state(); 
318 //      yy_push_state( u8 ); //?
319         yy_push_state( data );
320         return SYSEX_EVENT2;
321 }
322 <event>{META_EVENT}     {
323         tor( DEBUG_ver ) << "lex: meta" << endl;
324         yy_push_state( meta_event );
325         return META_EVENT;
326 }
327 <event>{U8}     {
328         error( String( "event: illegal byte: " ) 
329                 + String_convert::bin2hex_str( String( *YYText() ) ) );
330         exit( 1 );
331 }
332 <meta_event>{SEQUENCE}  {       // ssss sequence number
333         tor( DEBUG_ver ) << "lex: sequence" << endl;
334         yy_pop_state();
335         yy_pop_state();
336         yy_push_state( int16 );
337         return SEQUENCE;
338 }
339 <meta_event>{YYTEXT}    {               // len data
340         tor( DEBUG_ver ) << "lex: text" << endl;
341 //      yylval.byte = *(Byte*)YYText();
342         yylval.i = *(Byte*)YYText();
343         yy_pop_state();
344         yy_pop_state();
345         yy_push_state( data );
346         return YYTEXT;
347 }
348 <meta_event>{YYCOPYRIGHT}       {
349         tor( DEBUG_ver ) << "lex: copyright" << endl;
350 //      yylval.byte = *(Byte*)YYText();
351         yylval.i = *(Byte*)YYText();
352         yy_pop_state();
353         yy_pop_state();
354         yy_push_state( data );
355         return YYCOPYRIGHT;
356 }
357 <meta_event>{YYTRACK_NAME}      {
358         tor( DEBUG_ver ) << "lex: track name" << endl;
359 //      yylval.byte = *(Byte*)YYText();
360         yylval.i = *(Byte*)YYText();
361         yy_pop_state();
362         yy_pop_state();
363         yy_push_state( data );
364         return YYTRACK_NAME;
365 }
366 <meta_event>{YYINSTRUMENT_NAME} {
367         tor( DEBUG_ver ) << "lex: instrument name" << endl;
368 //      yylval.byte = *(Byte*)YYText();
369         yylval.i = *(Byte*)YYText();
370         yy_pop_state();
371         yy_pop_state();
372         yy_push_state( data );
373         return YYINSTRUMENT_NAME;
374 }
375 <meta_event>{YYLYRIC}   {
376         tor( DEBUG_ver ) << "lex: lyric" << endl;
377 //      yylval.byte = *(Byte*)YYText();
378         yylval.i = *(Byte*)YYText();
379         yy_pop_state();
380         yy_pop_state();
381         yy_push_state( data );
382         return YYLYRIC;
383 }
384 <meta_event>{YYMARKER}  {
385         tor( DEBUG_ver ) << "lex: marker" << endl;
386 //      yylval.byte = *(Byte*)YYText();
387         yylval.i = *(Byte*)YYText();
388         yy_pop_state();
389         yy_pop_state();
390         yy_push_state( data );
391         return YYMARKER;
392 }
393 <meta_event>{YYCUE_POINT}       {
394         tor( DEBUG_ver ) << "lex: cue point" << endl;
395 //      yylval.byte = *(Byte*)YYText();
396         yylval.i = *(Byte*)YYText();
397         yy_pop_state();
398         yy_pop_state();
399         yy_push_state( data );
400         return YYCUE_POINT;
401 }
402 <meta_event>{TEMPO}     {       // tttttt usec
403         tor( DEBUG_ver ) << "lex: tempo" << endl;
404         yy_pop_state();
405         yy_pop_state();
406         yy_push_state( u8 );
407         yy_push_state( u8 );
408         yy_push_state( u8 );
409         return TEMPO;
410 }
411 <meta_event>{SMPTE_OFFSET}      {               // hr mn se fr ff
412         tor( DEBUG_ver ) << "lex: smpte offset" << endl;
413         yy_pop_state();
414         yy_pop_state();
415         yy_push_state( u8 );
416         yy_push_state( u8 );
417         yy_push_state( u8 );
418         yy_push_state( u8 );
419         yy_push_state( u8 );
420         return SMPTE_OFFSET;
421 }
422 <meta_event>{TIME}      {               // nn dd cc bb
423         tor( DEBUG_ver ) << "lex: time" << endl;
424         yy_pop_state();
425         yy_pop_state();
426         yy_push_state( u8 );
427         yy_push_state( u8 );
428         yy_push_state( u8 );
429         yy_push_state( u8 );
430         return TIME;
431 }
432 <meta_event>{KEY}       {       // sf mi
433         tor( DEBUG_ver ) << "lex: key" << endl;
434         yy_pop_state();
435         yy_pop_state();
436         yy_push_state( i8 );
437         yy_push_state( i8 );
438         return KEY;
439 }
440 <meta_event>{SSME}      {       // len data
441         tor( DEBUG_ver ) << "lex: smme" << endl;
442         yy_pop_state();
443         yy_pop_state();
444         yy_push_state( data );
445         return SSME;
446 }
447 <meta_event>{END_OF_TRACK} {
448         tor( DEBUG_ver ) << "lex: end of track" << endl;
449         yy_pop_state();
450         yy_pop_state();
451         yy_pop_state();
452         return END_OF_TRACK;
453 }
454 <meta_event>{U8} {
455         warning( String( "meta_event: unimplemented event: " )
456                 + String_convert::bin2hex_str( String( *YYText() ) )
457 //,             this->here_ch_C() 
458         );
459         yy_pop_state();
460         yy_pop_state();
461         yy_push_state( u8 ); 
462         yy_push_state( u8 );
463         return U8;
464 }
465
466 <data>{VARINT} {
467         tor( DEBUG_ver ) << "lex: data" << endl;
468         String str( (Byte const*)YYText(), YYLeng() );
469         int i = My_midi_lexer::varint2_i( str );
470         String* str_p = new String;
471         while ( i-- )
472                 *str_p += (char)yyinput();
473         yylval.str_p = str_p;
474         yy_pop_state();
475         return DATA;
476 }
477 <data>{U8}      {
478         error( String( "data: illegal byte: " )
479                 + String_convert::bin2hex_str( String( *YYText() ) ) );
480         exit( 1 );
481 }
482 <data>{BACKUP_VARINT_0}{U8} {
483         error( String( "data: varint expected: " )
484                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
485         exit( 1 );
486 }
487 <data>{BACKUP_VARINT_1}{U8} {
488         error( String( "data: varint expected: " )
489                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
490         exit( 1 );
491 }
492 <data>{BACKUP_VARINT_2}{U8} {
493         error( String( "data: varint expected: " )
494                 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
495         exit( 1 );
496 }
497
498 <<EOF>> {
499 //      tor( NORMAL_ver ) << "<<EOF>>";
500
501         if ( !close_i() )
502           yyterminate(); // can't move this, since it actually rets a YY_NULL
503 }
504
505 %%
506