#ifndef NEURAL_NETWORK_H #define NEURAL_NETWORK_H #include "neural/node.h" #include "neural/column.h" #include "neural/container.h" #include "neural/row.h" #include "neural/neuron.h" #include #include namespace Neural { template class Network { public: Network() : pRoot( 0 ) { } virtual ~Network() { delete pRoot; } static Network *fromStr( const Bu::String &sCode ) { Network *pNet = new Network(); Bu::String::const_iterator i = sCode.begin(); pNet->pRoot = parseNode( i ); return pNet; } Node *getRoot() { return pRoot; } private: // Parser code enum TokenType { tokRow, tokColumn, tokNeuron, tokOpenParen, tokCloseParen, tokNumber, tokComma, tokEndOfInput }; static TokenType nextToken( Bu::String::const_iterator &i, int32_t &iValue ) { Bu::String sTmp; for(; i; i++ ) { switch( *i ) { case ' ': case '\t': case '\n': case '\r': continue; case ',': i++; //Bu::println("Token: tokComma"); return tokComma; case '(': i++; //Bu::println("Token: tokOpenParen"); return tokOpenParen; case ')': i++; //Bu::println("Token: tokCloseParen"); return tokCloseParen; default: if( (*i >= 'a' && *i <= 'z') || (*i >= 'A' && *i <= 'Z') ) { for(; i; i++ ) { if( (*i >= 'a' && *i <= 'z') || (*i >= 'A' && *i <= 'Z') ) { sTmp += *i; } else { //Bu::println("Read: '%1'").arg( sTmp ); sTmp = sTmp.toLower(); if( sTmp == "row" ) return tokRow; if( sTmp == "column" ) return tokColumn; if( sTmp == "neuron" ) return tokNeuron; throw Bu::ExceptionBase( Bu::String( "Invalid token discovered in input: %1" ).arg( sTmp ).end().getStr() ); } } } else if( *i >= '0' && *i <= '9' ) { for(; i; i++ ) { if( *i >= '0' && *i <= '9' ) { sTmp += *i; } else { //Bu::println("Read: '%1'").arg( sTmp ); iValue = strtol( sTmp.getStr(), NULL, 10 ); return tokNumber; } } } break; } } return tokEndOfInput; } static Node *parseNode( Bu::String::const_iterator &i ) { int iValue; TokenType eTok = nextToken( i, iValue ); Node *pNode = NULL; switch( eTok ) { case tokColumn: pNode = new Column(); parseNodeParams( (Column *)pNode, i ); break; case tokRow: pNode = new Row(); parseNodeParams( (Row *)pNode, i ); break; case tokNeuron: pNode = new Neuron(); break; default: throw Bu::ExceptionBase( "Unexpecetd token parsing neural net specifacion."); } return pNode; } static void parseNodeParams( Container *pParent, Bu::String::const_iterator &i ) { int iValue; TokenType eTok = nextToken( i, iValue ); if( eTok != tokOpenParen ) { throw Bu::ExceptionBase( "Unexpected token, expected open paren." ); } for(;;) { eTok = nextToken( i, iValue ); switch( eTok ) { case tokColumn: { Column *pNode = new Column(); parseNodeParams( pNode, i ); pParent->addNode( pNode ); } break; case tokRow: { Row *pNode = new Row(); parseNodeParams( pNode, i ); pParent->addNode( pNode ); } break; case tokNeuron: pParent->addNode( new Neuron() ); break; case tokNumber: for( int j = 0; j < iValue; j++ ) { pParent->addNode( new Neuron() ); } break; default: throw Bu::ExceptionBase( "Unexpecetd token parsing neural net specifacion."); } eTok = nextToken( i, iValue ); if( eTok == tokCloseParen ) return; else if( eTok == tokComma ) continue; else throw new Bu::ExceptionBase( "Unexpected token parsing neural net specification," " expected comma or close paren."); } } private: Node *pRoot; }; }; #endif