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.
9 it is, however, quite robust, simple, and very easy to extend
16 after making a change to the lexer rules, run
17 flex -b <this lexer file>
20 contains no backup states, but only the reminder
21 Compressed tables always back up.
22 (don-t forget to rm lex.yy.cc :-)
26 #include "midi-parser.hh"
28 #define YY_USER_ACTION char_count_ += YYLeng(); // ugh
35 %option yyclass="My_midi_lexer"
53 BACKUP_INT32_1 {U8}{U8}
54 BACKUP_INT32_2 {INT16}{U8}
55 INT7_8UNSET [\x00-\x7f]
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}
68 XRUNNING_STATUS [\x30-\x4f]
69 RUNNING_STATUS [\x00-\x5f]
70 DATA_ENTRY [\x60-\x79]
71 ALL_NOTES_OFF [\x7a-\x7f]
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]
89 YYINSTRUMENT_NAME [\x04]
94 END_OF_TRACK [\x2f][\x00]
96 SMPTE_OFFSET [\x54][\x05]
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 );
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 );
119 error( String( "top level: header expected: " )
120 + String_convert::bin2hex_str( String( *YYText() ) ) );
124 error( String( "top level: header expected: " )
125 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
129 error( String( "top level: header expected: " )
130 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
134 error( String( "top level: header expected: " )
135 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
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 );
146 <int32>{BACKUP_INT32_0} {
147 error( String( "int32: int32 expected: " )
148 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
151 <int32>{BACKUP_INT32_1} {
152 error( String( "int32: int32 expected: " )
153 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
156 <int32>{BACKUP_INT32_2} {
157 error( String( "int32: int32 expected: " )
158 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
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 );
169 <int16>{BACKUP_INT16_0} {
170 error( String( "int16: int16 expected: " )
171 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
175 tor( DEBUG_ver ) << "lex: i8" << endl;
176 assert( YYLeng() == 1 );
177 // yylval.byte = *(signed char*)YYText();
178 yylval.i = *(signed char*)YYText();
183 tor( DEBUG_ver ) << "lex: u8" << endl;
184 assert( YYLeng() == 1 );
185 // yylval.byte = *(Byte*)YYText();
186 yylval.i = *(Byte*)YYText();
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 );
201 error( String( "track: illegal byte: " )
202 + String_convert::bin2hex_str( String( *YYText() ) ) );
205 <track>{BACKUP_VARINT_0}{U8} {
206 error( String( "track: varint expected: " )
207 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
210 <track>{BACKUP_VARINT_1}{U8} {
211 error( String( "track: varint expected: " )
212 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
215 <track>{BACKUP_VARINT_2}{U8} {
216 error( String( "track: varint expected: " )
217 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
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;
225 // yy_push_state( u8 );
227 return RUNNING_STATUS;
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;
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;
245 return ALL_NOTES_OFF;
248 tor( DEBUG_ver ) << "lex: note off" << endl;
249 // yylval.byte = *(Byte*)YYText();
250 yylval.i = *(Byte*)YYText();
257 tor( DEBUG_ver ) << "lex: note on" << endl;
258 // yylval.byte = *(Byte*)YYText();
259 yylval.i = *(Byte*)YYText();
265 <event>{POLYPHONIC_AFTERTOUCH} {
266 tor( DEBUG_ver ) << "lex: polyphonic aftertouch" << endl;
267 // yylval.byte = *(Byte*)YYText();
268 yylval.i = *(Byte*)YYText();
272 return POLYPHONIC_AFTERTOUCH;
274 <event>{CONTROLMODE_CHANGE} {
275 tor( DEBUG_ver ) << "lex: controlmode change" << endl;
276 // yylval.byte = *(Byte*)YYText();
277 yylval.i = *(Byte*)YYText();
281 return CONTROLMODE_CHANGE;
283 <event>{PROGRAM_CHANGE} {
284 tor( DEBUG_ver ) << "lex: program change" << endl;
285 // yylval.byte = *(Byte*)YYText();
286 yylval.i = *(Byte*)YYText();
289 return PROGRAM_CHANGE;
291 <event>{CHANNEL_AFTERTOUCH} {
292 tor( DEBUG_ver ) << "lex: channel aftertouch" << endl;
293 // yylval.byte = *(Byte*)YYText();
294 yylval.i = *(Byte*)YYText();
298 return CHANNEL_AFTERTOUCH;
300 <event>{PITCHWHEEL_RANGE} {
301 tor( DEBUG_ver ) << "lex: pitchwheel range" << endl;
302 // yylval.byte = *(Byte*)YYText();
303 yylval.i = *(Byte*)YYText();
307 return PITCHWHEEL_RANGE;
309 <event>{SYSEX_EVENT1} { // len data
310 tor( DEBUG_ver ) << "lex: sysex1" << endl;
312 yy_push_state( data );
315 <event>{SYSEX_EVENT2} { // len data
316 tor( DEBUG_ver ) << "lex: sysex2" << endl;
318 // yy_push_state( u8 ); //?
319 yy_push_state( data );
322 <event>{META_EVENT} {
323 tor( DEBUG_ver ) << "lex: meta" << endl;
324 yy_push_state( meta_event );
328 error( String( "event: illegal byte: " )
329 + String_convert::bin2hex_str( String( *YYText() ) ) );
332 <meta_event>{SEQUENCE} { // ssss sequence number
333 tor( DEBUG_ver ) << "lex: sequence" << endl;
336 yy_push_state( int16 );
339 <meta_event>{YYTEXT} { // len data
340 tor( DEBUG_ver ) << "lex: text" << endl;
341 // yylval.byte = *(Byte*)YYText();
342 yylval.i = *(Byte*)YYText();
345 yy_push_state( data );
348 <meta_event>{YYCOPYRIGHT} {
349 tor( DEBUG_ver ) << "lex: copyright" << endl;
350 // yylval.byte = *(Byte*)YYText();
351 yylval.i = *(Byte*)YYText();
354 yy_push_state( data );
357 <meta_event>{YYTRACK_NAME} {
358 tor( DEBUG_ver ) << "lex: track name" << endl;
359 // yylval.byte = *(Byte*)YYText();
360 yylval.i = *(Byte*)YYText();
363 yy_push_state( data );
366 <meta_event>{YYINSTRUMENT_NAME} {
367 tor( DEBUG_ver ) << "lex: instrument name" << endl;
368 // yylval.byte = *(Byte*)YYText();
369 yylval.i = *(Byte*)YYText();
372 yy_push_state( data );
373 return YYINSTRUMENT_NAME;
375 <meta_event>{YYLYRIC} {
376 tor( DEBUG_ver ) << "lex: lyric" << endl;
377 // yylval.byte = *(Byte*)YYText();
378 yylval.i = *(Byte*)YYText();
381 yy_push_state( data );
384 <meta_event>{YYMARKER} {
385 tor( DEBUG_ver ) << "lex: marker" << endl;
386 // yylval.byte = *(Byte*)YYText();
387 yylval.i = *(Byte*)YYText();
390 yy_push_state( data );
393 <meta_event>{YYCUE_POINT} {
394 tor( DEBUG_ver ) << "lex: cue point" << endl;
395 // yylval.byte = *(Byte*)YYText();
396 yylval.i = *(Byte*)YYText();
399 yy_push_state( data );
402 <meta_event>{TEMPO} { // tttttt usec
403 tor( DEBUG_ver ) << "lex: tempo" << endl;
411 <meta_event>{SMPTE_OFFSET} { // hr mn se fr ff
412 tor( DEBUG_ver ) << "lex: smpte offset" << endl;
422 <meta_event>{TIME} { // nn dd cc bb
423 tor( DEBUG_ver ) << "lex: time" << endl;
432 <meta_event>{KEY} { // sf mi
433 tor( DEBUG_ver ) << "lex: key" << endl;
440 <meta_event>{SSME} { // len data
441 tor( DEBUG_ver ) << "lex: smme" << endl;
444 yy_push_state( data );
447 <meta_event>{END_OF_TRACK} {
448 tor( DEBUG_ver ) << "lex: end of track" << endl;
455 warning( String( "meta_event: unimplemented event: " )
456 + String_convert::bin2hex_str( String( *YYText() ) )
457 //, this->here_ch_C()
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;
472 *str_p += (char)yyinput();
473 yylval.str_p = str_p;
478 error( String( "data: illegal byte: " )
479 + String_convert::bin2hex_str( String( *YYText() ) ) );
482 <data>{BACKUP_VARINT_0}{U8} {
483 error( String( "data: varint expected: " )
484 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
487 <data>{BACKUP_VARINT_1}{U8} {
488 error( String( "data: varint expected: " )
489 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
492 <data>{BACKUP_VARINT_2}{U8} {
493 error( String( "data: varint expected: " )
494 + String_convert::bin2hex_str( String( *( YYText() ) ) ) );
499 // tor( NORMAL_ver ) << "<<EOF>>";
502 yyterminate(); // can't move this, since it actually rets a YY_NULL