#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() { txt->release(); } // behandelt einen Fehler void ColorParser::handleError( int begin, int ende ) { if( errorIgnore ) return; Error err; err.anfang = begin; err.ende = ende; error.add( err ); } // Setzt den Parsevorgang zum Beginn zurück void ColorParser::reset() { pos.pos = 0; pos.inKeyword = 0; pos.inTypename = 0; pos.inParameter = 0; pos.inInstanzVar = 0; pos.inString = 0; pos.inChar = 0; pos.lastLehr = 1; pos.lastTrenner = 1; } // Lädt das Script neu void ColorParser::reload() { error.leeren(); for( auto i = abschnitt.getArray(); i.set; i++ ) { if( i.var.zFunktion ) i.var.zFunktion->release(); if( i.var.zKlasse ) i.var.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 &underlineC ) { KSGScriptEditor::ColorType color = KSGScriptEditor::ColorType::NORMAL_TEXT; int scriptL = txt->getLength(); char c = txt->getText()[ pos.pos++ ]; bool inString = pos.inChar || pos.inString; if( c == '\'' && txt->getText()[ pos.pos - 2 ] != '\\' ) pos.inChar = !pos.inChar; if( c == '"' && txt->getText()[ pos.pos - 2 ] != '\\' ) pos.inString = !pos.inString; if( istLehr( c ) || istTrenner( c ) ) { pos.inKeyword = 0; pos.inTypename = 0; pos.inInstanzVar = 0; pos.inParameter = 0; } else if( !pos.inChar && !pos.inString ) { if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && pos.lastLehr ) { for( int i = 0; i < keywordAnz; i++ ) { int kl = textLength( keyword[ i ] ); pos.inKeyword = 1; for( int j = 0; j < kl && j + pos.pos <= scriptL && pos.inKeyword; j++ ) pos.inKeyword &= txt->getText()[ j + pos.pos - 1 ] == keyword[ i ][ j ]; if( pos.inKeyword && ( kl - 1 + pos.pos == scriptL || istTrenner( txt->getText()[ kl - 1 + pos.pos ] ) ) ) break; pos.inKeyword = 0; } } if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && pos.lastLehr ) { for( int i = 0; i < typeAnz; i++ ) { int tl = textLength( type[ i ] ); pos.inTypename = 1; for( int j = 0; j < tl && j + pos.pos <= scriptL && pos.inTypename; j++ ) pos.inTypename &= txt->getText()[ j + pos.pos - 1 ] == type[ i ][ j ]; if( pos.inTypename && ( tl - 1 + pos.pos == scriptL || istTrenner( txt->getText()[ tl - 1 + pos.pos ] ) ) ) 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 + pos.pos <= scriptL && pos.inTypename; j++ ) pos.inTypename &= txt->getText()[ j + pos.pos - 1 ] == dat->klassen.get( i )->name.getText()[ j ]; if( pos.inTypename && ( tl - 1 + pos.pos == scriptL || istTrenner( txt->getText()[ tl - 1 + pos.pos ] ) ) ) break; pos.inTypename = 0; } } } if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && pos.lastLehr ) { for( auto i = abschnitt.getArray(); i.set; i++ ) { if( i.var.anfang <= pos.pos - 1 && i.var.ende >= pos.pos - 1 ) { if( i.var.zFunktion ) { int anz = i.var.zFunktion->parameter.getEintragAnzahl(); for( int j = 0; j < anz; j++ ) { int nl = i.var.zFunktion->parameter.get( j )->name.getLength(); pos.inParameter = 1; for( int k = 0; k < nl && k + pos.pos <= scriptL && pos.inParameter; k++ ) pos.inParameter &= txt->getText()[ k + pos.pos - 1 ] == i.var.zFunktion->parameter.get( j )->name.getText()[ k ]; if( pos.inParameter && ( nl - 1 + pos.pos == scriptL || istTrenner( txt->getText()[ nl - 1 + pos.pos ] ) ) ) break; pos.inParameter = 0; } } } } } if( !pos.inInstanzVar && !pos.inParameter && !pos.inKeyword && !pos.inTypename && pos.lastLehr ) { for( auto i = abschnitt.getArray(); i.set; i++ ) { if( i.var.anfang <= pos.pos - 1 && i.var.ende >= pos.pos - 1 ) { if( i.var.zKlasse ) { int anz = i.var.zKlasse->variablen.getEintragAnzahl(); for( int j = 0; j < anz; j++ ) { int nl = i.var.zKlasse->variablen.get( j )->name.getLength(); pos.inInstanzVar = 1; for( int k = 0; k < nl && k + pos.pos <= scriptL && pos.inInstanzVar; k++ ) pos.inInstanzVar &= txt->getText()[ k + pos.pos - 1 ] == i.var.zKlasse->variablen.get( j )->name.getText()[ k ]; if( pos.inInstanzVar && ( nl - 1 + pos.pos == scriptL || istTrenner( txt->getText()[ nl - 1 + pos.pos ] ) ) ) 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( pos.inChar || pos.inString || inString ) color = KSGScriptEditor::ColorType::STRING; for( auto i = error.getArray(); i.set; i++ ) { if( i.var.anfang <= pos.pos && i.var.ende >= pos.pos ) underlineC = KSGScriptEditor::ColorType::ERROR_UNDERLINE; } pos.lastLehr = istLehr( c ); pos.lastTrenner = istTrenner( c ); return color; } // Reference Counting ColorParser *ColorParser::getThis() { ref++; return this; } ColorParser *ColorParser::release() { if( !--ref ) delete this; return 0; }