diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 47d455dd55be855e4cc691c32f687f723d9247ee (patch) | |
tree | 52e236aaa2576bdb3840ebede26619692fed6d7d /kpovmodeler/pmparser.cpp | |
download | tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kpovmodeler/pmparser.cpp')
-rw-r--r-- | kpovmodeler/pmparser.cpp | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/kpovmodeler/pmparser.cpp b/kpovmodeler/pmparser.cpp new file mode 100644 index 00000000..7a252c88 --- /dev/null +++ b/kpovmodeler/pmparser.cpp @@ -0,0 +1,433 @@ +/* +************************************************************************** + description + -------------------- + copyright : (C) 2000-2003 by Andreas Zehender + email : [email protected] +************************************************************************** + +************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +**************************************************************************/ + + +#include "pmparser.h" + +#include <qstring.h> +#include <qbuffer.h> +#include <klocale.h> + +#include "pmpart.h" +#include "pmdeclare.h" +#include "pmerrorflags.h" +#include "pmrecursiveobjectiterator.h" +#include "pmdebug.h" + +unsigned int PMParser::s_maxErrors = 30; +unsigned int PMParser::s_maxWarnings = 50; + + +PMParser::PMParser( PMPart* part, QIODevice* dev ) + : m_okDeclares( 101 ) +{ + m_pPart = part; + m_pDevice = dev; + m_bDeviceCreated = false; + + init( ); +} + +PMParser::PMParser( PMPart* part, const QByteArray& array ) + : m_okDeclares( 101 ) +{ + m_pPart = part; + QBuffer* buffer = new QBuffer( array ); + buffer->open( IO_ReadOnly ); + m_pDevice = buffer; + m_bDeviceCreated = true; + + init( ); +} + +void PMParser::init( ) +{ + m_okDeclares.setAutoDelete( true ); + m_pLocalST.setAutoDelete( true ); + + m_lineNum = -1; + m_pResultList = 0; + m_errors = 0; + m_warnings = 0; + m_bFatalError = false; + m_shownMessages = 0; + m_messages.clear( ); + + m_pTopParent = 0; + m_renamedObjectSymbols.clear( ); + m_okDeclares.clear( ); + m_pNextCheckDeclare = 0; +} + +PMParser::~PMParser( ) +{ + if( m_bDeviceCreated ) + delete m_pDevice; +} + +void PMParser::printMessage( const PMPMessage messageNum ) +{ + if( !( m_shownMessages & messageNum ) ) + { + m_shownMessages |= messageNum; + + switch( messageNum ) + { + case PMMClockDefault: + printWarning( i18n( "Using the default value of 0.0 for clock" ) ); + break; + case PMMClockDeltaDefault: + printWarning( i18n( "Using the default value of 1.0 for clock_delta" ) ); + break; + case PMMSpecialRawComment: + m_messages += PMMessage( i18n( "Note: The full povray syntax is not supported yet. " + "If you want to add unsupported povray code to the " + "scene, you can put this code between the two " + "special comments \"//*PMRawBegin\" and " + "\"//*PMRawEnd\"." ) ); + break; + } + } +} + +void PMParser::printMessage( const QString& type, const QString& msg ) +{ + if( m_lineNum >= 0 ) + m_messages += PMMessage( i18n( "Line %1: " ).arg( m_lineNum ) + type + ": " + msg ); + else + m_messages += PMMessage( type + ": " + msg ); +} + +void PMParser::printError( const QString& msg ) +{ + if( m_errors < s_maxErrors ) + { + printMessage( i18n( "Error" ), msg ); + m_errors++; + } + else if( m_errors == s_maxErrors ) + { + m_messages += PMMessage( i18n( "Maximum of %1 errors reached." ) + .arg( s_maxErrors ) ); + m_errors++; + } +} + +void PMParser::printWarning( const QString& msg ) +{ + if( m_warnings < s_maxWarnings ) + { + printMessage( i18n( "Warning" ), msg ); + m_warnings++; + } + else if( m_warnings == s_maxWarnings ) + { + m_messages += PMMessage( i18n( "Maximum of %1 warnings reached." ) + .arg( s_maxWarnings ) ); + m_warnings++; + } +} + +void PMParser::printExpected( const char c, const char* sValue ) +{ + printError( i18n( "'%1' expected, found token '%2' instead." ) + .arg( c ).arg( sValue ) ); +} + +void PMParser::printExpected( const QString& str, const char* sValue ) +{ + printError( i18n( "'%1' expected, found token '%2' instead." ) + .arg( str ).arg( sValue ) ); +} + +void PMParser::printUnexpected( const QString& str ) +{ + printError( i18n( "Unexpected token '%1'." ).arg( str ) ); +} + +void PMParser::printInfo( const QString& msg ) +{ + printMessage( i18n( "Info" ), msg ); +} + +int PMParser::errorFlags( ) const +{ + int result = 0; + if( errors( ) ) + result |= PMEError; + if( warnings( ) ) + result |= PMEWarning; + if( fatal( ) ) + result |= PMEFatal; + return result; +} + + +void PMParser::parse( PMObjectList* list, PMObject* parent, + PMObject* after ) +{ + m_pResultList = list; + m_pTopParent = parent; + m_pAfter = after; + + // find first item, that can be a declare and can be used as link + // for parsed objects. + if( parent ) + { + if( parent->type( ) == "Scene" ) + { + if( after ) + m_pNextCheckDeclare = after; + else + m_pNextCheckDeclare = 0; + } + else + { + PMObject* obj = parent; + bool stop = false; + + // go to parents, until the parent is the scene + // (declares can only be inserted as top level objects) + do + { + if( obj->parent( ) ) + { + if( obj->parent( )->type( ) == "Scene" ) + stop = true; + else + obj = obj->parent( ); + } + else + { + obj = 0; + stop = true; + } + } + while( obj && !stop ); + + // now obj is the top level parent of the object, where parsed objects + // will be inserted + if( obj ) + m_pNextCheckDeclare = obj->prevSibling( ); + else + m_pNextCheckDeclare = 0; + } + } + + topParse( ); + + QPtrListIterator<PMSymbol> it( m_renamedObjectSymbols ); + for( ; it.current( ); ++it ) + it.current( )->setRenamedSymbol( 0 ); + m_renamedObjectSymbols.clear( ); + m_pLocalST.clear( ); + + if( ( errors( ) || warnings( ) ) && m_pResultList->isEmpty( ) ) + setFatalError( ); +} + +bool PMParser::insertChild( PMObject* child, PMObject* parent ) +{ + bool inserted = false; + + if( parent ) + { + if( parent->canInsert( child, parent->lastChild( ) ) ) + { + parent->appendChild( child ); + inserted = true; + } + else + { + printError( i18n( "Can't insert %1 into %2." ) + .arg( child->description( ) ) + .arg( parent->description( ) ) ); + } + } + else + { + if( m_pTopParent ) + { + if( m_pTopParent->canInsert( child, m_pAfter, m_pResultList ) ) + { + m_pResultList->append( child ); + inserted = true; + } + else + { + printError( i18n( "Can't insert %1 into %2." ) + .arg( child->description( ) ) + .arg( m_pTopParent->description( ) ) ); + } + } + else + { + // these lines should not be executed + // m_pTopParent may not be null + m_pResultList->append( child ); + inserted = true; + } + } + + if( !inserted ) + { + // insert error + // remove all links + PMRecursiveObjectIterator rit( child ); + PMDeclare* decl = 0; + + for( ; rit.current( ); ++rit ) + { + decl = rit.current( )->linkedObject( ); + if( decl ) + decl->removeLinkedObject( rit.current( ) ); + } + } + + return inserted; +} + +void PMParser::checkID( PMDeclare* decl ) +{ + PMSymbolTable* st = m_pPart->symbolTable( ); + PMSymbol* s = m_pLocalST.find( decl->id( ) ); + if( !s ) + s = st->find( decl->id( ) ); + + if( s ) + { + PMSymbol* newSym = st->findNewID( s->id( ) + "_", decl ); + s->setRenamedSymbol( newSym ); + // Symbol can be inserted multiple times + // Faster than searching for s and inserting s + // if the list does not contain it. + m_renamedObjectSymbols.append( s ); + + if( m_pTopParent ) + m_pLocalST.insert( decl->id( ), newSym ); // paste/drop + else + st->insert( decl->id( ), newSym ); // load file + } + else + { + s = new PMSymbol( decl->id( ), decl ); + if( m_pTopParent ) + m_pLocalST.insert( decl->id( ), s ); // paste/drop + else + st->insert( decl->id( ), s ); // load file + m_okDeclares.insert( decl->id( ), new bool( true ) ); + } +} + +void PMParser::checkID( const QString& id, const PMValue& v ) +{ + PMSymbolTable* st = m_pPart->symbolTable( ); + PMSymbol* s = m_pLocalST.find( id ); + + if( s ) + { + PMSymbol* newSym = new PMSymbol( st->findNewID( id + "_" ), v ); + s->setRenamedSymbol( newSym ); + // Symbol can be inserted multiple times + // Faster than searching for s and inserting s + // if the list does not contain it. + m_renamedObjectSymbols.append( s ); + + if( m_pTopParent ) + m_pLocalST.insert( id, newSym ); // paste/drop + + // values are never inserted into the parts symbol table + // else + // st->insert( decl->id( ), newSym ); // load file + } + else + { + s = new PMSymbol( id, v ); + if( m_pTopParent ) + m_pLocalST.insert( id, s ); // paste/drop + + // values are never inserted into the parts symbol table + // else + // st->insert( decl->id( ), s ); // load file + + m_okDeclares.insert( id, new bool( true ) ); + } +} + +PMDeclare* PMParser::checkLink( const QString& id ) +{ + PMSymbolTable* t = m_pPart->symbolTable( ); + bool ok = false; + + // is object declared? + PMSymbol* s = m_pLocalST.find( id ); + if( !s ) + s = t->find( id ); + + if( !s ) + printError( i18n( "Undefined object \"%1\"." ).arg( id ) ); + else if( s->type( ) != PMSymbol::Object ) + printError( i18n( "Undefined object \"%1\"." ).arg( id ) ); + else + { + // the object is declared + // is the id already in m_okDeclares + bool* lok = m_okDeclares.find( id ); + if( lok ) + ok = true; + else + { + // the id is not in m_okDeclares + PMObject* obj = s->object( ); + while( m_pNextCheckDeclare && !ok ) + { + if( m_pNextCheckDeclare->isA( "Declare" ) ) + { + PMDeclare* decl = ( PMDeclare* ) m_pNextCheckDeclare; + m_okDeclares.insert( decl->id( ), new bool( true ) ); + } + if( m_pNextCheckDeclare == obj ) + ok = true; + + m_pNextCheckDeclare = m_pNextCheckDeclare->prevSibling( ); + } + } + + if( !ok ) + printError( i18n( "Object \"%1\" is undefined at that point." ) + .arg( id ) ); + } + + if( ok ) + { + while( s->renamedSymbol( ) ) + s = s->renamedSymbol( ); + + return s->object( ); + } + + return 0; +} + +PMSymbol* PMParser::getSymbol( const QString& id ) const +{ + PMSymbol* s = m_pLocalST.find( id ); + if( !s ) + s = m_pPart->symbolTable( )->find( id ); + return s; +} + |