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
23namespace Poco {
24namespace CppParser {
25
26
27int Symbol::_nextId = 0;
28
29
30Symbol::Symbol():
31 _id(_nextId++),
32 _pNameSpace(0),
33 _access(ACC_PUBLIC),
34 _line(-1)
35{
36}
37
38
39Symbol::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
51Symbol::~Symbol()
52{
53}
54
55
56void Symbol::setAccess(Access access)
57{
58 _access = access;
59}
60
61
62void Symbol::setDocumentation(const std::string& text)
63{
64 _documentation = text;
65}
66
67
68void Symbol::addDocumentation(const std::string& text)
69{
70 if (!_documentation.empty())
71 _documentation.append("\n");
72 _documentation.append(text);
73}
74
75
76void Symbol::setFile(const std::string& path)
77{
78 _file = path;
79}
80
81
82void Symbol::setLineNumber(int line)
83{
84 _line = line;
85}
86
87
88void Symbol::setPackage(const std::string& package)
89{
90 _package = package;
91}
92
93
94void Symbol::setLibrary(const std::string& library)
95{
96 _library = library;
97}
98
99
100std::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
113std::string Symbol::extractName(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
217bool Symbol::isIdent(char c)
218{
219 return std::isalnum(c) || c == '_';
220}
221
222
223bool 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
232void Symbol::setAttributes(const Attributes& attrs)
233{
234 _attrs = attrs;
235}
236
237
238const Attributes& Symbol::getAttributes() const
239{
240 return _attrs;
241}
242
243
244} } // namespace Poco::CppParser
245