#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 ) { pfad = new Text( "" ); ref = 1; txt = zTxt->getThis(); reset(); reload(); } // Destructor ColorParser::~ColorParser() { for( auto i = abschnitt.getIterator(); i; i++ ) { 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.getIterator(); i; i++ ) { if( i._.zFunktion ) i._.zFunktion->release(); if( i._.zKlasse ) i._.zKlasse->release(); } abschnitt.leeren(); delete dat; dat = new KSGSLeseScript(); d = new TextReader( 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( pfad->getText() ); pfad->setText( dPf ); Reader *tmp = d; if( !ladeDatei() ) { handleError( (int)d->getLPosition() - 1, (int)d->getLPosition() ); d = tmp; pfad->setText( pf ); //error( 6, { "Lade Anweisung", *pfad }, zObj ); br = 1; break; } d = tmp; pfad->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 = ( (TextReader*)d )->release(); } KSGSLeseKlasse *ColorParser::leseKlasse() { Abschnitt abs; abs.anfang = (int)d->getLPosition(); KSGSLeseKlasse *ret = __super::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 = __super::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 c = txt->getText()[ p ]; 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.getIterator(); i; i++ ) { if( i._.anfang <= p && i._.ende >= p ) inString = 1; } for( auto i = kommentar.getIterator(); i; i++ ) { 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( auto i = abschnitt.getIterator(); i; i++ ) { 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( auto i = abschnitt.getIterator(); i; i++ ) { 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.getIterator(); i; i++ ) { if( i._.anfang <= p && i._.ende >= p ) underlineC = KSGScriptEditor::ColorType::ERROR_UNDERLINE; } return color; } // Reference Counting ColorParser *ColorParser::getThis() { ref++; return this; } ColorParser *ColorParser::release() { if( !--ref ) delete this; return 0; }