%{//-*-Fundamental-*- // midi-lexer.l #include "mi2mu.hh" #include "midi-parser.hh" #define YY_USER_ACTION char_count_ += YYLeng(); // ugh %} %option c++ %option noyywrap %option nodefault %option debug %option yyclass="My_midi_lexer" %option stack %x data %x event %x i8 %x u8 %x int16 %x int32 %x meta_event %x track U8 [\x00-\xff] I8 {U8} INT16 {U8}{U8} INT32 {INT16}{INT16} INT7_8UNSET [\x00-\x7f] INT7_8SET [\x80-\xff] VARINT {INT7_8SET}{0,3}{INT7_8UNSET} HEADER MThd TRACK MTrk XRUNNING_STATUS [\x30-\x4f] RUNNING_STATUS [\x00-\x5f] DATA_ENTRY [\x60-\x79] ALL_NOTES_OFF [\x7a-\x7f] NOTE_OFF [\x80-\x8f] NOTE_ON [\x90-\x9f] POLYPHONIC_AFTERTOUCH [\xa0-\xaf] CONTROLMODE_CHANGE [\xb0-\xbf] PROGRAM_CHANGE [\xc0-\xcf] CHANNEL_AFTERTOUCH [\xd0-\xdf] PITCHWHEEL_RANGE [\xe0-\xef] SYSEX_EVENT1 [\xf0] SYSEX_EVENT2 [\xf7] META_EVENT [\xff] SEQUENCE [\x00][\x02] YYTEXT [\x01] YYCOPYRIGHT [\x02] YYTRACK_NAME [\x03] YYINSTRUMENT_NAME [\x04] YYLYRIC [\x05] YYMARKER [\x06] YYCUE_POINT [\x07] END_OF_TRACK [\x2f][\x00] TEMPO [\x51][\x03] SMPTE_OFFSET [\x54][\x05] TIME [\x58][\x04] KEY [\x59][\x02] SSME [\0x7f][\x03] %% {HEADER}/{INT32} { // using /{INT32}; longer match than {INT32} tor( DEBUG_ver ) << "lex: header" << endl; yy_push_state( int16 ); yy_push_state( int16 ); yy_push_state( int16 ); yy_push_state( int32 ); return HEADER; } {TRACK}/{INT32} { // using /{INT32}; longer match than {INT32} tor( DEBUG_ver ) << "lex: track" << endl; yy_push_state( track ); yy_push_state( int32 ); return TRACK; } {U8} { error( String( "top level: illegal byte: " ) + String_convert::bin2hex_str( String( *YYText() ) ) ); exit( 1 ); } {INT32} { // really signed? tor( DEBUG_ver ) << "lex: int32" << endl; assert( YYLeng() == 4 ); String str( (Byte const*)YYText(), YYLeng() ); yylval.i = String_convert::bin2_i( str ); yy_pop_state(); return INT32; } {INT16} { // really signed? tor( DEBUG_ver ) << "lex: int16" << endl; assert( YYLeng() == 2 ); String str( (Byte const*)YYText(), YYLeng() ); yylval.i = String_convert::bin2_i( str ); yy_pop_state(); return INT16; } {I8} { tor( DEBUG_ver ) << "lex: i8" << endl; assert( YYLeng() == 1 ); // yylval.byte = *(signed char*)YYText(); yylval.i = *(signed char*)YYText(); yy_pop_state(); return I8; } {U8} { tor( DEBUG_ver ) << "lex: u8" << endl; assert( YYLeng() == 1 ); // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); return U8; } {VARINT} { String str( (Byte const*)YYText(), YYLeng() ); yylval.i = My_midi_lexer::varint2_i( str ); tor( DEBUG_ver ) << String( "lex: track: varint(" ) + String( yylval.i ) + "): " + String_convert::bin2hex_str( str ) << endl; yy_push_state( event ); return VARINT; } {U8} { error( String( "track: illegal byte: " ) + String_convert::bin2hex_str( String( *YYText() ) ) ); exit( 1 ); } {RUNNING_STATUS} { // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); tor( DEBUG_ver ) << String ( "lex: running status: " ) + String( yylval.i ) << endl; yy_pop_state(); // yy_push_state( u8 ); yy_push_state( u8 ); return RUNNING_STATUS; } {DATA_ENTRY} { // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); tor( DEBUG_ver ) << String ( "lex: undefined data entry: " ) + String( yylval.i ) << endl; yy_pop_state(); yy_push_state( u8 ); return DATA_ENTRY; } {ALL_NOTES_OFF} { tor( DEBUG_ver ) << "lex: all note off" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); tor( DEBUG_ver ) << String ( "lex: all notes off: " ) + String( yylval.i ) << endl; yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return ALL_NOTES_OFF; } {NOTE_OFF} { tor( DEBUG_ver ) << "lex: note off" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return NOTE_OFF; } {NOTE_ON} { tor( DEBUG_ver ) << "lex: note on" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return NOTE_ON; } {POLYPHONIC_AFTERTOUCH} { tor( DEBUG_ver ) << "lex: polyphonic aftertouch" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return POLYPHONIC_AFTERTOUCH; } {CONTROLMODE_CHANGE} { tor( DEBUG_ver ) << "lex: controlmode change" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return CONTROLMODE_CHANGE; } {PROGRAM_CHANGE} { tor( DEBUG_ver ) << "lex: program change" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_push_state( u8 ); return PROGRAM_CHANGE; } {CHANNEL_AFTERTOUCH} { tor( DEBUG_ver ) << "lex: channel aftertouch" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return CHANNEL_AFTERTOUCH; } {PITCHWHEEL_RANGE} { tor( DEBUG_ver ) << "lex: pitchwheel range" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return PITCHWHEEL_RANGE; } {SYSEX_EVENT1} { // len data tor( DEBUG_ver ) << "lex: sysex1" << endl; yy_pop_state(); yy_push_state( data ); return SYSEX_EVENT1; } {SYSEX_EVENT2} { // len data tor( DEBUG_ver ) << "lex: sysex2" << endl; yy_pop_state(); // yy_push_state( u8 ); //? yy_push_state( data ); return SYSEX_EVENT2; } {META_EVENT} { tor( DEBUG_ver ) << "lex: meta" << endl; yy_push_state( meta_event ); return META_EVENT; } {U8} { error( String( "event: illegal byte: " ) + String_convert::bin2hex_str( String( *YYText() ) ) ); exit( 1 ); } {SEQUENCE} { // ssss sequence number tor( DEBUG_ver ) << "lex: sequence" << endl; yy_pop_state(); yy_pop_state(); yy_push_state( int16 ); return SEQUENCE; } {YYTEXT} { // len data tor( DEBUG_ver ) << "lex: text" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_pop_state(); yy_push_state( data ); return YYTEXT; } {YYCOPYRIGHT} { tor( DEBUG_ver ) << "lex: copyright" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_pop_state(); yy_push_state( data ); return YYCOPYRIGHT; } {YYTRACK_NAME} { tor( DEBUG_ver ) << "lex: track name" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_pop_state(); yy_push_state( data ); return YYTRACK_NAME; } {YYINSTRUMENT_NAME} { tor( DEBUG_ver ) << "lex: instrument name" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_pop_state(); yy_push_state( data ); return YYINSTRUMENT_NAME; } {YYLYRIC} { tor( DEBUG_ver ) << "lex: lyric" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_pop_state(); yy_push_state( data ); return YYLYRIC; } {YYMARKER} { tor( DEBUG_ver ) << "lex: marker" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_pop_state(); yy_push_state( data ); return YYMARKER; } {YYCUE_POINT} { tor( DEBUG_ver ) << "lex: cue point" << endl; // yylval.byte = *(Byte*)YYText(); yylval.i = *(Byte*)YYText(); yy_pop_state(); yy_pop_state(); yy_push_state( data ); return YYCUE_POINT; } {TEMPO} { // tttttt usec tor( DEBUG_ver ) << "lex: tempo" << endl; yy_pop_state(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); yy_push_state( u8 ); return TEMPO; } {SMPTE_OFFSET} { // hr mn se fr ff tor( DEBUG_ver ) << "lex: smpte offset" << endl; yy_pop_state(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); yy_push_state( u8 ); yy_push_state( u8 ); yy_push_state( u8 ); return SMPTE_OFFSET; } {TIME} { // nn dd cc bb tor( DEBUG_ver ) << "lex: time" << endl; yy_pop_state(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); yy_push_state( u8 ); yy_push_state( u8 ); return TIME; } {KEY} { // sf mi tor( DEBUG_ver ) << "lex: key" << endl; yy_pop_state(); yy_pop_state(); yy_push_state( i8 ); yy_push_state( i8 ); return KEY; } {SSME} { // len data tor( DEBUG_ver ) << "lex: smme" << endl; yy_pop_state(); yy_pop_state(); yy_push_state( data ); return SSME; } {END_OF_TRACK} { tor( DEBUG_ver ) << "lex: end of track" << endl; yy_pop_state(); yy_pop_state(); yy_pop_state(); return END_OF_TRACK; } {U8} { warning( String( "meta_event: unimplemented event: " ) + String_convert::bin2hex_str( String( *YYText() ) ) //, this->here_ch_C() ); yy_pop_state(); yy_pop_state(); yy_push_state( u8 ); yy_push_state( u8 ); return U8; } {VARINT} { tor( DEBUG_ver ) << "lex: data" << endl; String str( (Byte const*)YYText(), YYLeng() ); int i = My_midi_lexer::varint2_i( str ); String* str_p = new String; while ( i-- ) *str_p += (char)yyinput(); yylval.str_p = str_p; yy_pop_state(); return DATA; } {U8} { error( String( "data: illegal byte: " ) + String_convert::bin2hex_str( String( *YYText() ) ) ); exit( 1 ); } <> { // tor( NORMAL_ver ) << "<>"; if ( !close_i() ) yyterminate(); // can't move this, since it actually rets a YY_NULL } %%