#include "ColorParser.h" using namespace KSGScript; const char* (ColorParser::keyword[]) = { "lesen", "var", "func", "Rückruf", "class", "public", "private", "if", "else", "return", "break", "continue", "for", "while" }; const int ColorParser::keywordAnz = 14; const char* (ColorParser::type[]) = { "void", "bool", "int", "double", "Array", "Thread", "Text", "Bild", "MausEreignis", "TastaturEreignis", "TextFeld", "Knopf", "Fenster", "BildZ", "Animation2DData", "Animation2D" }; const int ColorParser::typeAnz = 16; // Konstructor // zTxt: Der Text, der geparsed werden soll ColorParser::ColorParser( Text* zTxt ) : KSGSLeser() { txt = dynamic_cast(zTxt->getThis()); reset(); reload(); } // Destructor ColorParser::~ColorParser() { for( auto i : abschnitt ) { if( i.zFunktion ) i.zFunktion->release(); if( i.zKlasse ) i.zKlasse->release(); } txt->release(); } // behandelt einen Fehler void ColorParser::handleError( int begin, int ende ) { if( errorIgnore ) return; TextAbschnitt err; err.anfang = begin; err.ende = ende; error.add( err ); } void ColorParser::handleKommentar( int beginn, int ende ) { TextAbschnitt kom; kom.anfang = beginn; kom.ende = ende; kommentar.add( kom ); } void ColorParser::handleString( int beginn, int ende ) { TextAbschnitt str; str.anfang = beginn; str.ende = ende; string.add( str ); } // Setzt den Parsevorgang zum Beginn zurück void ColorParser::reset() { pos.inKeyword = 0; pos.inTypename = 0; pos.inParameter = 0; pos.inInstanzVar = 0; } // Lädt das Script neu void ColorParser::reload() { error.leeren(); string.leeren(); kommentar.leeren(); for( auto i : abschnitt ) { if( i.zFunktion ) i.zFunktion->release(); if( i.zKlasse ) i.zKlasse->release(); } abschnitt.leeren(); delete dat; dat = new KSGSLeseScript(); d = new TextReader( dynamic_cast(txt->getThis()) ); 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 = new Text( datei ); dPf->ersetzen( '\\', '/' ); if( dPf->getText()[ 0 ] == '/' ) dPf->remove( 0 ); else dPf->insert( 0, wd->getText() ); delete[] datei; if( !leseBis( ')' ) ) { //error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } d->setLPosition( d->getLPosition() + 1, 0 ); Text* pf = new Text( fileName ); fileName.setText( dPf ); Reader* tmp = d; if( !ladeDatei() ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); d = tmp; fileName.setText( pf ); //error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } d = tmp; fileName.setText( pf ); } break; default: // Fehler handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); //error( 5, { *pfad, Text() += zeile }, zObj ); br = 1; break; } if( id == -1 ) break; if( br ) { //ok = 0; break; } } d = (Reader*)((TextReader*)d)->release(); } KSGSLeseKlasse* ColorParser::leseKlasse() { Abschnitt abs; abs.anfang = (int)d->getLPosition(); KSGSLeseKlasse* ret = KSGSLeser::leseKlasse(); abs.ende = (int)d->getLPosition(); abs.zKlasse = ret; abs.zFunktion = 0; if( ret ) ret->ref++; abschnitt.add( abs ); return ret; } KSGSLeseFunktion* ColorParser::leseFunktion() { Abschnitt abs; abs.anfang = (int)d->getLPosition(); KSGSLeseFunktion* ret = KSGSLeser::leseFunktion(); abs.ende = (int)d->getLPosition(); abs.zKlasse = 0; abs.zFunktion = ret; if( ret ) ret->ref++; abschnitt.add( abs ); return ret; } // Gibt den Farbtyp des nächsten Zeichens zurück KSGScriptEditor::ColorType ColorParser::getNextColor( int p, int& underlineC ) { KSGScriptEditor::ColorType color = KSGScriptEditor::ColorType::NORMAL_TEXT; int scriptL = txt->getLength(); char cm1 = txt->getText()[ p - 1 ]; if( istLehr( cm1 ) || istTrenner( cm1 ) ) { pos.inKeyword = 0; pos.inTypename = 0; pos.inInstanzVar = 0; pos.inParameter = 0; } bool inString = 0; bool inKommentar = 0; for( auto i : string ) { if( i.anfang <= p && i.ende >= p ) inString = 1; } for( auto i : kommentar ) { if( i.anfang <= p && i.ende >= p ) inKommentar = 1; } if( !inString && !inKommentar ) { if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && istLehr( cm1 ) ) { for( int i = 0; i < keywordAnz; i++ ) { int kl = textLength( keyword[ i ] ); pos.inKeyword = 1; for( int j = 0; j < kl && j + p < scriptL && pos.inKeyword; j++ ) pos.inKeyword &= txt->getText()[ j + p ] == keyword[ i ][ j ]; if( pos.inKeyword && (kl + p == scriptL || istTrenner( txt->getText()[ kl + p ] )) ) break; pos.inKeyword = 0; } } if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && istLehr( cm1 ) ) { for( int i = 0; i < typeAnz; i++ ) { int tl = textLength( type[ i ] ); pos.inTypename = 1; for( int j = 0; j < tl && j + p < scriptL && pos.inTypename; j++ ) pos.inTypename &= txt->getText()[ j + p ] == type[ i ][ j ]; if( pos.inTypename && (tl + p == scriptL || istTrenner( txt->getText()[ tl + p ] )) ) break; pos.inTypename = 0; } if( !pos.inTypename && dat ) { int anz = dat->klassen.getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { int tl = dat->klassen.get( i )->name.getLength(); pos.inTypename = 1; for( int j = 0; j < tl && j + p < scriptL && pos.inTypename; j++ ) pos.inTypename &= txt->getText()[ j + p ] == dat->klassen.get( i )->name.getText()[ j ]; if( pos.inTypename && (tl + p == scriptL || istTrenner( txt->getText()[ tl + p ] )) ) break; pos.inTypename = 0; } } } if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && istLehr( cm1 ) ) { for( const Abschnitt& i : abschnitt ) { if( i.anfang <= p && i.ende >= p ) { if( i.zFunktion ) { int anz = i.zFunktion->parameter.getEintragAnzahl(); for( int j = 0; j < anz; j++ ) { int nl = i.zFunktion->parameter.get( j )->name.getLength(); pos.inParameter = 1; for( int k = 0; k < nl && k + p < scriptL && pos.inParameter; k++ ) pos.inParameter &= txt->getText()[ k + p ] == i.zFunktion->parameter.get( j )->name.getText()[ k ]; if( pos.inParameter && (nl + p == scriptL || istTrenner( txt->getText()[ nl + p ] )) ) break; pos.inParameter = 0; } } } } } if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && istLehr( cm1 ) ) { for( const Abschnitt& i : abschnitt ) { if( i.anfang <= p && i.ende >= p ) { if( i.zKlasse ) { int anz = i.zKlasse->variablen.getEintragAnzahl(); for( int j = 0; j < anz; j++ ) { int nl = i.zKlasse->variablen.get( j )->name.getLength(); pos.inInstanzVar = 1; for( int k = 0; k < nl && k + p < scriptL && pos.inInstanzVar; k++ ) pos.inInstanzVar &= txt->getText()[ k + p ] == i.zKlasse->variablen.get( j )->name.getText()[ k ]; if( pos.inInstanzVar && (nl + p == scriptL || istTrenner( txt->getText()[ nl + p ] )) ) break; pos.inInstanzVar = 0; } } } } } } if( pos.inKeyword ) color = KSGScriptEditor::ColorType::KEYWORD; if( pos.inTypename ) color = KSGScriptEditor::ColorType::TYPENAME; if( pos.inParameter ) color = KSGScriptEditor::ColorType::PARAMETER_VARIABLE; if( pos.inInstanzVar ) color = KSGScriptEditor::ColorType::INSTANCE_VARIABLE; if( inString ) color = KSGScriptEditor::ColorType::STRING; if( inKommentar ) color = KSGScriptEditor::ColorType::KOMMENTAR; for( auto i : error ) { if( i.anfang <= p && i.ende >= p ) underlineC = (int)KSGScriptEditor::ColorType::ERROR_UNDERLINE; } return color; }