diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 1486a361..0836043c 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -16,6 +16,7 @@ SOURCES += \ compiler/executablerunner.cpp \ compiler/filecompiler.cpp \ compiler/stdincompiler.cpp \ + parser/cppparser.cpp \ parser/cpppreprocessor.cpp \ parser/cpptokenizer.cpp \ parser/parserutils.cpp \ @@ -77,6 +78,7 @@ HEADERS += \ compiler/executablerunner.h \ compiler/filecompiler.h \ compiler/stdincompiler.h \ + parser/cppparser.h \ parser/cpppreprocessor.h \ parser/cpptokenizer.h \ parser/parserutils.h \ diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp new file mode 100644 index 00000000..a0b59297 --- /dev/null +++ b/RedPandaIDE/parser/cppparser.cpp @@ -0,0 +1,6 @@ +#include "cppparser.h" + +CppParser::CppParser(QObject *parent) : QObject(parent) +{ + +} diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h new file mode 100644 index 00000000..8f5613e2 --- /dev/null +++ b/RedPandaIDE/parser/cppparser.h @@ -0,0 +1,65 @@ +#ifndef CPPPARSER_H +#define CPPPARSER_H + +#include +#include "statementmodel.h" +#include "cpptokenizer.h" +#include "cpppreprocessor.h" + +class CppParser : public QObject +{ + Q_OBJECT +public: + explicit CppParser(QObject *parent = nullptr); + +signals: +private: + int mParserId; + int mSerialCount; + int mSerialId; + int mUniqId; + bool mEnabled; + int mIndex; + bool mIsHeader; + bool mIsSystemHeader; + QString mCurrentFile; +// stack list , each element is a list of one/many scopes(like intypedef struct s1,s2; +// It's used for store scope nesting infos + QVector mCurrentScope; + QVector mCurrentClassScope; + +// the start index in tokens to skip to ; when parsing typedef struct we need to skip +// the names after the closing bracket because we have processed it + QVector mSkipList; // TList + StatementClassScope mClassScope; + StatementModel mStatementList; + std::shared_ptr> mIncludesList; //List of scaned files and it's infos + //It's used in preprocessor, so we can't use fIncludeList instead + std::shared_ptr> mScannedFiles; // List of scaned file names + CppTokenizer mTokenizer; + CppPreprocessor mPreprocessor; + { List of current compiler set's include path} + fIncludePaths: TStringList; + { List of current project's include path } + fProjectIncludePaths: TStringList; + { List of current project's include path } + fProjectFiles: TStringList; + fBlockBeginSkips: TIntList; //list of for/catch block begin token index; + fBlockEndSkips: TIntList; //list of for/catch block end token index; + fInlineNamespaceEndSkips: TIntList; // list for inline namespace end token index; + fFilesToScan: TStringList; // list of base files to scan + fFilesScannedCount: Integer; // count of files that have been scanned + fFilesToScanCount: Integer; // count of files and files included in files that have to be scanned + fParseLocalHeaders: boolean; + fParseGlobalHeaders: boolean; + fIsProjectFile: boolean; + //fMacroDefines : TList; + fLockCount: integer; // lock(don't reparse) when we need to find statements in a batch + fParsing: boolean; + fNamespaces :TDevStringList; //TStringList> namespace and the statements in its scope + //fRemovedStatements: THashedStringList; //THashedStringList + fCriticalSection: TCriticalSection; + fOnGetFileStream : TGetFileStreamEvent; +}; + +#endif // CPPPARSER_H diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 5fee2ced..cc145b86 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -4,7 +4,7 @@ #include #include -CppPreprocessor::CppPreprocessor(QObject *parent) : QObject(parent) +CppPreprocessor::CppPreprocessor() { } diff --git a/RedPandaIDE/parser/cpppreprocessor.h b/RedPandaIDE/parser/cpppreprocessor.h index 2aebac18..7e16e3be 100644 --- a/RedPandaIDE/parser/cpppreprocessor.h +++ b/RedPandaIDE/parser/cpppreprocessor.h @@ -16,10 +16,8 @@ struct ParsedFile { }; using PParsedFile = std::shared_ptr; -class CppPreprocessor : public QObject +class CppPreprocessor { - Q_OBJECT - enum class ContentType { AnsiCComment, CppComment, @@ -33,7 +31,7 @@ class CppPreprocessor : public QObject public: - explicit CppPreprocessor(QObject *parent = nullptr); + explicit CppPreprocessor(); void clear(); void addDefineByParts(const QString& name, const QString& args, const QString& value, bool hardCoded); diff --git a/RedPandaIDE/parser/cpptokenizer.cpp b/RedPandaIDE/parser/cpptokenizer.cpp index bde584f7..480bfa2a 100644 --- a/RedPandaIDE/parser/cpptokenizer.cpp +++ b/RedPandaIDE/parser/cpptokenizer.cpp @@ -1,15 +1,25 @@ #include "cpptokenizer.h" -cpptokenizer::cpptokenizer(QObject *parent) : QObject(parent) +#include +#include + +CppTokenizer::CppTokenizer() { } -void cpptokenizer::tokenize(const QStringList &buffer) +void CppTokenizer::reset() +{ + mTokenList.clear(); + mBuffer.clear(); + mBufferStr.clear(); +} + +void CppTokenizer::tokenize(const QStringList &buffer) { reset(); + mBuffer = buffer; - mBufferStr.clear(); if (mBuffer.isEmpty()) return; mBufferStr = mBuffer[0]; @@ -35,7 +45,19 @@ void cpptokenizer::tokenize(const QStringList &buffer) } } -void cpptokenizer::addToken(const QString &sText, int iLine) +void CppTokenizer::dumpTokens(const QString &fileName) +{ + QFile file(fileName); + + if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + QTextStream stream(&file); + for (PToken token:mTokenList) { + stream<line).arg(token->text)<(); token->text = sText; @@ -43,7 +65,7 @@ void cpptokenizer::addToken(const QString &sText, int iLine) mTokenList.append(token); } -void cpptokenizer::countLines() +void CppTokenizer::countLines() { while ((*mLineCount != '\0') && (mLineCount < mCurrent)) { if (*mLineCount == '\n') @@ -52,7 +74,7 @@ void cpptokenizer::countLines() } } -QString cpptokenizer::getArguments() +QString CppTokenizer::getArguments() { QChar* offset = mCurrent; skipPair('(', ')'); @@ -74,7 +96,7 @@ QString cpptokenizer::getArguments() return result; } -QString cpptokenizer::getForInit() +QString CppTokenizer::getForInit() { QChar* startOffset = mCurrent; @@ -98,7 +120,7 @@ QString cpptokenizer::getForInit() return ""; } -QString cpptokenizer::getNextToken(bool bSkipParenthesis, bool bSkipArray, bool bSkipBlock) +QString CppTokenizer::getNextToken(bool bSkipParenthesis, bool bSkipArray, bool bSkipBlock) { QString result; bool done = false; @@ -179,7 +201,7 @@ QString cpptokenizer::getNextToken(bool bSkipParenthesis, bool bSkipArray, bool return result; } -QString cpptokenizer::getNumber() +QString CppTokenizer::getNumber() { QChar* offset = mCurrent; @@ -190,7 +212,7 @@ QString cpptokenizer::getNumber() } QString result; - if (offset != mpCurrent) { + if (offset != mCurrent) { result = QString(offset,mCurrent-offset); if (*mCurrent=='.') // keep '.' for decimal result += *mCurrent; @@ -198,14 +220,14 @@ QString cpptokenizer::getNumber() return result; } -QString cpptokenizer::getPreprocessor() +QString CppTokenizer::getPreprocessor() { QChar *offset = mCurrent; skipToEOL(); return QString(offset, mCurrent-offset); } -QString cpptokenizer::getWord(bool bSkipParenthesis, bool bSkipArray, bool bSkipBlock) +QString CppTokenizer::getWord(bool bSkipParenthesis, bool bSkipArray, bool bSkipBlock) { bool bFoundTemplate = false; // bIsSmartPointer:=False; @@ -288,27 +310,27 @@ QString cpptokenizer::getWord(bool bSkipParenthesis, bool bSkipArray, bool bSkip return result; } -bool cpptokenizer::isArguments() +bool CppTokenizer::isArguments() { return *mCurrent == '('; } -bool cpptokenizer::isForInit() +bool CppTokenizer::isForInit() { return (*mCurrent == '(') && (mLastToken == "for"); } -bool cpptokenizer::isNumber() +bool CppTokenizer::isNumber() { return isDigitChar(*mCurrent); } -bool cpptokenizer::isPreprocessor() +bool CppTokenizer::isPreprocessor() { return *mCurrent=='#'; } -bool cpptokenizer::isWord() +bool CppTokenizer::isWord() { bool result = isLetterChar(*mCurrent); if (result && (*(mCurrent+1) == '"')) @@ -316,7 +338,7 @@ bool cpptokenizer::isWord() return result; } -void cpptokenizer::simplify(QString &output) +void CppTokenizer::simplify(QString &output) { //remove \n \r; QString temp; @@ -327,7 +349,7 @@ void cpptokenizer::simplify(QString &output) output = temp.trimmed(); } -void cpptokenizer::simplifyArgs(QString &output) +void CppTokenizer::simplifyArgs(QString &output) { QString temp; QString lastSpace = ""; @@ -360,7 +382,7 @@ void cpptokenizer::simplifyArgs(QString &output) output = temp; } -void cpptokenizer::skipAssignment() +void CppTokenizer::skipAssignment() { while (true) { switch ((*mCurrent).unicode()) { @@ -390,7 +412,7 @@ void cpptokenizer::skipAssignment() } } -void cpptokenizer::skipDoubleQuotes() +void CppTokenizer::skipDoubleQuotes() { mCurrent++; while (!(*mCurrent=='"' || *mCurrent == '\0')) { @@ -404,7 +426,7 @@ void cpptokenizer::skipDoubleQuotes() } } -void cpptokenizer::skipPair(const QChar &cStart, const QChar cEnd, const QSet& failChars) +void CppTokenizer::skipPair(const QChar &cStart, const QChar cEnd, const QSet& failChars) { mCurrent++; while (*mCurrent != '\0') { @@ -442,7 +464,7 @@ void cpptokenizer::skipPair(const QChar &cStart, const QChar cEnd, const QSetunicode()) { case '\"': skipDoubleQuotes(); @@ -571,7 +593,7 @@ void cpptokenizer::advance() } } -bool cpptokenizer::isLetterChar(const QChar &ch) +bool CppTokenizer::isLetterChar(const QChar &ch) { return (ch>= 'A' && ch<='Z') || (ch>='a' && ch<='z') @@ -581,7 +603,7 @@ bool cpptokenizer::isLetterChar(const QChar &ch) || ch == '~'; } -bool cpptokenizer::isHexChar(const QChar &ch) +bool CppTokenizer::isHexChar(const QChar &ch) { return (ch >= 'A' && ch<='F') || (ch>='a' && ch<='f') @@ -589,27 +611,27 @@ bool cpptokenizer::isHexChar(const QChar &ch) || ch == 'L'; } -bool cpptokenizer::isDigitChar(const QChar &ch) +bool CppTokenizer::isDigitChar(const QChar &ch) { return (ch>='0' && ch<='9'); } -bool cpptokenizer::isSpaceChar(const QChar &ch) +bool CppTokenizer::isSpaceChar(const QChar &ch) { return (ch == ' ' || ch == '\t'); } -bool cpptokenizer::isLineChar(const QChar &ch) +bool CppTokenizer::isLineChar(const QChar &ch) { return (ch=='\n' || ch=='\r'); } -bool cpptokenizer::isBlankChar(const QChar &ch) +bool CppTokenizer::isBlankChar(const QChar &ch) { return (ch<=32); } -bool cpptokenizer::isOperatorChar(const QChar &ch) +bool CppTokenizer::isOperatorChar(const QChar &ch) { switch (ch.unicode()) { case '+': @@ -632,7 +654,7 @@ bool cpptokenizer::isOperatorChar(const QChar &ch) } } -bool cpptokenizer::currentWordEquals(QChar *wordStart, QChar *wordEnd, const QString& text) +bool CppTokenizer::currentWordEquals(QChar *wordStart, QChar *wordEnd, const QString& text) { QString currentWord(wordStart, wordEnd-wordStart); return currentWord == text; diff --git a/RedPandaIDE/parser/cpptokenizer.h b/RedPandaIDE/parser/cpptokenizer.h index 1f241e03..9f2d12bf 100644 --- a/RedPandaIDE/parser/cpptokenizer.h +++ b/RedPandaIDE/parser/cpptokenizer.h @@ -4,9 +4,8 @@ #include #include "parserutils.h" -class cpptokenizer : public QObject +class CppTokenizer { - Q_OBJECT public: struct Token { QString text; @@ -14,7 +13,7 @@ public: }; using PToken = std::shared_ptr; using TokenList = QVector; - explicit cpptokenizer(QObject *parent = nullptr); + explicit CppTokenizer(); void reset(); void tokenize(const QStringList& buffer);