Dependencies:   mbed

Revision:
0:71d791204057
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parse.h	Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,448 @@
+#ifndef PARSE_H
+#define PARSE_H
+
+#include <string.h>
+#include <vector>
+
+void ParseCleanUp( char* s1, char* s2 )
+{
+    // copy all non blank till ; or 0
+    for( int i = 0, j = 0 ; i < 256 ; i++ )
+        if( s1[i] != 32 && s1[i] != 13 && s1[i] != 10 && s1[i] != 9 )
+            switch( s2[j++] = s1[i] ) {
+            case ';': s2[j-1] = 0; return;
+            case 0: return;
+        }
+}
+int GetOPIDfromFunction( char * f )
+{
+    if( strcmp( f, "add" ) == 0 ) return ADD;
+    if( strcmp( f, "mul" ) == 0 ) return MUL;
+    if( strcmp( f, "sub" ) == 0 ) return SUB;
+    if( strcmp( f, "div" ) == 0 ) return DIV;
+    if( strcmp( f, "i8"  ) == 0 ) return E8_;
+    if( strcmp( f, "i14" ) == 0 ) return E14;
+    if( strcmp( f, "mod" ) == 0 ) return MOD;
+    if( strcmp( f, "bit" ) == 0 ) return BIT;
+    if( strcmp( f, "bor" ) == 0 ) return BOR;
+    if( strcmp( f, "ban" ) == 0 ) return BAN;
+    if( strcmp( f, "bno" ) == 0 ) return BNO;
+    if( strcmp( f, "bsl" ) == 0 ) return BSL;
+    if( strcmp( f, "bsr" ) == 0 ) return BSR;
+    if( strcmp( f, "msb" ) == 0 ) return MSB;
+    if( strcmp( f, "lsb" ) == 0 ) return LSB;
+    if( strcmp( f, "map" ) == 0 ) return MAP;
+    if( strcmp( f, "nrpn") == 0 ) return NPN;
+    if( strcmp( f, "rpn" ) == 0 ) return RPN;
+    if( strcmp( f, "bank") == 0 ) return BNK;
+    if( strcmp( f, "nrp8") == 0 ) return NP8;
+    return 0;
+}
+
+int ParseError = 0;
+int ParseLine  = 0;
+#define abort(x) { ParseError = x; return false; }
+
+#define PARSE_NOERROR                0
+#define PARSE_NO_FILE                1
+#define PARSE_BAD_NUMBER_DEFINITION  2
+#define PARSE_BAD_MESSAGE_DEFINITION 3
+#define PARSE_BAD_SEQ_SYNTAXE        4
+#define PARSE_BAD_SEQ_HEXA_SIGN      5
+#define PARSE_BAD_SEQ_NUMBER         6
+#define PARSE_BAD_SEQ_IDENTIFIER     7
+#define PARSE_BAD_SEQ_BYTE           8
+#define PARSE_BAD_SEQ_FUNCTION       9
+#define PARSE_BAD_SEQ_TOOLONG       10
+#define PARSE_UNKNWON_ENTRY         11
+#define PARSE_MIN_GREATER_THAN_MAX  12
+
+#define TOKEN_END  *p == 0 || *p == ',' || *p == ')'
+#define TOKEN_NUM  *p >= '0' && *p <= '9'
+#define TOKEN_LOW  *p >= 'a' && *p <= 'z'
+#define TOKEN_UPP  *p >= 'A' && *p <= 'Z'
+#define TOKEN_LOX  *p >= 'a' && *p <= 'f'
+#define TOKEN_UPX  *p >= 'A' && *p <= 'F'
+
+class ParseEntry   
+{
+public:
+    char Name[17];
+    ParseEntry( char* name ) 
+    {
+        short i = 0;
+        for( i = 0 ; i < 16 && name[i] ; i++ )
+        {
+            if( name[i] >= 'A' && name[i]<='Z' ) Name[i] = name[i] + 32; else Name[i] = name[i];
+        }
+        Name[i] = 0;
+    }
+    virtual ~ParseEntry() {}
+    
+    virtual bool Parse( char* data ){ return true; }
+};
+class ParseFlag     : public ParseEntry
+{
+public:
+    int Flag;
+    ParseFlag( char* name ) : ParseEntry( name ), Flag(0) {}
+    virtual ~ParseFlag(){}
+    virtual bool Parse( char* data )
+    {
+        if( *data == '*' )
+        {
+            Flag = NAKW;
+            return true;
+        }
+        Flag = 0;
+        for( int i = 0 ; i < 16 ; i++ )
+            if( data[i] == 0 ) break;
+            else if( data[i] != '-' ) Flag |= 1 << i;
+        return true;
+    }
+};
+class ParseByte : public ParseEntry
+{
+public:
+    byte Mini;
+    byte Maxi;
+    ParseByte( char* name ) : ParseEntry( name ),Mini(NAKN), Maxi(NAKN) {}
+    virtual ~ParseByte(){}
+    virtual bool Parse( char* data )
+    {
+        if( *data == '*' )
+        {
+            Mini = NAKN;
+            Maxi = NAKN;
+            return true;
+        }
+
+        int   base  = 10;
+        bool  start = true;
+        int   dot   = 0;
+        char  set[] = "0123456789ABCDEF$.";
+        char* p;
+        bool  ok    = false;
+        
+        Mini = 0;
+        
+        while( *data )
+        {
+            ok = false;
+            p = strchr( set, *data++ );
+            if( p )
+            {
+                int index = p - set;
+
+                if( index==16 && start==true )                          { start=false; base=16,                    ok=true; }
+                else if( index == 17 && dot < 3 ) { dot++; if( dot==3)  { start=true;  base=10; Maxi = 0;          ok=true; } }
+                else if( index < base )                  { if( dot==3 ) { start=false; Maxi = Maxi * base + index; ok=true; }
+                                                           else         { start=false; Mini = Mini * base + index; ok=true; } }
+                else break;
+            }
+            else break;
+        }
+        if( ! ok ) abort( PARSE_BAD_NUMBER_DEFINITION )
+        if( Maxi != NAKN && Mini > Maxi ) abort( PARSE_MIN_GREATER_THAN_MAX )
+        return true;
+    }
+};
+class ParseShort : public ParseEntry
+{
+public:
+    short Mini;
+    short Maxi;
+    ParseShort( char* name ) : ParseEntry( name ),Mini(NAKW), Maxi(NAKW) {}
+    virtual ~ParseShort(){}
+    virtual bool Parse( char* data )
+    {
+        if( *data == '*' )
+        {
+            Mini = NAKW;
+            Maxi = NAKW;
+            return true;
+        }
+        int   base  = 10;
+        bool  start = true;
+        int   dot   = 0;
+        char  set[] = "0123456789ABCDEF$.";
+        char* p;
+        bool  ok    = false;
+        
+        Mini = 0;
+        
+        while( *data )
+        {
+            ok = false;
+            p = strchr( set, *data++ );
+            if( p )
+            {
+                int index = p - set;
+
+                if( index==16 && start==true )                          { start=false; base=16,                    ok=true; }
+                else if( index == 17 && dot < 3 ) { dot++; if( dot==3)  { start=true;  base=10; Maxi = 0;          ok=true; } }
+                else if( index < base )                  { if( dot==3 ) { start=false; Maxi = Maxi * base + index; ok=true; }
+                                                           else         { start=false; Mini = Mini * base + index; ok=true; } }
+                else break;
+            }
+            else break;
+        }
+        if( ! ok ) abort( PARSE_BAD_NUMBER_DEFINITION )
+        if( Maxi != NAKW && Mini>Maxi ) abort( PARSE_MIN_GREATER_THAN_MAX )
+        return true;
+    }
+};
+class ParseMessage  : public ParseEntry
+{
+public:
+    byte Code;
+    ParseMessage( char* name ) : ParseEntry( name ),Code(NAKN) {}
+    virtual ~ParseMessage(){}
+    virtual bool Parse( char* data )
+    {
+        static char keywords[] = "NOTE;POLA;CTRL;PROG;BANK;DATA;INCR;DECR;RPN_;NRPN;MONA;BEND;SYSX;TCOD;SPOS;SSEL;TUNE;CLOK;STAR;CONT;STOP;SENS;RSET";
+
+        char* p = strstr( keywords, data );
+         if( p == NULL ) abort( PARSE_BAD_MESSAGE_DEFINITION )
+
+        Code = ( p - keywords ) / 5 + 1;
+        return true;
+    }
+};
+
+#define PUSH(x) Sequence.push_back(x)
+
+class ParseSequence : public ParseEntry
+{
+public:
+    vector<short> Sequence;
+    ParseSequence( char* name ) : ParseEntry(name) {}
+    virtual ~ParseSequence() { }
+    
+    virtual bool Parse( char* data )
+    {
+        if( *data == '*' )
+        {
+            Sequence = vector<short>( 1, RAW );
+            return true;
+        }
+        char* p = data;
+        if( SubParse( p ) )
+        {
+            Sequence.push_back(NOP);
+            return true;
+        }
+        return false;
+    }
+    short SubParse( char* &p ) // returns the number of arguments in the sub-sequence
+    {
+        static int level = 0;
+        level++;
+
+        int args = 0;
+
+        while( *p )
+        {
+            int num = 0;
+
+            switch( *p ) 
+            {
+            case '=':
+            case ',':    p++; break;
+            case ')':    p++; level--; return args;
+
+                case '$':    while( 1 ) {
+                                p++; if( TOKEN_END ) { PUSH( num ); break; }
+                                else if( TOKEN_NUM )   num = num * 16 + (*p - 48 );
+                                else if( TOKEN_UPX )   num = num * 16 + (*p - 55 );
+                                else if( TOKEN_LOX )   num = num * 16 + (*p - 87 );
+                                else abort( PARSE_BAD_SEQ_HEXA_SIGN )
+                            } args++; break;
+
+                case '%':    { char fn[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int i = 0;
+                                while( 1 ) {
+                                    p++; if( TOKEN_END ) break;
+                                    else if( TOKEN_NUM ) fn[i++] = *p;
+                                    else if( TOKEN_UPP ) fn[i++] = *p + 32;
+                                    else if( TOKEN_LOW ) fn[i++] = *p;
+                                    else abort( PARSE_BAD_SEQ_IDENTIFIER )
+                                    if( i == 16 ) abort( PARSE_BAD_SEQ_TOOLONG )
+                                }
+                                     if( strcmp( fn, "mc") == 0 ) PUSH( VMC );
+                                else if( strcmp( fn, "m" ) == 0 ) PUSH( VM_ );
+                                else if( strcmp( fn, "c" ) == 0 ) PUSH( VC_ );
+                                else if( strcmp( fn, "a" ) == 0 ) PUSH( VA_ );
+                                else if( strcmp( fn, "b" ) == 0 ) PUSH( VB_ );
+                                else if( strcmp( fn, "n" ) == 0 ) PUSH( VN_ );
+                                else if( strcmp( fn, "d" ) == 0 ) PUSH( VD_ );
+                                else if( strcmp( fn, "k" ) == 0 ) PUSH( VK_ );
+                                else {
+                                    for( int j = 0 ; j < i ; j++ )
+                                        PUSH( CID + fn[j] );
+                                    PUSH( CID );
+                                }
+                            } args++; break;
+
+                default: if( TOKEN_UPP ) *p += 32;
+                
+                    if( TOKEN_LOW ) { char fn[] = {*p,0,0,0,0,0,0,0,0,0}; int i = 1;
+                            while( 1 ) {
+                                p++; if( *p == '(' ) break;
+                                else if( TOKEN_UPP ) fn[i++] = *p + 32;
+                                else if( TOKEN_LOW ) fn[i++] = *p;
+                                else if( TOKEN_NUM ) fn[i++] = *p;
+                                else abort(PARSE_BAD_SEQ_FUNCTION)
+                            }
+                            p++; // skip (
+                            if( level == 1 ) PUSH( SEQ );
+                            short a = SubParse( p );
+                            if( a == 0 ) return 0;
+                            int n = GetOPIDfromFunction( fn );
+                            if( n == 0 ) abort(PARSE_BAD_SEQ_FUNCTION)
+                            if( n == MAP ) PUSH( a );
+                            PUSH( n );
+                            if( level==1 && n!=E8_ && n!=E14 && n!=RPN && n!=NPN && n!=BNK && n!=NP8 ) PUSH( E7_ );
+                            args++;
+                            break;
+                    }
+                    if( TOKEN_NUM ) { 
+                            num = *p - 48;
+                            while( 1 ) {
+                                p++; if( TOKEN_END ) { PUSH( num ); break; }
+                                else if( TOKEN_NUM )   num = num * 10 + (*p - 48 );
+                                else abort( PARSE_BAD_SEQ_NUMBER )
+                            } args++; break;                                
+                    }
+                    abort( PARSE_BAD_SEQ_SYNTAXE )
+            }
+        }
+        level--;
+        return args;
+    }
+};
+
+class ParseRoute
+{
+public :
+    byte Inport;
+    byte Message;
+    short  Channels;
+    short minA;
+    short maxA;
+    short minB;
+    short maxB;
+    vector<byte> Head;
+    vector<short> Sequence1;
+    vector<short> Sequence2;
+    vector<short> Sequence3;
+    vector<Assignment*> Assigns;
+
+    ParseRoute() : Inport(0), Message(NAKN), Channels(NAKW), minA(NAKN), maxA(NAKN), minB(NAKN), maxB(NAKN) {}
+    ~ParseRoute()
+    {
+    }
+    bool Add( ParseEntry* entry )
+    {
+        ParseMessage*  m = (ParseMessage*)entry;
+        ParseFlag*     f = (ParseFlag*)entry;
+        ParseByte*     b = (ParseByte*)entry;
+        ParseShort*    s = (ParseShort*)entry;
+        ParseSequence* q = (ParseSequence*)entry;
+        
+             if( strcmp( entry->Name, "input1"   ) == 0 ) { Inport   = 0; Message  = m->Code; return true; }
+        else if( strcmp( entry->Name, "input2"   ) == 0 ) { Inport   = 1; Message  = m->Code; return true; }
+        else if( strcmp( entry->Name, "input3"   ) == 0 ) { Inport   = 2; Message  = m->Code; return true; }
+        else if( strcmp( entry->Name, "channels" ) == 0 ) { Channels = f->Flag; return true; }
+        else if( strcmp( entry->Name, "program"  ) == 0 ) { minA     = b->Mini; maxA = b->Maxi; return true; }
+        else if( strcmp( entry->Name, "valuea"   ) == 0 ) { minA     = b->Mini; maxA = b->Maxi; return true; }
+        else if( strcmp( entry->Name, "valueb"   ) == 0 ) { minB     = b->Mini; maxB = b->Maxi; return true; }
+        else if( strcmp( entry->Name, "parameter") == 0 ) { minA     = s->Mini; maxA = s->Maxi; return true; }
+        else if( strcmp( entry->Name, "data"     ) == 0 ) { minB     = s->Mini; maxB = s->Maxi; return true; }
+        else if( strcmp( entry->Name, "bank"     ) == 0 ) { minA     = s->Mini; maxA = s->Maxi; return true; }
+        else if( strcmp( entry->Name, "output1"  ) == 0 ) { Sequence1.insert( Sequence1.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+        else if( strcmp( entry->Name, "output2"  ) == 0 ) { Sequence2.insert( Sequence2.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+        else if( strcmp( entry->Name, "output3"  ) == 0 ) { Sequence3.insert( Sequence3.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+        else if( strcmp( entry->Name, "header"   ) == 0 ) { Head.insert( Head.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+        else if( entry->Name[0] == '%' )                  { Assigns.push_back( new Assignment( entry->Name + 1 /* skip the %*/, q->Sequence ) ); return true; }
+        ParseError = PARSE_UNKNWON_ENTRY;
+        return false;
+    }
+    bool Done()    
+    { 
+        FL.Add( Inport, Message, Channels, minA, maxA, minB, maxB, Head, Sequence1, Sequence2, Sequence3, Assigns );
+        return true; 
+    }
+};
+
+const char keywords_flag[] = "channels";
+const char keywords_nums[] = "valueA valueB program";
+const char keywords_nu14[] = "parameter data bank";
+const char keywords_mess[] = "input1 input2 input3";
+const char keywords_sequ[] = "output1 output2 output3 header";
+
+bool Parse()
+{
+    char Line1[256];
+    char Line2[256];
+    LocalFileSystem local("local");
+    FILE* f = fopen( "/local/filter.txt", "r" );
+    if( f == NULL )
+    {
+        ParseError = PARSE_NO_FILE;
+        return false;
+    }
+    ParseRoute* pr = NULL;
+    ParseLine = 0;
+    while( /* ( ParseLine < 200 ) && */ fgets( Line1, 256, f ) )
+    {
+        ParseLine++;
+        ParseEntry* sp = NULL;
+
+        ParseCleanUp( Line1, Line2 );
+        strtok( Line2, ":" );
+
+        if( Line2[0] == 0 || Line2[0] == 10 ) continue;
+
+        if( strcmp( Line2, "ROUTE"      ) == 0 ) { 
+            if( pr ) if( ! pr->Done() ) goto Bad;     
+            delete pr;
+            pr = NULL;
+            int mem =  AvailableMemory();
+            if( mem < 512 ) { printf("Only %d bytes left for program.\nFilter definitions reading stopped at line %d\n", mem, ParseLine ); break; }
+            pr = new ParseRoute();
+        }
+        else if( strstr( keywords_flag, Line2 ) )      sp = new ParseFlag(    Line2 );
+        else if( strstr( keywords_nums, Line2 ) )      sp = new ParseByte(    Line2 );
+        else if( strstr( keywords_nu14, Line2 ) )      sp = new ParseShort(   Line2 );
+        else if( strstr( keywords_mess, Line2 ) )      sp = new ParseMessage( Line2 );
+        else if( strstr( keywords_sequ, Line2 ) )      sp = new ParseSequence(Line2 );
+        else if( Line2[0] == '%' )                     sp = new ParseSequence(Line2 );
+        else { ParseError = PARSE_UNKNWON_ENTRY; goto Bad; }
+
+        if( sp != NULL )
+        {
+            if( pr == NULL )                          goto Bad;
+            if( ! sp->Parse( strtok( NULL, "\n" ) ) ) goto Bad;
+            if( ! pr->Add( sp ) )                     goto Bad;
+            delete sp;
+        }
+    }
+
+    if( pr ) if( ! pr->Done() ) goto Bad;
+
+    fclose( f );
+    return true;
+Bad:
+    if( f != NULL ) fclose(f);
+    return false;
+}
+
+#undef abort
+#undef TOKEN_END
+#undef TOKEN_NUM
+#undef TOKEN_LOW
+#undef TOKEN_UPP
+#undef TOKEN_LOX
+#undef TOKEN_UPX
+
+#endif
\ No newline at end of file