From e9ae80694875f869892f13f4fcaf1170a00dea41 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: 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/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- quanta/parsers/parser.cpp | 1757 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1757 insertions(+) create mode 100644 quanta/parsers/parser.cpp (limited to 'quanta/parsers/parser.cpp') diff --git a/quanta/parsers/parser.cpp b/quanta/parsers/parser.cpp new file mode 100644 index 00000000..7559f1ec --- /dev/null +++ b/quanta/parsers/parser.cpp @@ -0,0 +1,1757 @@ +/*************************************************************************** + parser.cpp - description + ------------------- + begin : Sun Sep 1 2002 + copyright : (C) 2002, 2003 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * 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; version 2 of the License. * + * * + ***************************************************************************/ + +//qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//standard library includes +#include +#include +//#include + +//app includes +#include "parser.h" +#include "saparser.h" +#include "parsercommon.h" +#include "node.h" +#include "tag.h" +#include "resource.h" +#include "quantaview.h" +#include "quantacommon.h" +#include "document.h" +#include "qextfileinfo.h" + + +#include "kafkacommon.h" +#include "undoredo.h" + +#include "dtds.h" +#include "structtreetag.h" + +#include "viewmanager.h" + +//kde includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern GroupElementMapList globalGroupMap; +static const QChar space(' '); + +extern int NN; +extern QMap nodes; + +Parser::Parser() +{ + m_node = 0L; + write = 0L; + oldMaxLines = 0; + m_parsingEnabled = true; + m_parsingNeeded = true; + m_parseIncludedFiles = true; + m_saParser = new SAParser(); + connect(m_saParser, SIGNAL(rebuildStructureTree(bool)), SIGNAL(rebuildStructureTree(bool))); + connect(m_saParser, SIGNAL(cleanGroups()), SLOT(cleanGroups())); + ParserCommon::includeWatch = new KDirWatch(); + connect(ParserCommon::includeWatch, SIGNAL(dirty(const QString&)), SLOT(slotIncludedFileChanged(const QString&))); +} + +Parser::~Parser() +{ + delete m_saParser; +} + +/** Parse a string, using as start position sLine, sCol. */ +Node *Parser::parseArea(int startLine, int startCol, int endLine, int endCol, Node **lastNode, Node *a_node) +{ + //first parse as an XML document + QString textLine; + textLine.fill(space, startCol); + int line = startLine; + int col = 0; + int tagStartLine = 0; + int tagEndLine, tagEndCol; + int tagStartPos, specialStartPos; + int lastLineLength; + // if (endCol == 0) + if (endLine > maxLines) + { + if (endLine > 0) + endLine--; + lastLineLength = write->editIf->lineLength(endLine) - 1; + endCol = lastLineLength + 1; + } else + lastLineLength = write->editIf->lineLength(endLine) - 1; + int specialAreaCount = m_dtd->specialAreas.count(); + bool nodeFound = false; + bool goUp; + Node *rootNode = 0L; + Node *parentNode = a_node; + Node *currentNode = a_node; + if (currentNode && (currentNode->tag->type != Tag::XmlTag || + currentNode->tag->single)) + parentNode = currentNode->parent; + Tag *tag = 0L; + QTag *qTag = 0L; + textLine.append(write->text(startLine, startCol, startLine, write->editIf->lineLength(startLine))); + if (line == endLine) + { + if (endCol > 0) + textLine.truncate(endCol + 1); + else + textLine = ""; + } + if (m_dtd->family == Xml) + { + while (line <= endLine) + { + nodeFound = false; + goUp = false; + //find the first "<" and the first special area start definition in this line + tagStartPos = textLine.find('<', col); + specialStartPos = specialAreaCount ? textLine.find(m_dtd->specialAreaStartRx, col): -1; + //if the special area start definition is before the first "<" it means + //that we have found a special area + if ( specialStartPos != -1 && + (specialStartPos <= tagStartPos || tagStartPos == -1) ) + { + currentNode = ParserCommon::createTextNode(write, currentNode, line, specialStartPos, parentNode); + if (!rootNode) + rootNode = currentNode; + QString foundText = m_dtd->specialAreaStartRx.cap(); + //create a toplevel node for the special area + AreaStruct area(line, specialStartPos, line, specialStartPos + foundText.length() - 1); + Node *node = ParserCommon::createScriptTagNode(write, area, foundText, m_dtd, parentNode, currentNode); + if (node->parent && node->prev == node->parent) //some strange cases, but it's possible, eg.: + { + node->prev->next = 0L; + node->prev = 0L; + } + if (node->tag->name.lower().startsWith("comment")) + node->tag->type = Tag::Comment; + + if (!rootNode) + rootNode = node; + + area.eLine = endLine; + area.eCol = endCol; + currentNode = m_saParser->parseArea(area, foundText, "", node, false, true); + line = m_saParser->lastParsedLine(); + textLine = ParserCommon::getLine(write, line, endLine, endCol); + col = m_saParser->lastParsedColumn() + 1; + continue; + } else + //if we have found an XML tag start ("<") + if ( tagStartPos != -1 /*&& + (tagStartPos < specialStartPos || specialStartPos == -1) */) + { + int openNum = 1; + tagStartLine = line; + tagEndLine = endLine; + tagEndCol = lastLineLength; + int sCol = tagStartPos + 1; + int firstStartCol = lastLineLength + 1; + int firstStartLine = endLine; + bool firstOpenFound = false; + bool insideSingleQuotes = false; + bool insideDoubleQuotes = false; + //find the matching ">" in the document + while (line <= endLine && openNum > 0 && !firstOpenFound) + { + textLine = ParserCommon::getLine(write, line, endLine, endCol); + uint textLineLen = textLine.length(); + for (uint i = sCol; i < textLineLen; i++) + { + if (i == 0 || (i > 0 && textLine[i-1] != '\\')) + { + if (textLine[i] == '\'' && !insideDoubleQuotes) + insideSingleQuotes = !insideSingleQuotes; + if (textLine[i] == '"' && !insideSingleQuotes) + insideDoubleQuotes = !insideDoubleQuotes; + } + if (!insideSingleQuotes && !insideDoubleQuotes) + { + if (textLine[i] == '<') + { + openNum++; + if (!firstOpenFound && + (i < textLineLen -1 && (textLine[i + 1] == '/' || textLine[i + 1].isLetter()) || + i == textLineLen -1) + ) + { + firstStartCol = i; + firstStartLine = line; + firstOpenFound = true; + break; + } + } else + if (textLine[i] == '>') openNum--; + } + if (openNum == 0) + { + tagEndCol = i; + tagEndLine = line; + break; + } + } + sCol = 0; + if (openNum != 0) + line++; + } + //the matching closing tag was not found + if (openNum != 0) + { + tagEndLine = firstStartLine; + tagEndCol = firstStartCol - 1; + if (tagEndCol < 0) + { + tagEndLine--; + if (tagEndLine < 0) + tagEndLine = 0; + tagEndCol = write->editIf->lineLength(tagEndLine); + } + line = tagEndLine; + textLine = ParserCommon::getLine(write, line, endLine, endCol); + } + col = tagEndCol; + nodeFound = true; + //build an xml tag node here + AreaStruct area(tagStartLine, tagStartPos, tagEndLine, tagEndCol); + tag = new Tag(area, write, m_dtd, true); + QString tagStr = tag->tagStr(); + tag->type = Tag::XmlTag; + tag->validXMLTag = (openNum == 0); + tag->single = QuantaCommon::isSingleTag(m_dtd->name, tag->name); + if (tag->isClosingTag()) + { + tag->type = Tag::XmlTagEnd; + tag->single = true; + } + if (tagStr.right(2) == "/>" || tag->name.isEmpty()) + { + tag->single = true; + if (tag->name.length() > 1 && tag->name.endsWith("/")) + tag->name.truncate(tag->name.length() - 1); + } + //the tag we found indicates the beginning of a special area, like