1 | // |
2 | // Symbol.cpp |
3 | // |
4 | // Library: CppParser |
5 | // Package: SymbolTable |
6 | // Module: Symbol |
7 | // |
8 | // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/CppParser/Symbol.h" |
16 | #include "Poco/CppParser/NameSpace.h" |
17 | #include "Poco/CppParser/Utility.h" |
18 | #include "Poco/String.h" |
19 | #include <cctype> |
20 | #include <cstddef> |
21 | |
22 | |
23 | namespace Poco { |
24 | namespace CppParser { |
25 | |
26 | |
27 | int Symbol::_nextId = 0; |
28 | |
29 | |
30 | Symbol::Symbol(): |
31 | _id(_nextId++), |
32 | _pNameSpace(0), |
33 | _access(ACC_PUBLIC), |
34 | _line(-1) |
35 | { |
36 | } |
37 | |
38 | |
39 | Symbol::Symbol(const std::string& name, NameSpace* pNameSpace): |
40 | _id(_nextId++), |
41 | _name(name), |
42 | _pNameSpace(pNameSpace), |
43 | _access(ACC_PUBLIC), |
44 | _line(-1) |
45 | { |
46 | if (_pNameSpace) |
47 | _pNameSpace->addSymbol(this); |
48 | } |
49 | |
50 | |
51 | Symbol::~Symbol() |
52 | { |
53 | } |
54 | |
55 | |
56 | void Symbol::setAccess(Access access) |
57 | { |
58 | _access = access; |
59 | } |
60 | |
61 | |
62 | void Symbol::setDocumentation(const std::string& text) |
63 | { |
64 | _documentation = text; |
65 | } |
66 | |
67 | |
68 | void Symbol::addDocumentation(const std::string& text) |
69 | { |
70 | if (!_documentation.empty()) |
71 | _documentation.append("\n" ); |
72 | _documentation.append(text); |
73 | } |
74 | |
75 | |
76 | void Symbol::setFile(const std::string& path) |
77 | { |
78 | _file = path; |
79 | } |
80 | |
81 | |
82 | void Symbol::setLineNumber(int line) |
83 | { |
84 | _line = line; |
85 | } |
86 | |
87 | |
88 | void Symbol::setPackage(const std::string& package) |
89 | { |
90 | _package = package; |
91 | } |
92 | |
93 | |
94 | void Symbol::setLibrary(const std::string& library) |
95 | { |
96 | _library = library; |
97 | } |
98 | |
99 | |
100 | std::string Symbol::fullName() const |
101 | { |
102 | std::string fullName; |
103 | if (_pNameSpace) |
104 | { |
105 | fullName = _pNameSpace->fullName(); |
106 | if (!fullName.empty()) fullName.append("::" ); |
107 | } |
108 | fullName.append(_name); |
109 | return fullName; |
110 | } |
111 | |
112 | |
113 | std::string Symbol::(const std::string& decl) |
114 | { |
115 | poco_assert (!decl.empty()); |
116 | |
117 | // special cases: operator () and operator [] |
118 | if (decl.find("operator ()" ) != std::string::npos) |
119 | return "operator ()" ; |
120 | else if (decl.find("operator[]" ) != std::string::npos) |
121 | return "operator []" ; |
122 | |
123 | std::string::size_type pos = decl.find('('); |
124 | // another special case: function pointer |
125 | if (pos != std::string::npos && pos < decl.size() - 1) |
126 | { |
127 | std::string::size_type i = pos + 1; |
128 | while (i < decl.size() && std::isspace(decl[i])) i++; |
129 | if (i < decl.size() && decl[i] == '*') |
130 | { |
131 | i++; |
132 | std::string name; |
133 | while (i < decl.size() && std::isspace(decl[i])) i++; |
134 | while (i < decl.size() && !std::isspace(decl[i]) && decl[i] != ')') name += decl[i++]; |
135 | return name; |
136 | } |
137 | } |
138 | if (pos == std::string::npos || (pos > 0 && decl[pos - 1] == '(')) |
139 | pos = decl.size(); |
140 | --pos; |
141 | // check for constant; start searching after template |
142 | std::string::size_type eqStart = 0; |
143 | if (decl.compare(0, 8, "template" ) == 0) |
144 | { |
145 | eqStart = 8; |
146 | while (std::isspace(decl[eqStart]) && eqStart < decl.size()) ++eqStart; |
147 | if (eqStart < decl.size() && decl[eqStart] == '<') |
148 | { |
149 | ++eqStart; |
150 | int tc = 1; |
151 | while (tc > 0 && eqStart < decl.size()) |
152 | { |
153 | if (decl[eqStart] == '<') |
154 | ++tc; |
155 | else if (decl[eqStart] == '>') |
156 | --tc; |
157 | ++eqStart; |
158 | } |
159 | } |
160 | } |
161 | std::string::size_type eqPos = decl.find('=', eqStart); |
162 | if (eqPos != std::string::npos) |
163 | { |
164 | // special case: default template parameter |
165 | std::string::size_type gtPos = decl.find('>', eqPos); |
166 | std::string::size_type ltPos = decl.find('<', eqPos); |
167 | if ((gtPos == std::string::npos || gtPos > pos || (ltPos != std::string::npos && gtPos > ltPos)) && eqPos < pos && eqPos > 0 && decl[eqPos + 1] != '=') |
168 | pos = eqPos - 1; |
169 | } |
170 | while (pos > 0 && std::isspace(decl[pos])) --pos; |
171 | while (pos > 0 && decl[pos] == ']') |
172 | { |
173 | --pos; |
174 | while (pos > 0 && decl[pos] != '[') --pos; |
175 | if (pos > 0) --pos; |
176 | while (pos > 0 && std::isspace(decl[pos])) --pos; |
177 | } |
178 | // iterate over template (specialization) |
179 | int nestedTemplateCount = 0; |
180 | if (pos > 1 && decl[pos] == '>' && decl[pos-1] != '-' && decl[pos-1] != '>') // the operators ->, >> |
181 | { |
182 | --pos; |
183 | ++nestedTemplateCount; |
184 | while (pos > 0 && nestedTemplateCount != 0) |
185 | { |
186 | if (decl[pos] == '<') |
187 | --nestedTemplateCount; |
188 | if (decl[pos] == '>') |
189 | ++nestedTemplateCount; |
190 | --pos; |
191 | } |
192 | while (pos > 0 && std::isspace(decl[pos])) --pos; |
193 | } |
194 | std::string::size_type end = pos; |
195 | std::string::size_type op = decl.find("operator " ); |
196 | if (op != std::string::npos && (op == 0 || std::isspace(decl[op - 1]) || decl[op - 1] == ':')) |
197 | { |
198 | pos = op; |
199 | } |
200 | else |
201 | { |
202 | while (pos > 0 && !isIdent(decl[pos])) --pos; |
203 | while (pos > 0 && std::isspace(decl[pos])) --pos; |
204 | while (pos > 0 && isIdent(decl[pos - 1])) --pos; |
205 | if (pos > 0 && decl[pos - 1] == '~') --pos; |
206 | } |
207 | |
208 | while (pos > 2 && decl[pos - 1] == ':') |
209 | { |
210 | pos -= 3; |
211 | while (pos > 0 && isIdent(decl[pos - 1])) --pos; |
212 | } |
213 | return decl.substr(pos, end - pos + 1); |
214 | } |
215 | |
216 | |
217 | bool Symbol::isIdent(char c) |
218 | { |
219 | return std::isalnum(c) || c == '_'; |
220 | } |
221 | |
222 | |
223 | bool Symbol::hasAttr(const std::string& decl, const std::string& attr) |
224 | { |
225 | std::string attrS(attr); |
226 | attrS += ' '; |
227 | std::string::size_type pos = decl.find(attrS); |
228 | return pos == 0 || (pos != std::string::npos && decl[pos - 1] == ' '); |
229 | } |
230 | |
231 | |
232 | void Symbol::setAttributes(const Attributes& attrs) |
233 | { |
234 | _attrs = attrs; |
235 | } |
236 | |
237 | |
238 | const Attributes& Symbol::getAttributes() const |
239 | { |
240 | return _attrs; |
241 | } |
242 | |
243 | |
244 | } } // namespace Poco::CppParser |
245 | |