feat(CppParser): C++11 attributes support

This commit is contained in:
Günter Obiltschnig 2024-02-05 21:05:12 +01:00
parent ad07839db9
commit 568b0fca8e
12 changed files with 94 additions and 30 deletions

View File

@ -32,8 +32,8 @@ class CppParser_API Attributes
/// name and values are strings. /// name and values are strings.
{ {
public: public:
typedef std::map<std::string, std::string> AttrMap; using AttrMap = std::map<std::string, std::string>;
typedef AttrMap::const_iterator Iterator; using Iterator = AttrMap::const_iterator;
Attributes(); Attributes();
/// Creates the Attributes object. /// Creates the Attributes object.

View File

@ -46,6 +46,8 @@ public:
{ {
OP_OPENBRACKET = 1, // [ OP_OPENBRACKET = 1, // [
OP_CLOSBRACKET, // ] OP_CLOSBRACKET, // ]
OP_DBL_OPENBRACKET, // [[
OP_DBL_CLOSBRACKET, // ]]
OP_OPENPARENT, // ( OP_OPENPARENT, // (
OP_CLOSPARENT, // ) OP_CLOSPARENT, // )
OP_OPENBRACE, // { OP_OPENBRACE, // {
@ -101,7 +103,7 @@ public:
int asInteger() const; int asInteger() const;
private: private:
typedef std::map<std::string, int> OpMap; using OpMap = std::map<std::string, int>;
OpMap _opMap; OpMap _opMap;
}; };
@ -112,7 +114,7 @@ class CppParser_API IdentifierToken: public CppToken
public: public:
enum Keywords enum Keywords
{ {
KW_ALIGNAS = 1, KW_ALIGNAS = 100, // Note: start with 100 to avoid overlapping definitions with operators
KW_ALIGNOF, KW_ALIGNOF,
KW_AND, KW_AND,
KW_AND_EQ, KW_AND_EQ,
@ -206,7 +208,7 @@ public:
int asInteger() const; int asInteger() const;
private: private:
typedef std::map<std::string, int> KWMap; using KWMap = std::map<std::string, int>;
KWMap _kwMap; KWMap _kwMap;
}; };

View File

@ -28,7 +28,7 @@ namespace CppParser {
class CppParser_API Decl: public Symbol class CppParser_API Decl: public Symbol
/// This class represents a simple declaration in a C++ source file. /// This class represents a simple declaration in a C++ source file.
/// It is a base class for Function, TypeDef or Variable. /// It is a base class for Function, TypeDef, Using or Variable.
{ {
public: public:
Decl(const std::string& decl, NameSpace* pNameSpace); Decl(const std::string& decl, NameSpace* pNameSpace);

View File

@ -37,8 +37,8 @@ class CppParser_API Enum: public Symbol
/// a collection of EnumValues. /// a collection of EnumValues.
{ {
public: public:
typedef std::vector<EnumValue*> Values; using Values = std::vector<EnumValue*>;
typedef Values::const_iterator Iterator; using Iterator = Values::const_iterator;
enum Flags enum Flags
{ {

View File

@ -49,8 +49,8 @@ public:
FN_DELETE = 1024 /// The function has been deleted. FN_DELETE = 1024 /// The function has been deleted.
}; };
typedef std::vector<Parameter*> Parameters; using Parameters = std::vector<Parameter*>;
typedef Parameters::const_iterator Iterator; using Iterator = Parameters::const_iterator;
Function(const std::string& decl, NameSpace* pNameSpace); Function(const std::string& decl, NameSpace* pNameSpace);
/// Creates the Function. /// Creates the Function.

View File

@ -33,10 +33,10 @@ class CppParser_API NameSpace: public Symbol
/// This class represents a namespace. /// This class represents a namespace.
{ {
public: public:
typedef std::multimap<std::string, Symbol*> SymbolTable; using SymbolTable = std::multimap<std::string, Symbol*>;
typedef SymbolTable::const_iterator Iterator; using Iterator = SymbolTable::const_iterator;
typedef std::map<std::string, std::string> AliasMap; using AliasMap = std::map<std::string, std::string>;
typedef std::vector<std::string> NameSpaceVec; using NameSpaceVec = std::vector<std::string>;
NameSpace(); NameSpace();
/// Creates the NameSpace. /// Creates the NameSpace.

View File

@ -73,7 +73,7 @@ protected:
const Poco::Token* parseExtern(const Poco::Token* pNext); const Poco::Token* parseExtern(const Poco::Token* pNext);
const Poco::Token* parseTypeDef(const Poco::Token* pNext); const Poco::Token* parseTypeDef(const Poco::Token* pNext);
const Poco::Token* parseUsing(const Poco::Token* pNext); const Poco::Token* parseUsing(const Poco::Token* pNext);
const Poco::Token* parseFunc(const Poco::Token* pNext, std::string& decl); const Poco::Token* parseFunc(const Poco::Token* pNext, const std::string& attrs, std::string& decl);
const Poco::Token* parseParameters(const Poco::Token* pNext, Function* pFunc); const Poco::Token* parseParameters(const Poco::Token* pNext, Function* pFunc);
const Poco::Token* parseBlock(const Poco::Token* pNext); const Poco::Token* parseBlock(const Poco::Token* pNext);
const Poco::Token* parseEnum(const Poco::Token* pNext); const Poco::Token* parseEnum(const Poco::Token* pNext);
@ -82,6 +82,7 @@ protected:
const Poco::Token* parseClassMembers(const Poco::Token* pNext, Struct* pClass); const Poco::Token* parseClassMembers(const Poco::Token* pNext, Struct* pClass);
const Poco::Token* parseAccess(const Poco::Token* pNext); const Poco::Token* parseAccess(const Poco::Token* pNext);
const Poco::Token* parseIdentifier(const Poco::Token* pNext, std::string& id); const Poco::Token* parseIdentifier(const Poco::Token* pNext, std::string& id);
const Poco::Token* parseAttributes(const Poco::Token* pNext, std::string& attrs);
void addSymbol(Symbol* pSymbol, int lineNumber, bool addGST = true); void addSymbol(Symbol* pSymbol, int lineNumber, bool addGST = true);
void pushNameSpace(NameSpace* pNameSpace, int lineNumber, bool addGST = true); void pushNameSpace(NameSpace* pNameSpace, int lineNumber, bool addGST = true);
@ -102,7 +103,7 @@ protected:
const Poco::Token* nextToken(); const Poco::Token* nextToken();
private: private:
typedef std::vector<NameSpace*> NSStack; using NSStack = std::vector<NameSpace*>;
NameSpace::SymbolTable& _gst; NameSpace::SymbolTable& _gst;
Poco::CountingInputStream _istr; Poco::CountingInputStream _istr;

View File

@ -51,13 +51,13 @@ public:
Struct* pClass; Struct* pClass;
}; };
typedef std::vector<Base> BaseClasses; using BaseClasses = std::vector<Base>;
typedef BaseClasses::const_iterator BaseIterator; using BaseIterator = BaseClasses::const_iterator;
typedef std::vector<Struct*> StructVec; using StructVec = std::vector<Struct*>;
typedef StructVec::const_iterator DerivedIterator; using DerivedIterator = StructVec::const_iterator;
typedef std::vector<Function*> Functions; using Functions = std::vector<Function*>;
typedef std::set<Function*> FunctionSet; using FunctionSet = std::set<Function*>;
typedef std::set<Struct*> StructSet; using StructSet = std::set<Struct*>;
Struct(const std::string& decl, bool isClass, NameSpace* pNameSpace); Struct(const std::string& decl, bool isClass, NameSpace* pNameSpace);
/// Creates the Struct. /// Creates the Struct.

View File

@ -85,6 +85,13 @@ public:
Access getAccess() const; Access getAccess() const;
/// Returns the symbol's access. /// Returns the symbol's access.
void setAttributeList(const std::string& attrs);
/// Sets the C++11 attribute list, e.g. "[[noreturn]]".
const std::string& getAttributeList() const;
/// Returns the C++11 attribute list, or an empty string
/// if the symbol does not have one.
void setDocumentation(const std::string& text); void setDocumentation(const std::string& text);
/// Sets the symbol's documentation. /// Sets the symbol's documentation.
@ -169,6 +176,7 @@ private:
std::string _package; std::string _package;
std::string _library; std::string _library;
Attributes _attrs; Attributes _attrs;
std::string _attributeList;
static int _nextId; static int _nextId;
}; };
@ -189,6 +197,12 @@ inline const std::string& Symbol::name() const
} }
inline const std::string& Symbol::getAttributeList() const
{
return _attributeList;
}
inline const std::string& Symbol::getDocumentation() const inline const std::string& Symbol::getDocumentation() const
{ {
return _documentation; return _documentation;

View File

@ -49,9 +49,11 @@ void CppToken::syntaxError(const std::string& expected, const std::string& actua
OperatorToken::OperatorToken() OperatorToken::OperatorToken()
{ {
int i = 1; int i = OP_OPENBRACKET;
_opMap["["] = i++; _opMap["["] = i++;
_opMap["]"] = i++; _opMap["]"] = i++;
_opMap["[["] = i++;
_opMap["]]"] = i++;
_opMap["("] = i++; _opMap["("] = i++;
_opMap[")"] = i++; _opMap[")"] = i++;
_opMap["{"] = i++; _opMap["{"] = i++;
@ -159,13 +161,23 @@ void OperatorToken::finish(std::istream& istr)
case ')': case ')':
case '{': case '{':
case '}': case '}':
case '[':
case ']':
case ';': case ';':
case '?': case '?':
case '~': case '~':
case ',': case ',':
break; break;
case '[':
if (next == '[')
{
_value += (char) istr.get();
}
break;
case ']':
if (next == ']')
{
_value += (char) istr.get();
}
break;
case '.': case '.':
if (next == '.') if (next == '.')
{ {
@ -231,7 +243,7 @@ int OperatorToken::asInteger() const
IdentifierToken::IdentifierToken() IdentifierToken::IdentifierToken()
{ {
int i = 1; int i = KW_ALIGNAS;
_kwMap["alignas"] = i++; _kwMap["alignas"] = i++;
_kwMap["alignof"] = i++; _kwMap["alignof"] = i++;
_kwMap["and"] = i++; _kwMap["and"] = i++;

View File

@ -39,6 +39,7 @@ using Poco::NumberFormatter;
using Poco::SyntaxException; using Poco::SyntaxException;
using Poco::icompare; using Poco::icompare;
using Poco::trimInPlace; using Poco::trimInPlace;
using namespace std::string_literals;
namespace Poco { namespace Poco {
@ -117,6 +118,8 @@ inline void Parser::append(std::string& decl, const std::string& token)
token != "," && token != "," &&
token != "[" && token != "[" &&
token != "]" && token != "]" &&
token != "[[" &&
token != "]]" &&
last != '~' && last != '~' &&
last != ':' && last != ':' &&
last != '(' && last != '(' &&
@ -380,7 +383,7 @@ const Token* Parser::parseClassMembers(const Token* pNext, Struct* /*pClass*/)
poco_assert (isOperator(pNext, OperatorToken::OP_OPENBRACE)); poco_assert (isOperator(pNext, OperatorToken::OP_OPENBRACE));
pNext = next(); pNext = next();
while (pNext->is(Token::IDENTIFIER_TOKEN) || pNext->is(Token::KEYWORD_TOKEN) || isOperator(pNext, OperatorToken::OP_COMPL) || isOperator(pNext, OperatorToken::OP_DBL_COLON)) while (pNext->is(Token::IDENTIFIER_TOKEN) || pNext->is(Token::KEYWORD_TOKEN) || isOperator(pNext, OperatorToken::OP_COMPL) || isOperator(pNext, OperatorToken::OP_DBL_COLON) || isOperator(pNext, OperatorToken::OP_DBL_OPENBRACKET))
{ {
switch (pNext->asInteger()) switch (pNext->asInteger())
{ {
@ -575,6 +578,11 @@ const Token* Parser::parseVarFunc(const Token* pNext)
const Token* Parser::parseVarFunc(const Token* pNext, std::string& decl) const Token* Parser::parseVarFunc(const Token* pNext, std::string& decl)
{ {
_pCurrentSymbol = 0; _pCurrentSymbol = 0;
std::string attrs;
if (isOperator(pNext, OperatorToken::OP_DBL_OPENBRACKET))
{
pNext = parseAttributes(pNext, attrs);
}
if (isKeyword(pNext, IdentifierToken::KW_EXTERN)) if (isKeyword(pNext, IdentifierToken::KW_EXTERN))
{ {
pNext = parseExtern(pNext); pNext = parseExtern(pNext);
@ -596,6 +604,7 @@ const Token* Parser::parseVarFunc(const Token* pNext, std::string& decl)
if (!currentNameSpace()->lookup(name)) if (!currentNameSpace()->lookup(name))
{ {
Variable* pVar = new Variable(decl, currentNameSpace()); Variable* pVar = new Variable(decl, currentNameSpace());
pVar->setAttributeList(attrs);
addSymbol(pVar, static_cast<int>(_istr.getCurrentLineNumber())); addSymbol(pVar, static_cast<int>(_istr.getCurrentLineNumber()));
} }
pNext = next(); pNext = next();
@ -611,7 +620,7 @@ const Token* Parser::parseVarFunc(const Token* pNext, std::string& decl)
pNext = next(); pNext = next();
expectOperator(pNext, OperatorToken::OP_OPENPARENT, "("); expectOperator(pNext, OperatorToken::OP_OPENPARENT, "(");
} }
pNext = parseFunc(pNext, decl); pNext = parseFunc(pNext, attrs, decl);
} }
} }
_pCurrentSymbol = 0; _pCurrentSymbol = 0;
@ -641,7 +650,7 @@ const Token* Parser::parseExtern(const Token* pNext)
} }
const Token* Parser::parseFunc(const Token* pNext, std::string& decl) const Token* Parser::parseFunc(const Token* pNext, const std::string& attrs, std::string& decl)
{ {
poco_assert (isOperator(pNext, OperatorToken::OP_OPENPARENT)); poco_assert (isOperator(pNext, OperatorToken::OP_OPENPARENT));
@ -651,6 +660,7 @@ const Token* Parser::parseFunc(const Token* pNext, std::string& decl)
if (name.find(':') == std::string::npos) if (name.find(':') == std::string::npos)
{ {
pFunc = new Function(decl, currentNameSpace()); pFunc = new Function(decl, currentNameSpace());
pFunc->setAttributeList(attrs);
addSymbol(pFunc, line); addSymbol(pFunc, line);
} }
pNext = parseParameters(pNext, pFunc); pNext = parseParameters(pNext, pFunc);
@ -909,6 +919,25 @@ const Token* Parser::parseIdentifier(const Token* pNext, std::string& id)
} }
const Poco::Token* Parser::parseAttributes(const Poco::Token* pNext, std::string& attrs)
{
poco_assert (isOperator(pNext, OperatorToken::OP_DBL_OPENBRACKET));
append(attrs, pNext);
pNext = next();
while (pNext && !isOperator(pNext, OperatorToken::OP_DBL_CLOSBRACKET))
{
append(attrs, pNext);
pNext = next();
}
if (pNext)
{
append(attrs, pNext);
pNext = next();
}
return pNext;
}
void Parser::addSymbol(Symbol* pSymbol, int lineNumber, bool addGST) void Parser::addSymbol(Symbol* pSymbol, int lineNumber, bool addGST)
{ {
pSymbol->setLineNumber(lineNumber); pSymbol->setLineNumber(lineNumber);

View File

@ -59,6 +59,12 @@ void Symbol::setAccess(Access access)
} }
void Symbol::setAttributeList(const std::string& attrs)
{
_attributeList = attrs;
}
void Symbol::setDocumentation(const std::string& text) void Symbol::setDocumentation(const std::string& text)
{ {
_documentation = text; _documentation = text;