Skip to content

Commit 900d469

Browse files
authored
updated attribute syntax to support commas and empty specifiers (#51)
1 parent b646d41 commit 900d469

2 files changed

Lines changed: 67 additions & 7 deletions

File tree

cppparser/src/parser.y

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ class CppTemplateArg;
183183
cppast::CppRefType refType;
184184
unsigned int attr;
185185
Optional<cppast::CppAccessType> objAccessType;
186-
cppast::CppExpression* attribSpecifier;
187186
cppast::CppCallArgs* attribSpecifiers;
188187
cppast::CppIfBlock* ifBlock;
189188
cppast::CppWhileBlock* whileBlock;
@@ -313,8 +312,7 @@ class CppTemplateArg;
313312
%type <accessSpecifier> entityaccessspecifier
314313
%type <identifierList> identifierlist
315314
%type <funcThrowSpec> functhrowspec optfuncthrowspec
316-
%type <attribSpecifier> attribspecifier
317-
%type <attribSpecifiers> attribspecifiers optattribspecifiers
315+
%type <attribSpecifiers> attribs optattribs attribspecifier attribspecifiers optattribspecifiers
318316
%type <hashDefine> define
319317
%type <hashUndef> undef
320318
%type <hashInclude> include
@@ -1703,8 +1701,26 @@ classdefnstmt
17031701
: classdefn ';' [ZZVALID;] { $$ = $1; }
17041702
;
17051703

1704+
attribs
1705+
: expr {
1706+
$$ = new std::vector<std::unique_ptr<cppast::CppExpression>>;
1707+
$$->push_back(Ptr($1));
1708+
}
1709+
| attribs ',' expr {
1710+
$$ = $1;
1711+
$$->push_back(Ptr($3));
1712+
}
1713+
;
1714+
1715+
optattribs
1716+
: {
1717+
$$ = new std::vector<std::unique_ptr<cppast::CppExpression>>;
1718+
}
1719+
| attribs { $$ = $1; }
1720+
;
1721+
17061722
attribspecifier
1707-
: '[' '[' expr ']' ']' {
1723+
: '[' '[' optattribs ']' ']' {
17081724
$$ = $3;
17091725
}
17101726
;
@@ -1719,11 +1735,11 @@ optattribspecifiers
17191735
attribspecifiers
17201736
: attribspecifier {
17211737
$$ = new std::vector<std::unique_ptr<cppast::CppExpression>>;
1722-
$$->push_back(Ptr($1));
1738+
$$->insert($$->end(), std::make_move_iterator($1->begin()), std::make_move_iterator($1->end()));
17231739
}
17241740
| attribspecifiers attribspecifier {
17251741
$$ = $1;
1726-
$$->push_back(Ptr($2));
1742+
$$->insert($$->end(), std::make_move_iterator($2->begin()), std::make_move_iterator($2->end()));
17271743
}
17281744
;
17291745

cppparser/test/unit/attribute-specifier-sequence.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ TEST_CASE_METHOD(CppAtributeTest, "Attribute specifier sequence")
3232

3333
[[xnet::HttpPost]] [[xnet::Route("/register")]] std::string CreateAccount(
3434
[[xnet::FromBody]] [[xnet::EnsureValid]] SignUpRequest request);
35+
36+
[[xnet::HttpGet, xnet::Route("/entities"), xnet::Route("/entity")]] std::string GetEntities();
37+
38+
[[]] [[]] void UnannotatedHelper();
3539
};
3640
#endif
3741
auto testSnippet = getTestSnippetParseStream(__LINE__ - 2);
@@ -72,7 +76,7 @@ TEST_CASE_METHOD(CppAtributeTest, "Attribute specifier sequence")
7276
CHECK((*classAttrib1Arg) == cppast::CppStringLiteralExpr("\"/plakmp\""));
7377

7478
const auto classMembers = GetAllOwnedEntities(*classDefn);
75-
REQUIRE(classMembers.size() == 4);
79+
REQUIRE(classMembers.size() == 6);
7680

7781
const cppast::CppConstFunctionEPtr methodGetPlakMpPlayers = classMembers[1];
7882
REQUIRE(methodGetPlakMpPlayers);
@@ -95,4 +99,44 @@ TEST_CASE_METHOD(CppAtributeTest, "Attribute specifier sequence")
9599
cppast::CppConstStringLiteralExprEPtr methodAttrib1Arg = &(methodAttrib1->arg(0));
96100
REQUIRE(methodAttrib1Arg);
97101
CHECK((*methodAttrib1Arg) == cppast::CppStringLiteralExpr("\"/players\""));
102+
103+
const cppast::CppConstFunctionEPtr methodGetEntities = classMembers[4];
104+
REQUIRE(methodGetEntities);
105+
const auto* returnTypeGetEntities = methodGetEntities->returnType();
106+
REQUIRE(returnTypeGetEntities);
107+
108+
const auto attribSeqGetEntities = GetAllAttributeSpecifiers(*returnTypeGetEntities);
109+
REQUIRE(attribSeqGetEntities.size() == 3);
110+
111+
cppast::CppConstNameExprEPtr method2Attrib0 = attribSeqGetEntities.at(0);
112+
REQUIRE(method2Attrib0);
113+
CHECK((*method2Attrib0) == cppast::CppNameExpr("xnet::HttpGet"));
114+
115+
cppast::CppConstFunctionCallExprEPtr method2Attrib1 = attribSeqGetEntities.at(1);
116+
REQUIRE(method2Attrib1);
117+
cppast::CppConstNameExprEPtr method2Attrib1Func = &(method2Attrib1->function());
118+
REQUIRE(method2Attrib1Func);
119+
CHECK((*method2Attrib1Func) == cppast::CppNameExpr("xnet::Route"));
120+
REQUIRE(method2Attrib1->numArgs() == 1);
121+
cppast::CppConstStringLiteralExprEPtr method2Attrib1Arg = &(method2Attrib1->arg(0));
122+
REQUIRE(method2Attrib1Arg);
123+
CHECK((*method2Attrib1Arg) == cppast::CppStringLiteralExpr("\"/entities\""));
124+
125+
cppast::CppConstFunctionCallExprEPtr method2Attrib2 = attribSeqGetEntities.at(2);
126+
REQUIRE(method2Attrib2);
127+
cppast::CppConstNameExprEPtr method2Attrib2Func = &(method2Attrib2->function());
128+
REQUIRE(method2Attrib2Func);
129+
CHECK((*method2Attrib2Func) == cppast::CppNameExpr("xnet::Route"));
130+
REQUIRE(method2Attrib2->numArgs() == 1);
131+
cppast::CppConstStringLiteralExprEPtr method2Attrib2Arg = &(method2Attrib2->arg(0));
132+
REQUIRE(method2Attrib2Arg);
133+
CHECK((*method2Attrib2Arg) == cppast::CppStringLiteralExpr("\"/entity\""));
134+
135+
const cppast::CppConstFunctionEPtr methodUnannotatedHelper = classMembers[5];
136+
REQUIRE(methodUnannotatedHelper);
137+
const auto* returnTypeUnannotatedHelper = methodUnannotatedHelper->returnType();
138+
REQUIRE(returnTypeUnannotatedHelper);
139+
140+
const auto attribSeqUnannotatedHelper = GetAllAttributeSpecifiers(*returnTypeUnannotatedHelper);
141+
REQUIRE(attribSeqUnannotatedHelper.size() == 0);
98142
}

0 commit comments

Comments
 (0)