/***************************************************************************
saparser . cpp - description
- - - - - - - - - - - - - - - - - - -
begin : Wed Feb 11 2004
copyright : ( C ) 2004 Andras Mantia < amantia @ kde . org >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***************************************************************************
* *
* 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//qt includes
# include <tqtimer.h>
//kde includes
# include <kdebug.h>
# include <ktexteditor/editinterface.h>
//own includes
# include "saparser.h"
# include "sagroupparser.h"
# include "document.h"
# include "dtds.h"
# include "node.h"
# include "parsercommon.h"
# include "qtag.h"
# include "quantacommon.h"
# include "resource.h"
//#define DEBUG_PARSER
SAParser : : SAParser ( )
{
m_write = 0L ;
m_baseNode = 0L ;
m_currentNode = 0L ;
m_quotesRx = TQRegExp ( " \" |' " ) ;
m_specialInsideXml = false ;
m_parsingEnabled = true ;
m_synchronous = true ;
m_parseOneLineTimer = new TQTimer ( this ) ;
connect ( m_parseOneLineTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotParseOneLine ( ) ) ) ;
m_parseInDetailTimer = new TQTimer ( this ) ;
connect ( m_parseInDetailTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotParseNodeInDetail ( ) ) ) ;
}
SAParser : : ~ SAParser ( )
{
}
void SAParser : : init ( Node * node , Document * write )
{
m_baseNode = node ;
m_write = write ;
m_dtd = write - > defaultDTD ( ) ;
}
bool SAParser : : slotParseOneLine ( )
{
if ( ( ! m_parsingEnabled | | ! baseNode ) & & ! m_synchronous )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " slotParseOneLine - interrupted " < < endl ;
# endif
return false ;
}
if ( s_line < = s_endLine )
{
s_contextFound = false ;
switch ( s_currentContext . type )
{
case Group :
case Text : {
int areaEndPos = - 1 ;
int quotedStringPos = - 1 ;
int commentPos = - 1 ;
int groupKeywordPos = - 1 ;
if ( s_searchContent | | ( s_parentNode & & s_parentNode - > tag - > dtd ( ) - > family = = Xml ) )
{
//search for different s_contexts
if ( s_searchContent ) //search for quoted strings, comments, groups only in non-comment special areas
{
quotedStringPos = s_textLine . find ( m_quotesRx , s_col ) ; //quoted strings
s_searchedString = s_textLine . left ( quotedStringPos ) ;
commentPos = s_searchedString . find ( s_dtd - > commentsStartRx , s_col ) ; //comments
s_searchedString = s_textLine . left ( commentPos ) ;
if ( s_fullParse )
groupKeywordPos = s_searchedString . find ( s_dtd - > structRx , s_col ) ; //groups, like { }
} else
s_searchedString = s_textLine ;
int specialAreaPos = - 1 ;
if ( s_searchForSpecialAreas ) //special area inside special area
{
s_searchedString = s_textLine . left ( groupKeywordPos ) ;
specialAreaPos = s_searchedString . find ( s_dtd - > specialAreaStartRx , s_col ) ;
}
if ( s_searchForAreaEnd ) //the end of the special area
{
s_searchedString = s_textLine . left ( specialAreaPos ) ;
areaEndPos = s_searchedString . find ( s_areaEndString , s_col ) ;
} else
if ( s_searchForForcedAreaEnd ) //the end of the special area if a forcing string was specified
{
s_searchedString = s_textLine . left ( specialAreaPos ) ;
areaEndPos = s_searchedString . find ( s_forcedAreaRx , s_col ) ;
if ( areaEndPos ! = - 1 )
s_areaEndString = s_forcedAreaRx . cap ( ) ;
}
//check which s_context was found first
if ( quotedStringPos ! = - 1 ) //is it a quoted string?
{
if ( ( quotedStringPos < commentPos | | commentPos = = - 1 ) & &
( quotedStringPos < groupKeywordPos | | groupKeywordPos = = - 1 ) & &
( quotedStringPos < specialAreaPos | | specialAreaPos = = - 1 ) & &
( quotedStringPos < areaEndPos | | areaEndPos = = - 1 ) )
{
s_context . type = QuotedString ;
s_context . area . bCol = quotedStringPos ;
s_context . startString = s_textLine . mid ( quotedStringPos , 1 ) ;
s_contextFound = true ;
}
}
if ( ! s_contextFound & & commentPos ! = - 1 ) //is it a comment?
{
if ( ( commentPos < groupKeywordPos | | groupKeywordPos = = - 1 ) & &
( commentPos < specialAreaPos | | specialAreaPos = = - 1 ) & &
( commentPos < areaEndPos | | areaEndPos = = - 1 ) )
{
s_context . type = Comment ;
s_context . area . bCol = commentPos ;
s_context . startString = s_dtd - > commentsStartRx . cap ( ) ;
s_contextFound = true ;
}
}
if ( ! s_contextFound & & groupKeywordPos ! = - 1 ) //is it a group structure?
{
if ( ( groupKeywordPos < specialAreaPos | | specialAreaPos = = - 1 ) & &
( groupKeywordPos < areaEndPos | | areaEndPos = = - 1 ) )
{
TQString foundText = s_dtd - > structRx . cap ( ) ;
if ( foundText = = s_dtd - > structBeginStr )
{
s_context . type = Group ;
s_context . area . bCol = groupKeywordPos ;
s_context . startString = foundText ;
//create a text node until the struct. beginning
s_currentContext . area . eLine = s_line ;
s_currentContext . area . eCol = groupKeywordPos + foundText . length ( ) - 1 ;
if ( s_currentNode & &
( s_currentNode - > tag - > type = = Tag : : Text | |
s_currentNode - > tag - > type = = Tag : : Empty ) )
ParserCommon : : appendAreaToTextNode ( m_write , s_currentContext . area , s_currentNode ) ;
else
s_currentNode = ParserCommon : : createTextNode ( m_write , s_currentNode , s_line , s_currentContext . area . eCol + 1 , s_currentContext . parentNode ) ;
s_currentNode - > tag - > type = Tag : : ScriptStructureBegin ;
s_currentNode - > tag - > single = false ;
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
s_currentContext . lastNode = s_currentNode ;
s_contextStack . push ( s_currentContext ) ;
s_currentContext . parentNode = s_currentNode ;
s_col = s_context . area . bCol + s_context . startString . length ( ) ;
s_currentContext . area . bLine = s_line ;
s_currentContext . area . bCol = s_col ;
s_currentContext . type = Group ;
if ( m_synchronous )
//slotParseOneLine();
return true ;
else
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseOneLine from parseArea (opening group struct). " < < endl ;
# endif
m_parseOneLineTimer - > start ( 0 , true ) ;
}
return true ;
} else //it's a closing group structure element (like "}")
{
if ( s_currentContext . type ! = Group )
{
s_col = groupKeywordPos + foundText . length ( ) ;
if ( m_synchronous )
//slotParseOneLine();
return true ;
else
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseOneLine from parseArea (closing group struct). " < < endl ;
# endif
m_parseOneLineTimer - > start ( 0 , true ) ;
}
return true ;
}
s_currentContext . area . eLine = s_line ;
s_currentContext . area . eCol = groupKeywordPos - 1 ;
//kdDebug(24000) << TQString("Group Struct s_context: %1, %2, %3, %4").arg( s_currentContext.bLine).arg(s_currentContext.bCol).arg(s_currentContext.eLine).arg(s_currentContext.eCol) << endl;
if ( s_currentNode & &
( s_currentNode - > tag - > type = = Tag : : Text | |
s_currentNode - > tag - > type = = Tag : : Empty ) )
ParserCommon : : appendAreaToTextNode ( m_write , s_currentContext . area , s_currentNode ) ;
else
s_currentNode = ParserCommon : : createTextNode ( m_write , s_currentNode , s_line , groupKeywordPos , s_currentContext . parentNode ) ;
if ( s_currentNode )
{
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
}
s_previousContext = s_contextStack . pop ( ) ;
s_currentContext . parentNode = s_previousContext . parentNode ;
s_currentContext . lastNode = s_previousContext . lastNode ;
s_currentContext . type = s_previousContext . type ;
s_currentContext . area . bLine = s_line ;
s_currentContext . area . bCol = groupKeywordPos + foundText . length ( ) ;
s_currentContext . area . eLine = s_currentContext . area . eCol = - 1 ;
s_currentContext . startString = s_previousContext . startString ;
s_col = s_currentContext . area . bCol ;
Tag * tag = new Tag ( ) ;
tag - > name = foundText ;
tag - > setStr ( foundText ) ;
tag - > setWrite ( m_write ) ;
tag - > setTagPosition ( s_line , groupKeywordPos , s_line , s_col - 1 ) ;
tag - > setDtd ( s_dtd ) ;
tag - > type = Tag : : ScriptStructureEnd ;
tag - > single = true ;
Node * node = new Node ( s_currentContext . parentNode ) ;
nodeNum + + ;
node - > tag = tag ;
node - > insideSpecial = true ;
node - > specialInsideXml = m_specialInsideXml ;
if ( s_currentContext . parentNode & & ! s_currentContext . parentNode - > child )
{
s_currentContext . parentNode - > child = node ;
}
else if ( s_currentContext . lastNode )
{
node - > prev = s_currentContext . lastNode ;
s_currentContext . lastNode - > next = node ;
}
s_currentNode = node ;
if ( m_synchronous )
return true ;
else
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseOneLine from parseArea (group structure). " < < endl ;
# endif
m_parseOneLineTimer - > start ( 0 , true ) ;
}
return true ;
}
}
}
if ( ! s_contextFound & & specialAreaPos ! = - 1 ) //is it a special area?
{
if ( specialAreaPos < areaEndPos | | areaEndPos = = - 1 )
{
TQString foundText = s_dtd - > specialAreaStartRx . cap ( ) ;
s_currentContext . area . eLine = s_line ;
s_currentContext . area . eCol = specialAreaPos - 1 ;
if ( s_fullParse )
{
if ( s_currentNode & &
( s_currentNode - > tag - > type = = Tag : : Text | |
s_currentNode - > tag - > type = = Tag : : Empty ) )
ParserCommon : : appendAreaToTextNode ( m_write , s_currentContext . area , s_currentNode ) ;
else
s_currentNode = ParserCommon : : createTextNode ( m_write , s_currentNode , s_line , specialAreaPos , s_currentContext . parentNode ) ;
if ( s_currentNode )
{
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
}
}
//create a toplevel node for the included special area
AreaStruct area ( s_line , specialAreaPos , s_line , specialAreaPos + foundText . length ( ) - 1 ) ;
Node * node = ParserCommon : : createScriptTagNode ( m_write , area , foundText , s_dtd , s_currentContext . parentNode , s_currentNode ) ;
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Parsing a nested area. " < < endl ;
# endif
AreaStruct area2 ( s_line , specialAreaPos , s_endLine , s_endCol ) ;
SAParser * p = new SAParser ( ) ;
p - > init ( m_baseNode , m_write ) ;
s_currentNode = p - > parseArea ( area2 , foundText , " " , node , s_fullParse , true ) ;
s_line = p - > lastParsedLine ( ) ;
s_col = p - > lastParsedColumn ( ) ;
delete p ;
s_currentContext . area . bLine = s_line ;
s_currentContext . area . bCol = s_col + 1 ;
s_textLine = ParserCommon : : getLine ( m_write , s_line , s_endLine , s_endCol ) ;
s_col + + ;
if ( m_synchronous )
{
return true ;
}
else
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseOneLine from slotParseOneLine (nested area). " < < endl ;
# endif
m_parseOneLineTimer - > start ( 0 , true ) ;
return true ;
}
}
}
} else //when we look only for the area end string
if ( s_searchForAreaEnd )
{
areaEndPos = s_textLine . find ( s_areaEndString , s_col ) ;
} else
if ( s_searchForForcedAreaEnd )
{
areaEndPos = s_textLine . find ( s_forcedAreaRx , s_col ) ;
if ( areaEndPos ! = - 1 )
s_areaEndString = s_forcedAreaRx . cap ( ) ;
}
if ( ! s_contextFound & & areaEndPos ! = - 1 ) //did we find the end of the special area?
{
m_lastParsedLine = s_line ;
m_lastParsedCol = areaEndPos + s_areaEndString . length ( ) - 1 ;
s_currentContext . area . eLine = s_line ;
s_currentContext . area . eCol = areaEndPos - 1 ;
//Always create a node between the opening and closing special area nodes.
//This fixes the "commnet loss" bug when editing in VPL and autocompletion
//for simple special areas like <? a ?>
if ( s_fullParse | | ! s_parentNode - > child )
{
if ( s_currentNode & &
( s_currentNode - > tag - > type = = Tag : : Text | |
s_currentNode - > tag - > type = = Tag : : Empty ) )
ParserCommon : : appendAreaToTextNode ( m_write , s_currentContext . area , s_currentNode ) ;
else
{
s_currentNode = ParserCommon : : createTextNode ( m_write , s_currentNode , s_line , areaEndPos , s_parentNode ) ;
}
if ( s_currentNode )
{
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
}
}
//kdDebug(24000) << TQString("Special area %1 ends at %2, %3").arg(s_dtd->name).arg(s_line).arg(lastCol) << endl;
//create a closing node for the special area
Tag * tag = new Tag ( ) ;
tag - > setTagPosition ( s_line , areaEndPos , s_line , m_lastParsedCol ) ;
tag - > parse ( s_areaEndString , m_write ) ;
tag - > setDtd ( s_dtd ) ;
tag - > type = Tag : : XmlTagEnd ;
tag - > validXMLTag = false ; //FIXME: this is more or less a workaround. We should introduce and handle Tag::ScriptTagEnd
tag - > single = true ;
//at this point s_parentNode = the opening node of the special area (eg. <?)
//and it should always exist
Node * node = new Node ( s_parentNode - > parent ) ;
nodeNum + + ;
s_parentNode - > next = node ;
node - > prev = s_parentNode ;
node - > tag = tag ;
node - > closesPrevious = true ;
if ( s_fullParse )
{
Node * g_node , * g_endNode ;
g_node = s_parentNode - > child ;
/* g_endNode = s_currentNode;
if ( g_node & & g_node = = g_endNode )
g_endNode = s_parentNode - > next ; */
g_endNode = node ;
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseForScriptGroup from slotParseOneLine. " < < endl ;
# endif
// slotParseForScriptGroup();
if ( ! m_synchronous )
{
bool parsingLastNode = true ;
Node * n = g_endNode ;
while ( n )
{
n = n - > nextSibling ( ) ;
if ( n & & n - > insideSpecial )
{
parsingLastNode = false ;
break ;
}
}
SAGroupParser * groupParser = new SAGroupParser ( this , write ( ) , g_node , g_endNode , m_synchronous , parsingLastNode , true ) ;
connect ( groupParser , TQT_SIGNAL ( rebuildStructureTree ( bool ) ) , TQT_SIGNAL ( rebuildStructureTree ( bool ) ) ) ;
connect ( groupParser , TQT_SIGNAL ( cleanGroups ( ) ) , TQT_SIGNAL ( cleanGroups ( ) ) ) ;
connect ( groupParser , TQT_SIGNAL ( parsingDone ( SAGroupParser * ) ) , TQT_SLOT ( slotGroupParsingDone ( SAGroupParser * ) ) ) ;
groupParser - > slotParseForScriptGroup ( ) ;
m_groupParsers . append ( groupParser ) ;
}
}
m_lastParsedNode = node ;
s_useReturnVars = true ;
if ( ! m_synchronous )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling parsingDone from slotParseOneLine (area end found). " < < endl ;
# endif
m_lastParsedNode = parsingDone ( ) ;
}
return false ; //parsing finished
}
if ( s_contextFound )
{
s_context . area . bLine = s_line ;
s_context . area . eLine = s_context . area . eCol = - 1 ;
s_context . parentNode = s_currentContext . parentNode ;
s_currentContext . area . eLine = s_context . area . bLine ;
s_currentContext . area . eCol = s_context . area . bCol - 1 ;
// s_currentContext.parentNode = s_parentNode;
s_contextStack . push ( s_currentContext ) ;
if ( s_fullParse )
{
if ( s_currentNode & &
( s_currentNode - > tag - > type = = Tag : : Text | | s_currentNode - > tag - > type = = Tag : : Empty ) )
{
ParserCommon : : appendAreaToTextNode ( m_write , s_currentContext . area , s_currentNode ) ;
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
} else
if ( s_currentContext . area . bLine < s_currentContext . area . eLine | |
( s_currentContext . area . bLine = = s_currentContext . area . eLine & &
s_currentContext . area . bCol < s_currentContext . area . eCol ) )
{
//create a tag from the s_currentContext
Tag * tag = new Tag ( s_currentContext . area , m_write , s_dtd ) ;
TQString tagStr = tag - > tagStr ( ) ;
tag - > cleanStr = tagStr ;
QuantaCommon : : removeCommentsAndQuotes ( tag - > cleanStr , s_dtd ) ;
if ( tagStr . simplifyWhiteSpace ( ) . isEmpty ( ) )
{
tag - > type = Tag : : Empty ;
} else
{
tag - > type = Tag : : Text ;
}
tag - > single = true ;
//create a node with the above tag
Node * node = new Node ( s_currentContext . parentNode ) ;
nodeNum + + ;
node - > tag = tag ;
node - > insideSpecial = true ;
node - > specialInsideXml = m_specialInsideXml ;
if ( s_currentContext . parentNode & & ! s_currentContext . parentNode - > child )
{
s_currentContext . parentNode - > child = node ;
}
else if ( s_currentNode )
{
node - > prev = s_currentNode ;
s_currentNode - > next = node ;
}
s_currentNode = node ;
}
}
//kdDebug(24000) << TQString("%1 s_context: %2, %3, %4, %5").arg(s_currentContext.type).arg( s_currentContext.bLine).arg(s_currentContext.bCol).arg(s_currentContext.eLine).arg(s_currentContext.eCol) << endl;
s_currentContext = s_context ;
s_col = s_context . area . bCol + s_context . startString . length ( ) ;
} else
{
s_line + + ;
s_col = 0 ;
s_textLine = ParserCommon : : getLine ( m_write , s_line , s_endLine , s_endCol ) ;
}
break ;
}
case QuotedString :
{
int pos = - 1 ;
int p = s_col ;
int l = s_textLine . length ( ) ;
while ( p < l )
{
p = s_textLine . find ( s_currentContext . startString , p ) ;
if ( p ! = - 1 )
{
if ( p > = 0 )
{
int i = p - 1 ;
int slahNum = 0 ;
while ( i > 0 & & s_textLine [ i ] = = ' \\ ' )
{
slahNum + + ;
i - - ;
}
if ( p = = 0 | | ( slahNum % 2 = = 0 ) )
{
pos = p ;
break ;
}
}
} else
break ;
p + + ;
}
if ( pos ! = - 1 )
{
// if (pos != 0) pos++;
s_currentContext . area . eLine = s_line ;
s_currentContext . area . eCol = pos ;
//kdDebug(24000) << TQString("Quoted String s_context: %1, %2, %3, %4").arg( s_currentContext.bLine).arg(s_currentContext.bCol).arg(s_currentContext.eLine).arg(s_currentContext.eCol) << endl;
if ( s_fullParse )
{
if ( s_currentNode & &
( s_currentNode - > tag - > type = = Tag : : Text | |
s_currentNode - > tag - > type = = Tag : : Empty ) )
ParserCommon : : appendAreaToTextNode ( m_write , s_currentContext . area , s_currentNode ) ;
else
s_currentNode = ParserCommon : : createTextNode ( m_write , 0L , s_line , pos , s_currentContext . parentNode ) ;
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
}
s_previousContext = s_contextStack . pop ( ) ;
s_currentContext . parentNode = s_previousContext . parentNode ;
s_currentContext . type = s_previousContext . type ;
s_currentContext . area . bLine = s_line ;
s_currentContext . area . bCol = pos + 1 ;
s_currentContext . area . eLine = s_currentContext . area . eCol = - 1 ;
s_currentContext . startString = s_previousContext . startString ;
s_col = pos + 1 ;
} else
{
s_line + + ;
s_col = 0 ;
s_textLine = ParserCommon : : getLine ( m_write , s_line , s_endLine , s_endCol ) ;
}
break ;
}
case Comment :
{
int pos = s_textLine . find ( s_dtd - > comments [ s_currentContext . startString ] , s_col ) ;
if ( pos = = - 1 & & s_dtd - > comments [ s_currentContext . startString ] = = " \n " )
{
int pos2 = s_textLine . find ( s_areaEndString , s_col ) ;
if ( pos2 ! = - 1 )
{
pos = pos2 - 1 ;
} else
{
pos = s_textLine . length ( ) ;
}
}
if ( pos ! = - 1 )
{
s_currentContext . area . eLine = s_line ;
s_currentContext . area . eCol = pos + s_dtd - > comments [ s_currentContext . startString ] . length ( ) - 1 ;
s_currentContext . type = s_previousContext . type ;
//kdDebug(24000) << TQString("Comment s_context: %1, %2, %3, %4").arg( s_currentContext.bLine).arg(s_currentContext.bCol).arg(s_currentContext.eLine).arg(s_currentContext.eCol) << endl;
if ( s_fullParse )
{
//create a tag with the comment
Tag * tag = new Tag ( s_currentContext . area , m_write , s_dtd ) ;
tag - > type = Tag : : Comment ;
tag - > single = true ;
//create a node with the above tag
Node * node = new Node ( s_currentContext . parentNode ) ;
nodeNum + + ;
node - > tag = tag ;
node - > insideSpecial = true ;
node - > specialInsideXml = m_specialInsideXml ;
if ( s_currentNode & & s_currentNode ! = node - > parent )
{
s_currentNode - > next = node ;
node - > prev = s_currentNode ;
} else
if ( node - > parent & & ! node - > parent - > child )
node - > parent - > child = node ;
s_currentNode = node ;
}
s_previousContext = s_contextStack . pop ( ) ;
s_currentContext . parentNode = s_previousContext . parentNode ;
s_currentContext . type = s_previousContext . type ;
s_currentContext . area . bLine = s_line ;
s_currentContext . area . bCol = s_currentContext . area . eCol + 1 ;
s_currentContext . area . eLine = s_currentContext . area . eCol = - 1 ;
s_currentContext . startString = s_previousContext . startString ;
s_col = s_currentContext . area . bCol ;
} else
{
s_line + + ;
s_col = 0 ;
s_textLine = ParserCommon : : getLine ( m_write , s_line , s_endLine , s_endCol ) ;
}
break ;
}
default :
{
s_line + + ;
s_col = 0 ;
s_textLine = ParserCommon : : getLine ( m_write , s_line , s_endLine , s_endCol ) ;
}
}
if ( m_synchronous )
{
//slotParseOneLine();
}
else
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseOneLine from slotParseOneLine. " < < endl ;
# endif
m_parseOneLineTimer - > start ( 0 , true ) ;
}
} else
{
if ( ! m_synchronous )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling parsingDone from slotParseOneLine. " < < endl ;
# endif
parsingDone ( ) ;
}
return false ; //parsing finished
}
return true ;
}
Node * SAParser : : parseArea ( const AreaStruct & specialArea ,
const TQString & areaStartString ,
const TQString & forcedAreaEndString ,
Node * parentNode ,
bool fullParse , bool synchronous )
{
m_synchronous = synchronous ;
s_parentNode = parentNode ;
s_fullParse = fullParse ;
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " parseArea full: " < < s_fullParse < < " synch: " < < m_synchronous < < endl ;
# endif
int s_startLine = specialArea . bLine ;
int s_startCol = specialArea . bCol ;
s_endLine = specialArea . eLine ;
s_endCol = specialArea . eCol ;
//kdDebug(24000) << TQString("Starting to parse at %1, %2 for %3").arg(s_startLine).arg(s_startCol).arg(areaStartString) << endl;
s_searchForAreaEnd = false ;
s_searchForForcedAreaEnd = false ;
s_dtd = 0L ;
if ( s_parentNode & & ! areaStartString . isEmpty ( ) )
{
const DTDStruct * parentDTD = m_dtd ;
if ( s_parentNode - > parent )
parentDTD = s_parentNode - > parent - > tag - > dtd ( ) ;
s_dtd = DTDs : : ref ( ) - > find ( parentDTD - > specialAreaNames [ areaStartString ] ) ;
s_areaEndString = parentDTD - > specialAreas [ areaStartString ] ;
s_searchForAreaEnd = true ;
}
if ( ! forcedAreaEndString . isEmpty ( ) )
{
s_forcedAreaRx . setPattern ( forcedAreaEndString ) ;
s_forcedAreaRx . setCaseSensitive ( m_dtd - > caseSensitive ) ;
s_searchForForcedAreaEnd = true ;
s_searchForAreaEnd = false ;
if ( s_parentNode )
s_dtd = s_parentNode - > tag - > dtd ( ) ;
}
s_searchContent = true ;
if ( s_parentNode & & s_parentNode - > tag - > type = = Tag : : Comment )
s_searchContent = false ;
if ( ! s_dtd )
{
if ( s_parentNode )
s_dtd = s_parentNode - > tag - > dtd ( ) ; //fallback, usually when the special area is a comment
else
s_dtd = m_dtd ; //fallback when there is no s_parentNode
}
m_write - > addDTEP ( s_dtd - > name ) ;
s_searchForSpecialAreas = ( s_dtd - > specialAreas . count ( ) > 0 ) ;
if ( s_parentNode & & s_parentNode - > tag - > type = = Tag : : Comment )
s_searchForSpecialAreas = false ;
s_col = s_startCol + areaStartString . length ( ) ;
s_line = s_startLine ;
s_textLine = m_write - > text ( s_startLine , 0 , s_startLine , m_write - > editIf - > lineLength ( s_startLine ) ) ;
if ( s_line = = s_endLine )
{
if ( s_endCol > 0 )
s_textLine . truncate ( s_endCol + 1 ) ;
else
s_textLine = " " ;
}
s_previousContext . type = Unknown ;
s_currentContext . type = Text ;
s_currentContext . area . bLine = s_line ;
s_currentContext . area . bCol = s_col ;
s_currentContext . area . eLine = s_currentContext . area . eCol = - 1 ;
s_currentContext . parentNode = s_parentNode ;
s_currentNode = s_parentNode ;
m_lastParsedNode = 0L ;
s_useReturnVars = false ;
if ( s_line < = s_endLine )
{
if ( m_synchronous )
{
while ( slotParseOneLine ( ) ) ; //actually this parses the whole area, as synchronous == true
if ( s_useReturnVars ) //this is true if the special area end was found
{
return m_lastParsedNode ;
}
}
else
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseOneLine from parseArea. " < < endl ;
# endif
m_parseOneLineTimer - > start ( 0 , true ) ;
return 0L ;
}
}
if ( m_synchronous ) //if the special area end was not found and we are in synchronous mode
{
s_next = 0L ;
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling parsingDone from parseArea. " < < endl ;
# endif
s_currentNode = parsingDone ( ) ;
return s_currentNode ;
}
return 0L ;
}
Node * SAParser : : parsingDone ( )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " parsingDone. Use return values: " < < s_useReturnVars < < endl ;
# endif
if ( s_useReturnVars )
{
if ( s_fullParse )
{
Node * n = m_lastParsedNode ;
if ( m_useNext )
{
// kdDebug(24000) << "m_lastParsedNode: " << m_lastParsedNode << " " << m_lastParsedNode->tag->tagStr() << endl;
n - > next = s_next ;
if ( s_next )
{
s_next - > prev = n ;
}
n - > prev = s_parentNode ;
}
m_currentNode = n - > nextSibling ( ) ;
if ( m_currentNode )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseNodeInDetail from parsingDone (use return values) " < < endl ;
# endif
m_parseInDetailTimer - > start ( 0 , true ) ;
return m_lastParsedNode ;
}
else
{
m_parsingEnabled = true ;
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Emitting rebuildStructureTree from parsingDone (use return values). Enable parsing. " < < endl ;
# endif
emit rebuildStructureTree ( false ) ;
# ifdef DEBUG_PARSER
// kdDebug(24000) << "Calling cleanGroups from SAParser::parsingDone" << endl;
# endif
emit cleanGroups ( ) ;
}
}
m_currentNode = 0L ;
return m_lastParsedNode ;
}
if ( ! s_currentNode )
{
s_currentNode = ParserCommon : : createTextNode ( m_write , s_parentNode , s_endLine , s_endCol , s_parentNode ) ;
if ( s_currentNode )
{
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
}
}
else if ( s_parentNode & & ! s_parentNode - > next )
{
s_currentNode = ParserCommon : : createTextNode ( m_write , s_currentNode , s_endLine , s_endCol , s_parentNode ) ;
s_currentNode - > insideSpecial = true ;
s_currentNode - > specialInsideXml = m_specialInsideXml ;
}
if ( s_fullParse )
{
Node * n ;
if ( s_parentNode )
{
n = s_parentNode ; //->child;
} else
{
n = s_currentNode ;
while ( n & & n - > prev )
n = n - > prev ;
s_currentNode = n ;
}
Node * g_node = n ;
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseForScriptGroup from parsingDone. Synch: " < < m_synchronous < < endl ;
# endif
//parse for groups only when doing aynchronous detailed parsing
if ( ! m_synchronous )
{
SAGroupParser * groupParser = new SAGroupParser ( this , write ( ) , g_node , 0L , m_synchronous , true /*last node*/ , true ) ;
connect ( groupParser , TQT_SIGNAL ( rebuildStructureTree ( bool ) ) , TQT_SIGNAL ( rebuildStructureTree ( bool ) ) ) ;
connect ( groupParser , TQT_SIGNAL ( cleanGroups ( ) ) , TQT_SIGNAL ( cleanGroups ( ) ) ) ;
connect ( groupParser , TQT_SIGNAL ( parsingDone ( SAGroupParser * ) ) , TQT_SLOT ( slotGroupParsingDone ( SAGroupParser * ) ) ) ;
groupParser - > slotParseForScriptGroup ( ) ;
m_groupParsers . append ( groupParser ) ;
}
}
m_lastParsedLine = s_endLine ;
m_lastParsedCol = s_endCol + 1 ;
if ( s_fullParse & & m_currentNode )
{
if ( m_useNext & & s_currentNode )
{
// kdDebug(24000) << "s_currentNode: " << s_currentNode << endl;
Node * n = s_currentNode ;
n - > next = s_next ;
if ( s_next )
s_next - > prev = n ;
}
m_currentNode = m_currentNode - > nextSibling ( ) ;
if ( m_currentNode )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseNodeInDetail from parsingDone. " < < endl ;
# endif
m_parseInDetailTimer - > start ( 0 , true ) ;
emit rebuildStructureTree ( false ) ;
}
else
{
m_parsingEnabled = true ;
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Emitting detailedParsingDone from parsingDone. Enable parsing. " < < endl ;
# endif
emit rebuildStructureTree ( false ) ;
}
}
m_currentNode = 0L ;
return s_currentNode ;
}
void SAParser : : parseInDetail ( bool synchronous )
{
// synchronous = true; //for testing. Uncomment to test the parser in synchronous mode
// return; //for testing. Uncomment to disable the detailed parser
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " parseInDetail. Enabled: " < < m_parsingEnabled < < endl ;
# endif
if ( ! m_parsingEnabled )
{
m_currentNode = m_baseNode ;
m_parsingEnabled = true ;
m_synchronous = synchronous ;
if ( m_currentNode )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling slotParseNodeInDetail from parseInDetail. " < < endl ;
# endif
slotParseNodeInDetail ( ) ;
}
}
}
void SAParser : : slotParseNodeInDetail ( )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " slotParseNodeInDetail. Enabled: " < < m_parsingEnabled < < " Synch: " < < m_synchronous < < endl ; //this is really heavy debug information, enable only when really needed
# endif
if ( m_currentNode & & m_parsingEnabled & & baseNode )
{
if ( m_currentNode - > insideSpecial & &
m_currentNode - > tag - > type ! = Tag : : Comment & &
m_currentNode - > tag - > type ! = Tag : : Text & &
m_currentNode - > tag - > type ! = Tag : : Empty )
{
Node : : deleteNode ( m_currentNode - > child ) ;
m_currentNode - > child = 0L ;
AreaStruct area ( m_currentNode - > tag - > area ( ) ) ;
s_next = 0L ;
m_useNext = false ;
//FIXME: Find out why can the tag become 0L
if ( m_currentNode - > next & & m_currentNode - > next - > tag )
{
AreaStruct area2 ( m_currentNode - > next - > tag - > area ( ) ) ;
area . eLine = area2 . eLine ;
area . eCol = area2 . eCol + 1 ;
s_next = m_currentNode - > next - > next ;
if ( m_currentNode - > next - > closesPrevious )
{
m_currentNode - > next - > removeAll = false ;
Node * secondNext = m_currentNode - > next - > next ;
if ( secondNext )
secondNext - > prev = m_currentNode ;
Node : : deleteNode ( m_currentNode - > next ) ;
m_currentNode - > next = secondNext ;
m_useNext = true ;
}
} else
{
area . eLine = m_write - > editIf - > numLines ( ) - 1 ;
area . eCol = m_write - > editIf - > lineLength ( area . eLine ) ;
}
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Calling parseArea from slotParseNodeInDetail. " < < endl ;
# endif
TQString areaStartString = m_currentNode - > tag - > tagStr ( ) ;
if ( m_currentNode - > tag - > dtd ( ) - > specialAreaNames [ areaStartString ] . isEmpty ( ) )
{
AreaStruct area2 ( m_currentNode - > tag - > area ( ) ) ;
area . bLine = area2 . eLine ;
area . bCol = area2 . eCol + 1 ;
parseArea ( area , " " , " </ " + m_currentNode - > tag - > name + " \\ s*> " , m_currentNode , true , m_synchronous ) ;
}
else
parseArea ( area , m_currentNode - > tag - > tagStr ( ) , " " , m_currentNode , true , m_synchronous ) ;
} else
{
// Node *node = m_currentNode;
m_currentNode = m_currentNode - > nextSibling ( ) ;
if ( m_currentNode )
{
# ifdef DEBUG_PARSER
// kdDebug(24001) << "Calling slotParseNodeInDetail from slotParseNodeInDetail." << endl; //this is really heavy debug information, enable only when really needed
# endif
m_parseInDetailTimer - > start ( 0 , true ) ;
} else
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Emitting rebuildStructureTree from slotParseNodeInDetail. " < < endl ;
# endif
emit rebuildStructureTree ( false ) ;
}
}
}
}
void SAParser : : setParsingEnabled ( bool enabled )
{
# ifdef DEBUG_PARSER
kdDebug ( 24001 ) < < " Parsing enabled: " < < enabled < < endl ;
# endif
m_parsingEnabled = enabled ;
if ( ! enabled )
{
m_parseOneLineTimer - > stop ( ) ;
m_parseInDetailTimer - > stop ( ) ;
for ( TQValueList < SAGroupParser * > : : Iterator it = m_groupParsers . begin ( ) ; it ! = m_groupParsers . end ( ) ; + + it )
{
( * it ) - > m_parseForGroupTimer - > stop ( ) ;
delete ( * it ) ;
}
m_groupParsers . clear ( ) ;
}
}
void SAParser : : slotGroupParsingDone ( SAGroupParser * groupParser )
{
m_groupParsers . remove ( groupParser ) ;
delete groupParser ;
}
# include "saparser.moc"