File indexing completed on 2024-04-28 12:21:23

0001 /*****************************************************************************
0002  * Copyright (c) 2007 Andreas Pakulat <apaku@gmx.de>                         *
0003  * Copyright (c) 2007 Piyush verma <piyush.verma@gmail.com>                  *
0004  * Copyright (c) 2008 Niko Sams <niko.sams@gmail.com>                        *
0005  *                                                                           *
0006  * Permission is hereby granted, free of charge, to any person obtaining     *
0007  * a copy of this software and associated documentation files (the           *
0008  * "Software"), to deal in the Software without restriction, including       *
0009  * without limitation the rights to use, copy, modify, merge, publish,       *
0010  * distribute, sublicense, and/or sell copies of the Software, and to        *
0011  * permit persons to whom the Software is furnished to do so, subject to     *
0012  * the following conditions:                                                 *
0013  *                                                                           *
0014  * The above copyright notice and this permission notice shall be            *
0015  * included in all copies or substantial portions of the Software.           *
0016  *                                                                           *
0017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,           *
0018  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF        *
0019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                     *
0020  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE    *
0021  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION    *
0022  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION     *
0023  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.           *
0024  *****************************************************************************/
0025 #include "parsesession.h"
0026 
0027 #include "cssast.h"
0028 #include "debug.h"
0029 
0030 #include "kdev-pg-memory-pool.h"
0031 #include "kdev-pg-token-stream.h"
0032 
0033 #include <QFile>
0034 #include <QTextCodec>
0035 #include <KLocalizedString>
0036 
0037 namespace Css
0038 {
0039 
0040 ParseSession::ParseSession()
0041         :   m_debug(false),
0042         m_pool(new KDevPG::MemoryPool()),
0043         m_tokenStream(new KDevPG::TokenStream())
0044 {
0045 }
0046 ParseSession::~ParseSession()
0047 {
0048     delete m_pool;
0049     delete m_tokenStream;
0050 }
0051 
0052 QString ParseSession::contents() const
0053 {
0054     return m_contents;
0055 }
0056 
0057 KDevelop::IndexedString ParseSession::currentDocument() const
0058 {
0059     return m_currentDocument;
0060 }
0061 
0062 void ParseSession::setContents(const QString& contents)
0063 {
0064     m_contents = contents;
0065 }
0066 
0067 void ParseSession::setCurrentDocument(const KDevelop::IndexedString& filename)
0068 {
0069     m_currentDocument = filename;
0070 }
0071 
0072 bool ParseSession::readFile(const QString& filename, const char* codec)
0073 {
0074     m_currentDocument = KDevelop::IndexedString(filename);
0075 
0076     QFile f(filename);
0077     if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
0078         qCDebug(KDEV_CSS) << "Couldn't open project file:" << filename;
0079         return false;
0080     }
0081     QTextStream s(&f);
0082     if (codec)
0083         s.setCodec(QTextCodec::codecForName(codec));
0084     m_contents = s.readAll();
0085     return true;
0086 }
0087 
0088 void ParseSession::setDebug(bool debug)
0089 {
0090     m_debug = debug;
0091 }
0092 
0093 void ParseSession::setOffset(const KDevelop::CursorInRevision& offset)
0094 {
0095     m_offset = offset;
0096 }
0097 
0098 KDevPG::TokenStream* ParseSession::tokenStream() const
0099 {
0100     return m_tokenStream;
0101 }
0102 
0103 Parser* ParseSession::createParser()
0104 {
0105     Parser* parser = new Parser;
0106     parser->setTokenStream(m_tokenStream);
0107     parser->setMemoryPool(m_pool);
0108     parser->setDebug(m_debug);
0109     parser->setCurrentDocument(m_currentDocument);
0110 
0111     parser->tokenize(m_contents);
0112     return parser;
0113 }
0114 
0115 bool ParseSession::parse(Css::StartAst** ast)
0116 {
0117     Parser* parser = createParser();
0118     StartAst* cssAst;
0119     bool matched = parser->parseStart(&cssAst);
0120     *ast = cssAst;
0121     if (matched) {
0122         qCDebug(KDEV_CSS) << "Successfully parsed";
0123     } else {
0124         parser->expectedSymbol(AstNode::StartKind, "start");
0125         qCDebug(KDEV_CSS) << "Couldn't parse content";
0126     }
0127     m_problems << parser->problems();
0128     delete parser;
0129     return matched;
0130 }
0131 
0132 bool ParseSession::parse(DeclarationListAst** ast)
0133 {
0134     Parser* parser = createParser();
0135     DeclarationListAst* cssAst;
0136     bool matched = parser->parseDeclarationList(&cssAst);
0137     *ast = cssAst;
0138     if (matched) {
0139         qCDebug(KDEV_CSS) << "Successfully parsed";
0140     } else {
0141         parser->expectedSymbol(AstNode::DeclarationListKind, "declarationList");
0142         qCDebug(KDEV_CSS) << "Couldn't parse content";
0143     }
0144     m_problems << parser->problems();
0145     delete parser;
0146     return matched;
0147 }
0148 
0149 KDevelop::CursorInRevision ParseSession::positionAt(qint64 offset) const
0150 {
0151     qint64 line, column;
0152     m_tokenStream->locationTable()->positionAt(offset, &line, &column);
0153     if (m_offset.isValid()) {
0154         if (line == 0) column += m_offset.column;
0155         line += m_offset.line;
0156     }
0157     return KDevelop::CursorInRevision(line, column);
0158 }
0159 
0160 QString ParseSession::symbol(qint64 token) const
0161 {
0162     const KDevPG::TokenStream::Token& tok = m_tokenStream->at(token);
0163     return m_contents.mid(tok.begin, tok.end - tok.begin + 1);
0164 }
0165 
0166 QString ParseSession::symbol(AstNode* node) const
0167 {
0168     const KDevPG::TokenStream::Token& startTok = m_tokenStream->at(node->startToken);
0169     const KDevPG::TokenStream::Token& endTok = m_tokenStream->at(node->endToken);
0170     return m_contents.mid(startTok.begin, endTok.end - startTok.begin + 1);
0171 }
0172 
0173 QList<KDevelop::ProblemPointer> ParseSession::problems()
0174 {
0175     return m_problems;
0176 }
0177 
0178 }