RedPanda-CPP/RedPandaIDE/parser/cpppreprocessor.h

194 lines
6.3 KiB
C
Raw Normal View History

2021-08-05 23:13:21 +08:00
#ifndef CPPPREPROCESSOR_H
#define CPPPREPROCESSOR_H
#include <QObject>
2021-08-07 18:02:57 +08:00
#include <QTextStream>
#include "parserutils.h"
2021-08-07 18:02:57 +08:00
2021-08-10 21:27:24 +08:00
#define MAX_DEFINE_EXPAND_DEPTH 20
2021-08-27 23:51:42 +08:00
enum class DefineArgTokenType{
Symbol,
Identifier,
Space,
Sharp,
DSharp,
Other
};
struct DefineArgToken {
QString value;
DefineArgTokenType type;
};
using PDefineArgToken = std::shared_ptr<DefineArgToken>;
2021-08-10 21:27:24 +08:00
2021-08-07 18:02:57 +08:00
struct ParsedFile {
int index; // 0-based for programming convenience
QString fileName; // Record filename, but not used now
QStringList buffer; // do not concat them all
int branches; //branch levels;
PFileIncludes fileIncludes; // includes of this file
};
using PParsedFile = std::shared_ptr<ParsedFile>;
2021-08-05 23:13:21 +08:00
2021-08-14 22:52:37 +08:00
class CppPreprocessor
2021-08-05 23:13:21 +08:00
{
enum class ContentType {
AnsiCComment,
CppComment,
String,
Character,
EscapeSequence,
RawStringPrefix,
RawString,
Other
};
2021-08-05 23:13:21 +08:00
public:
2021-08-07 18:02:57 +08:00
2021-08-14 22:52:37 +08:00
explicit CppPreprocessor();
2021-08-08 17:22:37 +08:00
void clear();
void addDefineByParts(const QString& name, const QString& args,
const QString& value, bool hardCoded);
void getDefineParts(const QString& input, QString &name, QString &args, QString &value);
2021-08-08 17:22:37 +08:00
void addDefineByLine(const QString& line, bool hardCoded);
PDefine getDefine(const QString& name);
PDefine getHardDefine(const QString& name);
2021-08-08 17:22:37 +08:00
void reset(); //reset but don't clear generated defines
void resetDefines();
void setScanOptions(bool parseSystem, bool parseLocal);
void preprocess(const QString& fileName, QStringList buffer = QStringList());
2021-08-08 17:22:37 +08:00
void invalidDefinesInFile(const QString& fileName);
2021-08-21 22:15:44 +08:00
void dumpDefinesTo(const QString& fileName) const;
void dumpIncludesListTo(const QString& fileName) const;
QStringList result() const;
QHash<QString, PFileIncludes> &includesList();
QSet<QString> &scannedFiles();
QSet<QString> &includePaths();
QSet<QString> &projectIncludePaths();
2021-08-22 23:48:00 +08:00
const DefineMap &hardDefines() const;
2021-08-05 23:13:21 +08:00
signals:
2021-08-07 18:02:57 +08:00
private:
void preprocessBuffer();
void skipToEndOfPreprocessor();
void skipToPreprocessor();
QString getNextPreprocessor();
void simplify(QString& output);
void handleBranch(const QString& line);
2021-08-08 17:22:37 +08:00
void handleDefine(const QString& line);
2021-08-07 18:02:57 +08:00
void handleInclude(const QString& line);
2021-08-08 17:22:37 +08:00
void handlePreprocessor(const QString& value);
void handleUndefine(const QString& line);
2021-08-07 18:02:57 +08:00
QString expandMacros(const QString& line, int depth);
2021-08-07 23:30:01 +08:00
void expandMacro(const QString& line, QString& newLine, QString& word, int& i, int depth);
2021-08-07 18:02:57 +08:00
QString removeGCCAttributes(const QString& line);
2021-08-12 21:25:13 +08:00
void removeGCCAttribute(const QString&line, QString& newLine, int &i, const QString& word);
2021-08-07 18:02:57 +08:00
// current file stuff
PParsedFile getInclude(int index);
void openInclude(const QString& fileName, QStringList bufferedText=QStringList());
2021-08-07 18:02:57 +08:00
void closeInclude();
2021-08-07 23:30:01 +08:00
2021-08-07 18:02:57 +08:00
// branch stuff
bool getCurrentBranch();
void setCurrentBranch(bool value);
void removeCurrentBranch();
// include stuff
PFileIncludes getFileIncludesEntry(const QString& FileName);
void addDefinesInFile(const QString& fileName);
2021-08-07 23:30:01 +08:00
2021-08-12 21:25:13 +08:00
void parseArgs(PDefine define);
2021-08-27 23:51:42 +08:00
QList<PDefineArgToken> tokenizeValue(const QString& value);
2021-08-12 21:25:13 +08:00
QStringList removeComments(const QStringList& text);
2021-08-09 09:11:10 +08:00
/*
* '_','a'..'z','A'..'Z','0'..'9'
*/
bool isWordChar(const QChar& ch);
/*
* 'A'..'Z', '0'..'9', 'a'..'z', '_', '*', '&', '~'
*/
2021-08-07 23:30:01 +08:00
bool isIdentChar(const QChar& ch);
2021-08-09 09:47:36 +08:00
/*
* '\r','\n'
*/
bool isLineChar(const QChar& ch);
/*
* '\t' ' '
*/
bool isSpaceChar(const QChar& ch);
/*
* '+', '-', '*', '/', '!', '=', '<', '>', '&', '|', '^'
*/
bool isOperatorChar(const QChar& ch);
/*
* 'A'..'Z', 'a'..'z', '_'
*/
bool isMacroIdentChar(const QChar& ch);
2021-08-08 17:22:37 +08:00
2021-08-10 12:09:48 +08:00
/*
* '0'..'9'
*/
bool isDigit(const QChar& ch);
/*
* '0'..'9','x',X','a'..'f','A'..'F','u','U','l','L'
*/
bool isNumberChar(const QChar& ch);
2021-08-08 17:22:37 +08:00
QString lineBreak();
2021-08-09 09:11:10 +08:00
bool evaluateIf(const QString& line);
2021-08-10 12:09:48 +08:00
QString expandDefines(QString line);
bool skipBraces(const QString&line, int& index, int step = 1);
QString expandFunction(PDefine define,QString args);
bool skipSpaces(const QString &expr, int& pos);
bool evalNumber(const QString &expr, int& result, int& pos);
2021-08-10 12:09:48 +08:00
bool evalTerm(const QString &expr, int& result, int& pos);
bool evalUnaryExpr(const QString &expr, int& result, int& pos);
bool evalMulExpr(const QString &expr, int& result, int& pos);
bool evalAddExpr(const QString &expr, int& result, int& pos);
bool evalShiftExpr(const QString &expr, int& result, int& pos);
bool evalRelationExpr(const QString &expr, int& result, int& pos);
bool evalEqualExpr(const QString &expr, int& result, int& pos);
bool evalBitAndExpr(const QString &expr, int& result, int& pos);
bool evalBitXorExpr(const QString &expr, int& result, int& pos);
bool evalBitOrExpr(const QString &expr, int& result, int& pos);
bool evalLogicAndExpr(const QString &expr, int& result, int& pos);
bool evalLogicOrExpr(const QString &expr, int& result, int& pos);
bool evalExpr(const QString &expr, int& result, int& pos);
int evaluateExpression(QString line);
2021-08-07 18:02:57 +08:00
private:
int mIndex; // points to current file buffer. do not free
QString mFileName; // idem
QStringList mBuffer; // idem
QStringList mResult;
PFileIncludes mCurrentIncludes;
int mPreProcIndex;
2021-08-21 22:15:44 +08:00
QHash<QString,PFileIncludes> mIncludesList;
2021-08-07 18:02:57 +08:00
DefineMap mHardDefines; // set by "cpp -dM -E -xc NUL"
DefineMap mDefines; // working set, editable
QHash<QString, PDefineMap> mFileDefines; //dictionary to save defines for each headerfile;
QList<PParsedFile> mIncludes; // stack of files we've stepped into. last one is current file, first one is source file
2021-08-07 23:30:01 +08:00
QList<bool> mBranchResults;// stack of branch results (boolean). last one is current branch, first one is outermost branch
2021-08-21 22:15:44 +08:00
//{ List of current compiler set's include path}
QSet<QString> mIncludePaths;
//{ List of current project's include path }
2021-08-19 23:49:23 +08:00
QSet<QString> mProjectIncludePaths;
2021-08-21 22:15:44 +08:00
2021-08-07 18:02:57 +08:00
bool mParseSystem;
bool mParseLocal;
2021-08-21 22:15:44 +08:00
QSet<QString> mScannedFiles;
2021-08-07 18:02:57 +08:00
QSet<QString> mProcessed; // dictionary to save filename already processed
2021-08-05 23:13:21 +08:00
};
#endif // CPPPREPROCESSOR_H