#include "KSGSLeser.h" #include #include "../Error/Error.h" #include "KSGSCompile.h" #include "../Befehl/KSGSKlasse.h" #include "../Klassen/KSGSTyp.h" #include "../Funktionen/KSGSRückruf.h" #include "../Main/KSGScriptObj.h" using namespace KSGScript; void KSGScript::removeLehr( Text *txt ) { if( !txt->getLength() ) return; while( txt->getLength() && ( *txt[ 0 ] == ' ' || *txt[ 0 ] == '\n' || *txt[ 0 ] == '\r' || *txt[ 0 ] == '\t' ) ) txt->remove( 0 ); while( txt->getLength() && ( txt->getText()[ txt->getLength() - 1 ] == ' ' || txt->getText()[ txt->getLength() - 1 ] == '\n' || txt->getText()[ txt->getLength() - 1 ] == '\r' || txt->getText()[ txt->getLength() - 1 ] == '\t' ) ) txt->remove( txt->getLength() - 1 ); } void KSGScript::removeKlammer( Text *txt ) { if( !txt->getLength() ) return; removeLehr( txt ); while( *txt[ 0 ] == '(' && txt->getText()[ txt->getLength() - 1 ] == ')' ) { int count = 0; for( int i = 0; i < txt->getLength(); i++ ) { if( txt->getText()[ i ] == '(' ) count++; if( txt->getText()[ i ] == ')' ) count--; if( !count && i != txt->getLength() - 1 ) return; } txt->remove( 0 ); txt->remove( txt->getLength() - 1 ); removeLehr( txt ); if( !txt->getLength() ) return; } } int KSGScript::hatOperator( Text *txt ) { if( txt->hat( "+=" ) ) return KSGS_O_PLUSSET; if( txt->hat( "-=" ) ) return KSGS_O_MINUSSET; if( txt->hat( "*=" ) ) return KSGS_O_MAHLSET; if( txt->hat( "/=" ) ) return KSGS_O_GETEILTSET; if( txt->hat( "&=" ) ) return KSGS_O_UNDSET; if( txt->hat( "|=" ) ) return KSGS_O_ODERSET; if( txt->hat( "==" ) ) return KSGS_O_GLEICH; if( txt->hat( "<=" ) ) return KSGS_O_KLEINERGLEICH; if( txt->hat( ">=" ) ) return KSGS_O_GRÖßERGLEICH; if( txt->hat( "!=" ) ) return KSGS_O_UNGLEICH; if( txt->hat( "||" ) ) return KSGS_O_ODER; if( txt->hat( "&&" ) ) return KSGS_O_UND; if( txt->hat( "++" ) ) return KSGS_O_PLUS1; if( txt->hat( "--" ) ) return KSGS_O_MINUS1; if( txt->hat( "<<" ) ) return KSGS_O_NACHLINKS; if( txt->hat( ">>" ) ) return KSGS_O_NACHRECHTS; if( txt->hat( "=" ) ) return KSGS_O_SET; if( txt->hat( "<" ) ) return KSGS_O_KLEINER; if( txt->hat( ">" ) ) return KSGS_O_GRÖßER; if( txt->hat( "|" ) ) return KSGS_O_BITODER; if( txt->hat( "&" ) ) return KSGS_O_BITUND; if( txt->hat( "+" ) ) return KSGS_O_PLUS; if( txt->hat( "-" ) ) return KSGS_O_MINUS; if( txt->hat( "*" ) ) return KSGS_O_MAHL; if( txt->hat( "/" ) ) return KSGS_O_GETEILT; if( txt->hat( "%" ) ) return KSGS_O_REST; if( txt->hat( "!" ) ) return KSGS_O_NICHT; if( txt->hat( "~" ) ) return KSGS_O_BITNICHT; return -1; } int KSGScript::getOperatorPos( Text *txt, int *län ) { *län = 2; if( txt->hat( "+=" ) ) return txt->positionVon( "+=" ); if( txt->hat( "-=" ) ) return txt->positionVon( "-=" ); if( txt->hat( "*=" ) ) return txt->positionVon( "*=" ); if( txt->hat( "/=" ) ) return txt->positionVon( "/=" ); if( txt->hat( "&=" ) ) return txt->positionVon( "&=" ); if( txt->hat( "|=" ) ) return txt->positionVon( "|=" ); if( txt->hat( "==" ) ) return txt->positionVon( "==" ); if( txt->hat( "<=" ) ) return txt->positionVon( "<=" ); if( txt->hat( ">=" ) ) return txt->positionVon( ">=" ); if( txt->hat( "!=" ) ) return txt->positionVon( "!=" ); if( txt->hat( "||" ) ) return txt->positionVon( "||" ); if( txt->hat( "&&" ) ) return txt->positionVon( "&&" ); if( txt->hat( "++" ) ) return txt->positionVon( "++" ); if( txt->hat( "--" ) ) return txt->positionVon( "--" ); if( txt->hat( "<<" ) ) return txt->positionVon( "<<" ); if( txt->hat( ">>" ) ) return txt->positionVon( ">>" ); *län = 1; if( txt->hat( "=" ) ) return txt->positionVon( "=" ); if( txt->hat( "<" ) ) return txt->positionVon( "<" ); if( txt->hat( ">" ) ) return txt->positionVon( ">" ); if( txt->hat( "|" ) ) return txt->positionVon( "|" ); if( txt->hat( "&" ) ) return txt->positionVon( "&" ); if( txt->hat( "+" ) ) return txt->positionVon( "+" ); if( txt->hat( "-" ) ) return txt->positionVon( "-" ); if( txt->hat( "*" ) ) return txt->positionVon( "*" ); if( txt->hat( "/" ) ) return txt->positionVon( "/" ); if( txt->hat( "%" ) ) return txt->positionVon( "%" ); if( txt->hat( "!" ) ) return txt->positionVon( "!" ); if( txt->hat( "~" ) ) return txt->positionVon( "~" ); *län = 0; return -1; } // Lese Strukturen KSGSLeseBefehl::~KSGSLeseBefehl() { int anz = listA.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) delete listA.get( i ); anz = listB.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) delete listB.get( i ); } void KSGSLeseFunktion::release() { if( !--ref ) delete this; } KSGSLeseFunktion::~KSGSLeseFunktion() { int anz3 = parameter.getEintragAnzahl(); for( int k = 0; k < anz3; k++ ) delete parameter.get( k ); anz3 = befehle.getEintragAnzahl(); for( int k = 0; k < anz3; k++ ) delete befehle.get( k ); } void KSGSLeseKlasse::release() { if( !--ref ) delete this; } KSGSLeseKlasse::~KSGSLeseKlasse() { int anz2 = variablen.getEintragAnzahl(); for( int j = 0; j < anz2; j++ ) delete variablen.get( j ); anz2 = funktionen.getEintragAnzahl(); for( int j = 0; j < anz2; j++ ) funktionen.get( j )->release(); } KSGSLeseScript::~KSGSLeseScript() { int anz = variablen.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) delete variablen.get( i ); anz = funktionen.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) funktionen.get( i )->release(); anz = klassen.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) klassen.get( i )->release(); } // Inhalt der KSGSLeser klasse aus KSGSLeser.h // Konstruktor KSGSLeser::KSGSLeser( const char *pfad, KSGScriptO *zObj ) : KSGSLeser() { this->zObj = zObj; this->pfad = new Text( pfad ); } // Destruktor KSGSLeser::~KSGSLeser() { delete dat; if( pfad ) pfad->release(); } // protected KSGSLeser::KSGSLeser() { errorIgnore = 0; this->zObj = 0; d = 0; dat = 0; this->pfad = 0; zeile = 0; mainFuncId = -1; mausFuncId = -1; tastaturFuncId = -1; tickFuncId = -1; renderFuncId = -1; ref = 1; } void KSGSLeser::handleError( int beginn, int ende ) {} void KSGSLeser::handleKommentar( int beginn, int ende ) {} void KSGSLeser::handleString( int beginn, int ende ) {} // Script Laden bool KSGSLeser::ladeDatei() { bool ok = 1; Datei *datei = new Datei(); datei->setDatei( *pfad ); if( !datei->open( Datei::Style::lesen ) ) { datei->release(); error( 4, { *pfad }, zObj ); return 0; } d = datei; zeile = 1; while( !d->istEnde() ) { bool br = 0; int id = leseNext(); switch( id ) { case -1: // Ende der Datei break; case 1: // Klasse if( 1 ) { KSGSLeseKlasse *k = leseKlasse(); if( !k ) { error( 6, { "Klasse", *pfad }, zObj ); br = 1; } else dat->klassen.add( k ); } break; case 2: // funktion if( 1 ) { KSGSLeseFunktion *f = leseFunktion(); if( !f ) { error( 6, { "Funktion", *pfad }, zObj ); br = 1; } else dat->funktionen.add( f ); } break; case 3: // Variable if( 1 ) { KSGSLeseVariable *v = leseVariable(); if( !v ) { error( 6, { "Variable", *pfad }, zObj ); br = 1; } else dat->variablen.add( v ); } break; case 12: // lesen if( 1 ) { if( !leseBis( '(' ) ) { error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } d->setLPosition( d->getLPosition() + 1, 0 ); if( !leseBis( '"' ) ) { error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } d->setLPosition( d->getLPosition() + 1, 0 ); __int64 end = nextPosOf( '"', 0 ); if( end < 0 ) { error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } char *datei = new char[ (int)( end - d->getLPosition() ) + 1 ]; datei[ end - d->getLPosition() ] = 0; d->lese( datei, (int)( end - d->getLPosition() ) ); Text *dPf = zObj->convertPfad( datei ); delete[] datei; if( !leseBis( ')' ) ) { error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } d->setLPosition( d->getLPosition() + 1, 0 ); Text *pf = new Text( pfad->getText() ); pfad->setText( dPf ); Reader *tmp = d; if( !ladeDatei() ) { d = tmp; pfad->setText( pf ); error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } d = tmp; pfad->setText( pf ); } break; default: // Fehler error( 5, { *pfad, Text() += zeile }, zObj ); br = 1; break; } if( id == -1 ) break; if( br ) { ok = 0; break; } } datei->close(); d = datei->release(); return ok; } bool KSGSLeser::leseBis( char c ) { __int64 pos = d->getLPosition(); int tmpZ = zeile; char byte = 0; bool kommentar = 0; int kBeg = 0; bool slash = 0; bool gefunden = 0; bool inString = 0; bool inChar = 0; int sBeg = 0; while( !d->istEnde() ) { d->lese( &byte, 1 ); if( byte == '\n' ) { zeile++; if( kommentar ) handleKommentar( kBeg, (int)d->getLPosition() ); kommentar = 0; continue; } if( byte == '"' && !inChar && !kommentar ) { if( inString ) handleString( sBeg, (int)d->getLPosition() ); inString = !inString; sBeg = (int)d->getLPosition() - 1; } if( byte == '\'' && !inString && !kommentar ) { if( inChar ) handleString( sBeg, (int)d->getLPosition() ); inChar = !inChar; sBeg = (int)d->getLPosition() - 1; } if( byte == '#' ) { kBeg = (int)d->getLPosition() - 1; kommentar = 1; continue; } if( byte == '/' ) { if( slash ) { kBeg = (int)d->getLPosition() - 2; kommentar = 1; slash = 0; } else slash = 1; continue; } else slash = 0; if( byte == c && !kommentar ) { gefunden = 1; break; } } if( d->istEnde() && !gefunden ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); d->setLPosition( pos, 0 ); zeile = tmpZ; return 0; } d->setLPosition( d->getLPosition() - 1, 0 ); return 1; } __int64 KSGSLeser::nextPosOf( char c, char c2 ) { __int64 pos = d->getLPosition(); char byte = 0; bool kommentar = 0; int kBeg = 0; bool slash = 0; int count = 0; bool gefunden = 0; bool inString = 0; bool inChar = 0; int sBeg = 0; while( !d->istEnde() ) { d->lese( &byte, 1 ); if( byte == '\n' ) { if( kommentar ) handleKommentar( kBeg, (int)d->getLPosition() ); kommentar = 0; continue; } if( byte == '"' && !inChar && !kommentar ) { if( inString ) handleString( sBeg, (int)d->getLPosition() ); inString = !inString; sBeg = (int)d->getLPosition() - 1; } if( byte == '\'' && !inString && !kommentar ) { if( inChar ) handleString( sBeg, (int)d->getLPosition() ); inChar = !inChar; sBeg = (int)d->getLPosition() - 1; } if( byte == '#' ) { kBeg = (int)d->getLPosition() - 1; kommentar = 1; continue; } if( byte == '/' ) { if( slash ) { kBeg = (int)d->getLPosition() - 2; kommentar = 1; slash = 0; } else slash = 1; continue; } else slash = 0; if( !kommentar ) { if( byte == c2 ) { count++; continue; } if( byte == c ) { if( !count ) { gefunden = 1; break; } count--; continue; } } } if( d->istEnde() && !gefunden ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); d->setLPosition( pos, 0 ); return -1; } __int64 ret = d->getLPosition() - 1; d->setLPosition( pos, 0 ); return ret; } bool KSGSLeser::leseBisText() { __int64 pos = d->getLPosition(); char c = 0; bool kommentar = 0; int kBeg = 0; bool slash = 0; bool gefunden = 0; bool inString = 0; bool inChar = 0; int sBeg = 0; while( !d->istEnde() ) { d->lese( &c, 1 ); if( c == '\n' ) { zeile++; if( kommentar ) handleKommentar( kBeg, (int)d->getLPosition() ); kommentar = 0; continue; } if( c == '"' && !inChar && !kommentar ) { if( inString ) handleString( sBeg, (int)d->getLPosition() ); inString = !inString; sBeg = (int)d->getLPosition() - 1; } if( c == '\'' && !inString && !kommentar ) { if( inChar ) handleString( sBeg, (int)d->getLPosition() ); inChar = !inChar; sBeg = (int)d->getLPosition() - 1; } if( c == '#' ) { kBeg = (int)d->getLPosition() - 1; kommentar = 1; continue; } if( c == '/' ) { if( slash ) { kBeg = (int)d->getLPosition() - 2; kommentar = 1; slash = 0; } else slash = 1; continue; } else slash = 0; if( !istLehr( c ) && !kommentar ) { gefunden = 1; break; } } if( d->istEnde() && !gefunden ) { d->setLPosition( pos, 0 ); return 0; } d->setLPosition( d->getLPosition() - 1, 0 ); return 1; } int KSGSLeser::leseNext() { if( !leseBisText() ) return -1; __int64 pos = d->getLPosition(); int ret = 0; Text txt = ""; char byte[] = { 0, 0 }; d->lese( byte, 1 ); while( !istTrenner( byte[ 0 ] ) && !d->istEnde() ) { txt.append( byte ); d->lese( byte, 1 ); } if( d->istEnde() || !txt.getLength() ) { d->setLPosition( pos, 0 ); return -1; } if( txt.istGleich( "class" ) ) ret = 1; if( txt.istGleich( "func" ) ) ret = 2; if( txt.istGleich( "var" ) ) ret = 3; if( txt.istGleich( "public" ) ) ret = 4; if( txt.istGleich( "private" ) ) ret = 5; if( txt.istGleich( "if" ) ) ret = 6; if( txt.istGleich( "for" ) ) ret = 7; if( txt.istGleich( "while" ) ) ret = 8; if( txt.istGleich( "return" ) ) ret = 9; if( txt.istGleich( "break" ) ) ret = 10; if( txt.istGleich( "continue" ) ) ret = 11; if( txt.istGleich( "lesen" ) ) ret = 12; d->setLPosition( pos, 0 ); return ret; } bool KSGSLeser::istTrenner( char c ) { return !( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || ( c >= '0' && c <= '9' ) || c == '_' || c == 'ä' || c == 'ö' || c == 'ü' || c == 'Ä' || c == 'Ö' || c == 'Ü' || c == 'ß' ); } bool KSGSLeser::istLehr( char c ) { return c == ' ' || c == '\n' || c == '\r' || c == '\t'; } KSGSLeseKlasse *KSGSLeser::leseKlasse() { KSGSLeseKlasse *ret = new KSGSLeseKlasse(); ret->debug.datei.setText( *pfad ); ret->debug.zeile = zeile; d->setLPosition( d->getLPosition() + 5, 0 ); // 'class' überspringen if( !leseBisText() ) // Bis zum beginn des Klassennamens lesen { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); ret->release(); return 0; } char byte[] = { 0, 0 }; // Klassenname lesen d->lese( byte, 1 ); while( !istTrenner( *byte ) ) { ret->name.append( byte ); d->lese( byte, 1 ); } if( !leseBis( '{' ) ) // Bis zum beginn der Klasse lesen { ret->release(); return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); bool sichtbar = 0; __int64 ende = nextPosOf( '}', '{' ); // Ende der Klasse if( ende < 0 ) { ret->release(); return 0; } while( d->getLPosition() < ende ) // Inhalt der Klasse lesen { int id = leseNext(); if( id == -1 ) break; switch( id ) { case 2: // Funktion if( 1 ) { KSGSLeseFunktion *f = leseFunktion(); if( !f ) { ret->release(); return 0; } ret->funktionen.add( f ); ret->fSichtbar.add( sichtbar ); } break; case 3: // Variable if( 1 ) { KSGSLeseVariable *v = leseVariable(); if( !v ) { ret->release(); return 0; } ret->variablen.add( v ); ret->vSichtbar.add( sichtbar ); } break; case 4: // public sichtbar = 1; d->setLPosition( d->getLPosition() + 6, 0 ); if( !leseBis( ':' ) ) { ret->release(); return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); break; case 5: // private sichtbar = 0; d->setLPosition( d->getLPosition() + 7, 0 ); if( !leseBis( ':' ) ) { ret->release(); return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); break; default: ret->release(); return 0; } } if( d->getLPosition() > ende ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); ret->release(); return 0; } d->setLPosition( ende + 1, 0 ); if( !leseBis( ';' ) ) // ';' Nach einer Klasse überlesen { ret->release(); return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); return ret; } KSGSLeseFunktion *KSGSLeser::leseFunktion() { KSGSLeseFunktion *ret = new KSGSLeseFunktion(); ret->debug.datei.setText( *pfad ); ret->debug.zeile = zeile; d->setLPosition( d->getLPosition() + 4, 0 ); // 'func' überspringen if( !leseBisText() ) { ret->release(); return 0; } char byte[] = { 0, 0 }; // Rückgabetyp der Funktion lesen d->lese( byte, 1 ); while( !istTrenner( *byte ) ) { ret->typ.append( byte ); d->lese( byte, 1 ); } d->setLPosition( d->getLPosition() - 1, 0 ); if( !leseBisText() ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); ret->release(); return 0; } d->lese( byte, 1 ); // Name der Funktion lesen while( !istTrenner( *byte ) ) { ret->name.append( byte ); d->lese( byte, 1 ); } d->setLPosition( d->getLPosition() - 1, 0 ); if( !leseBis( '(' ) ) // Parameterbeginn { ret->release(); return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); __int64 paramEnde = nextPosOf( ')', '(' ); if( paramEnde < 0 ) { ret->release(); return 0; } while( d->getLPosition() < paramEnde ) { KSGSLeseVariable *param = leseVariable( 1 ); // Übergabeparameter einlesen if( !param ) break; ret->parameter.add( param ); } d->setLPosition( paramEnde + 1, 0 ); if( !leseBis( '{' ) ) // Funktionsrumpf beginn { ret->release(); return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); __int64 funkEnde = nextPosOf( '}', '{' ); // Ende der Funktion if( funkEnde < 0 ) { ret->release(); return 0; } while( d->getLPosition() < funkEnde ) { KSGSLeseBefehl *bef = leseBefehl(); // Befehle einlesen if( !bef ) break; else ret->befehle.add( bef ); if( !leseBisText() ) { ret->release(); return 0; } } d->setLPosition( funkEnde + 1, 0 ); // '}' am ende der Funktion überlesen return ret; } KSGSLeseVariable *KSGSLeser::leseVariable( bool param ) { KSGSLeseVariable *ret = new KSGSLeseVariable(); ret->debug.datei.setText( *pfad ); ret->debug.zeile = zeile; if( !param ) d->setLPosition( d->getLPosition() + 3, 0 ); // 'var' überspringen __int64 endPos = 0; if( param ) { endPos = nextPosOf( ')', 0 ); if( endPos < 0 ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); delete ret; return 0; } } if( !leseBisText() ) { delete ret; return 0; } if( param && d->getLPosition() >= endPos ) { delete ret; return 0; } char byte[] = { 0, 0 }; // Variablentyp lesen d->lese( byte, 1 ); while( !istTrenner( *byte ) ) { ret->typ.append( byte ); d->lese( byte, 1 ); } d->setLPosition( d->getLPosition() - 1, 0 ); if( !leseBisText() ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); delete ret; return 0; } d->lese( byte, 1 ); // Variablenname lesen while( !istTrenner( *byte ) ) { ret->name.append( byte ); d->lese( byte, 1 ); } d->setLPosition( d->getLPosition() - 1, 0 ); __int64 ende = nextPosOf( ';', 0 ); if( ende < 0 ) { delete ret; return 0; } if( param ) { errorIgnore = 1; __int64 tmp = nextPosOf( ',', 0 ); errorIgnore = 0; if( tmp >= 0 && tmp < endPos ) ende = tmp; else ende = endPos; } errorIgnore = 1; __int64 gleich = nextPosOf( '=', 0 ); errorIgnore = 0; if( gleich < ende && gleich >= 0 ) // prüfen ob die variable gesetzt wird { if( !leseBis( '=' ) ) { delete ret; return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); } if( leseBisText() ) { if( d->getLPosition() < ende ) { while( d->getLPosition() < ende ) // Wert der Variable lesen { d->lese( byte, 1 ); ret->wert.append( byte ); } } } while( istLehr( ret->wert.getText()[ ret->wert.getLength() - 1 ] ) && ret->wert.getLength() > 0 ) { if( ret->wert.getText()[ ret->wert.getLength() - 1 ] == '\n' ) zeile++; if( !( ret->wert.getLength() - 1 ) ) { ret->wert.setText( "" ); break; } ret->wert.setText( ret->wert.getText(), ret->wert.getLength() - 1 ); } if( d->getLPosition() > ende ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); delete ret; return 0; } d->setLPosition( ende + 1, 0 ); // ';' oder bei param ')' oder ',' am Ende überlesen return ret; } KSGSLeseBefehl *KSGSLeser::leseBefehl() { __int64 fEnde = nextPosOf( '}', '{' ); if( fEnde < 0 ) return 0; int typ = leseNext(); if( typ < 0 ) return 0; KSGSLeseBefehl *ret = new KSGSLeseBefehl(); ret->debug.datei.setText( *pfad ); ret->debug.zeile = zeile; ret->typ = typ; switch( typ ) { case 0: case 3: // var if( 1 ) { __int64 endPos = nextPosOf( ';', 0 ); if( endPos < 0 ) { delete ret; return 0; } int län = (int)( endPos - d->getLPosition() ); if( län ) { char *txt = new char[ län + 1 ]; txt[ län ] = 0; d->lese( txt, län ); ret->befehl = txt; delete[] txt; } d->setLPosition( endPos + 1, 0 ); } break; case 6: // if if( 1 ) { if( !leseBis( '(' ) ) { delete ret; return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); __int64 endPos = nextPosOf( ')', '(' ); if( endPos < 0 ) { delete ret; return 0; } int län = (int)( endPos - d->getLPosition() ); if( län ) { char *txt = new char[ län + 1 ]; txt[ län ] = 0; d->lese( txt, län ); ret->befehl = txt; delete[] txt; } d->setLPosition( endPos + 1, 0 ); if( !leseBis( '{' ) ) { delete ret; return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); endPos = nextPosOf( '}', '{' ); if( endPos < 0 ) { delete ret; return 0; } while( d->getLPosition() < endPos ) { KSGSLeseBefehl *tmp = leseBefehl(); if( !tmp ) break; else ret->listA.add( tmp ); } d->setLPosition( endPos + 1, 0 ); int tmpZ = zeile; if( !leseBisText() ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); delete ret; return 0; } char *el = new char[ 5 ]; if( d->getLPosition() + 4 <= fEnde ) d->lese( el, 4 ); else el[ 0 ] = 0; el[ 4 ] = 0; if( Text( "else" ).istGleich( el ) ) { if( !leseBis( '{' ) ) { delete ret; return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); endPos = nextPosOf( '}', '{' ); if( endPos < 0 ) { delete ret; return 0; } while( d->getLPosition() < endPos ) { KSGSLeseBefehl *tmp = leseBefehl(); if( !tmp ) break; else ret->listB.add( tmp ); } d->setLPosition( endPos + 1, 0 ); } else { d->setLPosition( endPos + 1, 0 ); zeile = tmpZ; } delete[] el; } break; case 7: // for case 8: // while if( 1 ) { if( !leseBis( '(' ) ) { delete ret; return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); __int64 endPos = nextPosOf( ')', '(' ); if( endPos < 0 ) { delete ret; return 0; } int län = (int)( endPos - d->getLPosition() ); if( län ) { char *txt = new char[ län + 1 ]; txt[ län ] = 0; d->lese( txt, län ); ret->befehl = txt; delete[] txt; } d->setLPosition( endPos + 1, 0 ); if( !leseBis( '{' ) ) { delete ret; return 0; } d->setLPosition( d->getLPosition() + 1, 0 ); endPos = nextPosOf( '}', '{' ); if( endPos < 0 ) { delete ret; return 0; } while( d->getLPosition() < endPos ) { KSGSLeseBefehl *tmp = leseBefehl(); if( !tmp ) break; else ret->listA.add( tmp ); } d->setLPosition( endPos + 1, 0 ); } break; case 9: // return if( 1 ) { __int64 endPos = nextPosOf( ';', 0 ); if( endPos < 0 ) { delete ret; return 0; } int län = (int)( endPos - d->getLPosition() ); if( län ) { char *txt = new char[ län + 1 ]; txt[ län ] = 0; d->lese( txt, län ); ret->befehl = txt; delete[] txt; } d->setLPosition( endPos + 1, 0 ); } break; case 10: // break case 11: // continue if( 1 ) { __int64 endPos = nextPosOf( ';', 0 ); if( endPos < 0 ) { delete ret; return 0; } d->setLPosition( endPos + 1, 0 ); } break; default: handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); delete ret; return 0; } if( d->getLPosition() > fEnde ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); delete ret; return 0; } ret->befehl.ersetzen( "->", "." ); return ret; } // Script Compilieren bool KSGSLeser::compileKlasse( KSGSLeseKlasse *zLK, KSGSCompKlassTable *zKT ) { if( !zKT->hat( (char*)zLK->name ) ) { error( 10, {}, zObj ); return 0; } KSGSCompileKlasse *k = zKT->get( (char*)zLK->name ); int lFAnz = zLK->funktionen.getEintragAnzahl(); for( int i = 0; i < lFAnz; i++ ) { if( !compileFunktion( zLK->funktionen.get( i ), zKT, &k->funcs, 1 + !zLK->fSichtbar.get( i ) ) ) return 0; } k->vars.addVariable( "this", new KSGSCompileVariable( k->id, 2 ) ); int lVAnz = zLK->variablen.getEintragAnzahl(); for( int i = 0; i < lVAnz; i++ ) { auto tmp = zKT->get( (char*)zLK->variablen.get( i )->typ ); if( !tmp ) { error( 11, { zLK->debug.datei, Text() += zLK->debug.zeile, (char*)zLK->variablen.get( i )->typ, (char*)zLK->variablen.get( i )->name }, zObj ); return 0; } if( !k->vars.addVariable( zLK->variablen.get( i )->name, new KSGSCompileVariable( tmp->id, 1 + !zLK->vSichtbar.get( i ) ) ) ) { error( 9, { zLK->variablen.get( i )->debug.datei, Text() += zLK->variablen.get( i )->debug.zeile, zLK->variablen.get( i )->name }, zObj ); return 0; } } return 1; } bool KSGSLeser::compileFunktion( KSGSLeseFunktion *zLF, KSGSCompKlassTable *zKT, KSGSCompFuncTable *zFT, int s ) { KSGSCompileFunktion *f = new KSGSCompileFunktion( zKT->get( (char*)zLF->typ )->id, s, {} ); int anz = zLF->parameter.getEintragAnzahl(); for( int j = 0; j < anz; j++ ) { auto tmp = zKT->get( (char*)zLF->parameter.get( j )->typ ); if( tmp ) f->parameterTyp.add( tmp->id ); else { error( 11, { zLF->debug.datei, Text() += zLF->debug.zeile, zLF->parameter.get( j )->typ, zLF->parameter.get( j )->name }, zObj ); return 0; } } if( !zFT->addFunktion( zLF->name, f ) ) { error( 8, { zLF->debug.datei, Text() += zLF->debug.zeile, zLF->name }, zObj ); return 0; } return 1; } KSGSVariableDef *KSGSLeser::compileVariable( KSGSLeseVariable *zLV, KSGSCompKlassTable *zKT, int id ) { if( !zKT->hat( (char*)zLV->typ ) ) { error( 11, { zLV->debug.datei, Text() += zLV->debug.zeile, zLV->typ, zLV->name }, zObj ); return 0; } KSGSVariableDef *ret = new KSGSVariableDef(); ret->id = id; ret->sichtbar = 0; ret->typId = zKT->get( (char*)zLV->typ )->id; ret->wert.setText( zLV->wert ); return ret; } KSGSKlasse *KSGSLeser::buildKlasse( KSGSLeseKlasse *zLK, KSGSCompKlassTable *zKT, KSGSCompFuncTable *zFT, KSGSCompVarTable *zVT ) { if( !zKT->hat( (char*)zLK->name ) ) { error( 10, {}, zObj ); return 0; } KSGSKlasse *ret = new KSGSKlasse( zKT->get( (char*)zLK->name )->id ); int anz = zLK->funktionen.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { KSGSFunktion *f = buildFunktion( zLK->funktionen.get( i ), zKT, zFT, zVT, zLK->name ); if( !f ) { ret->release(); return 0; } ret->addFunktion( f ); } anz = zLK->variablen.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { KSGSVariableDef *v = compileVariable( zLK->variablen.get( i ), zKT, i ); if( !v ) { ret->release(); return 0; } v->sichtbar = 1 + !zLK->vSichtbar.get( i ); ret->addVariable( v ); } return ret; } KSGSFunktion *KSGSLeser::buildFunktion( KSGSLeseFunktion *zLF, KSGSCompKlassTable *zKT, KSGSCompFuncTable *zFT, KSGSCompVarTable *zVT, const char *klassName ) { KSGSCompFuncTable *ft = zFT; if( klassName ) ft = &zKT->get( klassName )->funcs; if( !ft->hat( zLF->name ) ) { error( 10, {}, zObj ); return 0; } KSGSFunktion *ret = new KSGSFunktion( ft->get( zLF->name )->id, ft->get( zLF->name )->sichtbar, zKT->get( (char*)zLF->typ )->id ); ret->setName( zLF->name ); int anz = zLF->parameter.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { KSGSVariableDef *v = compileVariable( zLF->parameter.get( i ), zKT, i ); if( !v ) { ret->release(); return 0; } v->sichtbar = 3; ret->addParameter( v ); auto tmp = zKT->get( (char*)zLF->parameter.get( i )->typ ); if( !tmp ) { error( 11, { zLF->debug.datei, Text() += zLF->debug.zeile, zLF->parameter.get( i )->typ, zLF->parameter.get( i )->name }, zObj ); return 0; } ft->get( zLF->name )->vars.addVariable( zLF->parameter.get( i )->name, new KSGSCompileVariable( tmp->id, 3 ) ); } anz = zLF->befehle.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { KSGSBefehl *b = buildBefehl( zLF->befehle.get( i ), zKT, zFT, zVT, klassName, zLF->name ); if( !b ) { ret->release(); return 0; } ret->addBefehl( b ); } return ret; } KSGSBefehl *KSGSLeser::buildBefehl( KSGSLeseBefehl *zLB, KSGSCompKlassTable *zKT, KSGSCompFuncTable *zFT, KSGSCompVarTable *zVT, const char *klassName, const char *funktionName ) { KSGSBefehl *ret = 0; zLB->befehl.setSuchGrenzen( '(', ')' ); removeKlammer( &zLB->befehl ); switch( zLB->typ ) { case 0: // call oder operator if( 1 ) { if( hatOperator( &zLB->befehl ) >= 0 ) ret = new KSGSOperatorBefehl( zObj, zLB, zKT, zFT, zVT, klassName, funktionName ); else ret = new KSGSCallBefehl( zObj, zLB, zKT, zFT, zVT, klassName, funktionName ); } break; case 3: // var ret = new KSGSVariableBefehl( zObj, zLB, zKT, zFT, zVT, klassName, funktionName ); break; case 6: // if ret = new KSGSIfBefehl( zObj, zLB, zKT, zFT, zVT, klassName, funktionName ); break; case 7: // for ret = new KSGSForBefehl( zObj, zLB, zKT, zFT, zVT, klassName, funktionName ); break; case 8: // while ret = new KSGSWhileBefehl( zObj, zLB, zKT, zFT, zVT, klassName, funktionName ); break; case 9: // return ret = new KSGSReturnBefehl( zObj, zLB, zKT, zFT, zVT, klassName, funktionName ); break; case 10: // break ret = new KSGSBreakBefehl( zLB, zKT, zFT, zVT, klassName, funktionName ); break; case 11: // continue ret = new KSGSContinueBefehl( zLB, zKT, zFT, zVT, klassName, funktionName ); break; } if( !ret ) error( 13, { zLB->debug.datei, Text() += zLB->debug.zeile, zLB->befehl }, zObj ); if( ret && ret->hatFehler() ) ret = ret->release(); return ret; } // nicht constant bool KSGSLeser::laden() { delete dat; dat = new KSGSLeseScript(); bool ok = ladeDatei(); return ok; } bool KSGSLeser::compile( RCArray< KSGSKlasse > *klassen, RCArray< KSGSFunktion > *funktionen, Array< KSGSVariableDef* > *variablen ) { // Klassen Tabelle KSGSCompKlassTable *klassT = new KSGSCompKlassTable(); int kAnz = dat->klassen.getEintragAnzahl(); for( int i = 0; i < kAnz; i++ ) { if( !klassT->addKlasse( dat->klassen.get( i )->name, new KSGSCompileKlasse() ) ) { error( 7, { dat->klassen.get( i )->debug.datei, Text() += dat->klassen.get( i )->debug.zeile, dat->klassen.get( i )->name }, zObj ); klassT->release(); return 0; } } // Funktions Tabelle KSGSCompFuncTable *funcT = new KSGSCompFuncTable(); funcT->addFunktion( "Rückruf", new KSGSCompileFunktion( KSGS_VOID, 0, {} ) ); int fAnz = dat->funktionen.getEintragAnzahl(); for( int i = 0; i < fAnz; i++ ) { if( !compileFunktion( dat->funktionen.get( i ), klassT, funcT ) ) { error( 8, { dat->funktionen.get( i )->debug.datei, Text() += dat->funktionen.get( i )->debug.zeile, dat->funktionen.get( i )->name }, zObj ); klassT->release(); funcT->release(); return 0; } if( dat->funktionen.get( i )->name.istGleich( "start" ) ) mainFuncId = funcT->get( "start" )->id; if( dat->funktionen.get( i )->name.istGleich( "maus" ) ) mausFuncId = funcT->get( "maus" )->id; if( dat->funktionen.get( i )->name.istGleich( "tastatur" ) ) tastaturFuncId = funcT->get( "tastatur" )->id; if( dat->funktionen.get( i )->name.istGleich( "tick" ) ) tickFuncId = funcT->get( "tick" )->id; if( dat->funktionen.get( i )->name.istGleich( "render" ) ) renderFuncId = funcT->get( "render" )->id; } // Variablen Tabelle KSGSCompVarTable *varT = new KSGSCompVarTable(); int vAnz = dat->variablen.getEintragAnzahl(); for( int i = 0; i < vAnz; i++ ) { auto tmp = klassT->get( (char*)dat->variablen.get( i )->typ ); if( !tmp ) { error( 11, { dat->variablen.get( i )->debug.datei, Text() += dat->variablen.get( i )->debug.zeile, dat->variablen.get( i )->typ, dat->variablen.get( i )->name }, zObj ); return 0; } if( !varT->addVariable( dat->variablen.get( i )->name, new KSGSCompileVariable( klassT->get( (char*)dat->variablen.get( i )->typ )->id, 0 ) ) ) { error( 9, { dat->variablen.get( i )->debug.datei, Text() += dat->variablen.get( i )->debug.zeile, dat->variablen.get( i )->name }, zObj ); klassT->release(); funcT->release(); varT->release(); return 0; } } for( int i = 0; i < kAnz; i++ ) { if( !compileKlasse( dat->klassen.get( i ), klassT ) ) { klassT->release(); funcT->release(); varT->release(); return 0; } } for( int i = 0; i < vAnz; i++ ) { KSGSVariableDef *k = compileVariable( dat->variablen.get( i ), klassT, i ); if( !k ) { int anz = variablen->getEintragAnzahl(); for( int i = 0; i < anz; i++ ) delete variablen->get( i ); variablen->leeren(); klassT->release(); funcT->release(); varT->release(); return 0; } variablen->add( k ); } for( int i = 0; i < kAnz; i++ ) { KSGSKlasse *k = buildKlasse( dat->klassen.get( i ), klassT, funcT, varT ); if( !k ) { klassen->leeren(); variablen->leeren(); klassT->release(); funcT->release(); varT->release(); return 0; } klassen->add( k ); } funktionen->add( new KSGSRückrufFunktion() ); for( int i = 0; i < fAnz; i++ ) { KSGSFunktion *f = buildFunktion( dat->funktionen.get( i ), klassT, funcT, varT ); if( !f ) { klassen->leeren(); funktionen->leeren(); variablen->leeren(); klassT->release(); funcT->release(); varT->release(); return 0; } funktionen->add( f ); } klassT->release(); funcT->release(); varT->release(); return 1; } // constant int KSGSLeser::getMainFuncId() const { return mainFuncId; } int KSGSLeser::getMausFuncId() const { return mausFuncId; } int KSGSLeser::getTastaturFuncId() const { return tastaturFuncId; } int KSGSLeser::getTickFuncId() const { return tickFuncId; } int KSGSLeser::getRenderFuncId() const { return renderFuncId; } // Reference Counting KSGSLeser *KSGSLeser::getThis() { ref++; return this; } KSGSLeser *KSGSLeser::release() { ref--; if( !ref ) delete this; return 0; }