1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcpp/symbols/ContainerSymbol.hpp>
  7 #include <sngcpp/symbols/FunctionSymbol.hpp>
  8 #include <sngcpp/symbols/ClassTypeSymbol.hpp>
  9 #include <sngcpp/symbols/NamespaceSymbol.hpp>
 10 #include <sngcpp/symbols/EnumerationSymbol.hpp>
 11 #include <sngcpp/symbols/TypedefSymbol.hpp>
 12 #include <sngcpp/symbols/VariableSymbol.hpp>
 13 #include <sngcpp/symbols/GrammarSymbol.hpp>
 14 #include <soulng/util/Unicode.hpp>
 15 #include <algorithm>
 16 
 17 namespace sngcpp { namespace symbols {
 18 
 19 using namespace soulng::unicode;
 20 
 21 ContainerSymbol::ContainerSymbol(const Span& span_const std::u32string& name_) : Symbol(span_name_)containerScope(this)
 22 {
 23 }
 24 
 25 void ContainerSymbol::AddMember(std::std::unique_ptr<Symbol>&&member)
 26 {
 27     if (member->IsInstallSymbol())
 28     {
 29         containerScope.Install(member.get());
 30         member->SetParent(this);
 31         members.push_back(std::move(member));
 32     }
 33     else
 34     {
 35         if (member->IsFunctionSymbol())
 36         {
 37             FunctionSymbol* functionSymbol = static_cast<FunctionSymbol*>(member.get());
 38             FunctionGroupSymbol* functionGroup = MakeFunctionGroupSymbol(member->GetSpan()functionSymbol->GroupName());
 39             functionGroup->AddFunction(std::unique_ptr<FunctionSymbol>(static_cast<FunctionSymbol*>(member.release())));
 40         }
 41         else if (member->IsFunctionDeclarationSymbol())
 42         {
 43             FunctionDeclarationSymbol* functionDeclarationSymbol = static_cast<FunctionDeclarationSymbol*>(member.get());
 44             FunctionGroupSymbol* functionGroup = MakeFunctionGroupSymbol(member->GetSpan()functionDeclarationSymbol->GroupName());
 45             functionGroup->AddFunctionDeclaration(std::unique_ptr<FunctionDeclarationSymbol>(static_cast<FunctionDeclarationSymbol*>(member.release())));
 46         }
 47         else if (member->IsClassTypeSymbol())
 48         {
 49             ClassGroupSymbol* classGroup = MakeClassGroupSymbol(member->GetSpan()member->Name());
 50             classGroup->AddClass(std::unique_ptr<ClassTypeSymbol>(static_cast<ClassTypeSymbol*>(member.release())));
 51         }
 52         else
 53         {
 54             throw std::runtime_error("function or class type symbol expected");
 55         }
 56     }
 57 }
 58 
 59 FunctionGroupSymbol* ContainerSymbol::MakeFunctionGroupSymbol(const Span& span_const std::u32string& groupName)
 60 {
 61     Symbol* symbol = containerScope.Lookup(groupName);
 62     if (!symbol)
 63     {
 64         FunctionGroupSymbol* functionGroupSymbol = new FunctionGroupSymbol(span_groupName);
 65         AddMember(std::unique_ptr<Symbol>(functionGroupSymbol));
 66         return functionGroupSymbol;
 67     }
 68     else if (symbol->IsFunctionGroupSymbol())
 69     {
 70         return static_cast<FunctionGroupSymbol*>(symbol);
 71     }
 72     else
 73     {
 74         throw std::runtime_error("symbol '" + ToUtf8(groupName) + "' conflicts with function group of the same name");
 75     }
 76 }
 77 
 78 ClassGroupSymbol* ContainerSymbol::MakeClassGroupSymbol(const Span& span_const std::u32string& groupName)
 79 {
 80     Symbol* symbol = containerScope.Lookup(groupName);
 81     if (!symbol)
 82     {
 83         ClassGroupSymbol* classGroupSymbol = new ClassGroupSymbol(span_groupName);
 84         AddMember(std::unique_ptr<Symbol>(classGroupSymbol));
 85         return classGroupSymbol;
 86     }
 87     else if (symbol->IsClassGroupSymbol())
 88     {
 89         return static_cast<ClassGroupSymbol*>(symbol);
 90     }
 91     else
 92     {
 93         throw std::runtime_error("symbol '" + ToUtf8(groupName) + "' conflicts with class group of the same name");
 94     }
 95 }
 96 
 97 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Namespaces()
 98 {
 99     std::unique_ptr<sngxml::dom::Element> namespacesElement;
100     std::vector<NamespaceSymbol*> namespaces;
101     for (const std::std::unique_ptr<Symbol>&member : members)
102     {
103         if (member->IsNamespaceSymbol())
104         {
105             namespaces.push_back(static_cast<NamespaceSymbol*>(member.get()));
106         }
107     }
108     if (!namespaces.empty())
109     {
110         namespacesElement.reset(new sngxml::dom::Element(U"namespaces"));
111         std::sort(namespaces.begin()namespaces.end()ByName());
112         for (NamespaceSymbol* ns : namespaces)
113         {
114             std::unique_ptr<sngxml::dom::Element> namespaceElement = ns->ToDomElement();
115             namespacesElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(namespaceElement.release()));
116         }
117     }
118     return namespacesElement;
119 }
120 
121 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Classes()
122 {
123     std::unique_ptr<sngxml::dom::Element> classesElement;
124     std::vector<ClassTypeSymbol*> classes;
125     for (const std::std::unique_ptr<Symbol>&member : members)
126     {
127         if (member->IsClassGroupSymbol())
128         {
129             ClassGroupSymbol* classGroup = static_cast<ClassGroupSymbol*>(member.get());
130             for (const std::std::unique_ptr<ClassTypeSymbol>&cls : classGroup->Classes())
131             {
132                 classes.push_back(cls.get());
133             }
134         }
135     }
136     if (!classes.empty())
137     {
138         classesElement.reset(new sngxml::dom::Element(U"classes"));
139         std::sort(classes.begin()classes.end()ByName());
140         for (ClassTypeSymbol* cls : classes)
141         {
142             std::unique_ptr<sngxml::dom::Element> classElement = cls->ToDomElement();
143             classesElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(classElement.release()));
144         }
145     }
146     return classesElement;
147 }
148 
149 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Constructors()
150 {
151     std::unique_ptr<sngxml::dom::Element> constructorsElement;
152     std::vector<ConstructorSymbol*> constructors;
153     for (const std::std::unique_ptr<Symbol>&member : members)
154     {
155         if (member->IsFunctionGroupSymbol())
156         {
157             FunctionGroupSymbol* functionroup = static_cast<FunctionGroupSymbol*>(member.get());
158             for (const std::std::unique_ptr<FunctionSymbol>&function : functionroup->Functions())
159             {
160                 if (function->IsConstructorSymbol())
161                 {
162                     constructors.push_back(static_cast<ConstructorSymbol*>(function.get()));
163                 }
164             }
165         }
166     }
167     if (!constructors.empty())
168     {
169         constructorsElement.reset(new sngxml::dom::Element(U"constructors"));
170         std::sort(constructors.begin()constructors.end()ByName());
171         for (ConstructorSymbol* constructor : constructors)
172         {
173             std::unique_ptr<sngxml::dom::Element> constructorElement = constructor->ToDomElement();
174             constructorsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(constructorElement.release()));
175         }
176     }
177     return constructorsElement;
178 }
179 
180 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Functions()
181 {
182     std::unique_ptr<sngxml::dom::Element> functionsElement;
183     std::vector<FunctionSymbol*> functions;
184     for (const std::std::unique_ptr<Symbol>&member : members)
185     {
186         if (member->IsFunctionGroupSymbol())
187         {
188             FunctionGroupSymbol* functionGroup = static_cast<FunctionGroupSymbol*>(member.get());
189             for (const std::std::unique_ptr<FunctionSymbol>&function : functionGroup->Functions())
190             {
191                 if (function->IsFunctionSymbol() && !function->IsConstructorSymbol())
192                 {
193                     functions.push_back(function.get());
194                 }
195             }
196         }
197     }
198     if (!functions.empty())
199     {
200         functionsElement.reset(new sngxml::dom::Element(U"functions"));
201         std::sort(functions.begin()functions.end()ByName());
202         for (FunctionSymbol* function : functions)
203         {
204             std::unique_ptr<sngxml::dom::Element> functionElement = function->ToDomElement();
205             functionsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(functionElement.release()));
206         }
207     }
208     return functionsElement;
209 }
210 
211 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::EnumTypes()
212 {
213     std::unique_ptr<sngxml::dom::Element> enumTypesElement;
214     std::vector<EnumTypeSymbol*> enumTypes;
215     for (const std::std::unique_ptr<Symbol>&member : members)
216     {
217         if (member->IsEnumTypeSymbol())
218         {
219             EnumTypeSymbol* enumType = static_cast<EnumTypeSymbol*>(member.get());
220             enumTypes.push_back(enumType);
221         }
222     }
223     if (!enumTypes.empty())
224     {
225         enumTypesElement.reset(new sngxml::dom::Element(U"enumTypes"));
226         std::sort(enumTypes.begin()enumTypes.end()ByName());
227         for (EnumTypeSymbol* enumType : enumTypes)
228         {
229             std::unique_ptr<sngxml::dom::Element> enumTypeElement = enumType->ToDomElement();
230             enumTypesElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(enumTypeElement.release()));
231         }
232     }
233     return enumTypesElement;
234 }
235 
236 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Enumerators()
237 {
238     std::unique_ptr<sngxml::dom::Element> enumeratorsElement;
239     std::vector<EnumeratorSymbol*> enumerators;
240     for (const std::std::unique_ptr<Symbol>&member : members)
241     {
242         if (member->IsEnumeratorSymbol())
243         {
244             EnumeratorSymbol* enumerator = static_cast<EnumeratorSymbol*>(member.get());
245             enumerators.push_back(enumerator);
246         }
247     }
248     if (!enumerators.empty())
249     {
250         enumeratorsElement.reset(new sngxml::dom::Element(U"enumerators"));
251         for (EnumeratorSymbol* enumerator : enumerators)
252         {
253             std::unique_ptr<sngxml::dom::Element> enumeratorElement = enumerator->ToDomElement();
254             enumeratorsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(enumeratorElement.release()));
255         }
256     }
257     return enumeratorsElement;
258 }
259 
260 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Typedefs()
261 {
262     std::unique_ptr<sngxml::dom::Element> typedefsElement;
263     std::vector<TypedefSymbol*> typedefs;
264     for (const std::std::unique_ptr<Symbol>&member : members)
265     {
266         if (member->IsTypedefSymbol())
267         {
268             TypedefSymbol* typedef_ = static_cast<TypedefSymbol*>(member.get());
269             typedefs.push_back(typedef_);
270         }
271     }
272     if (!typedefs.empty())
273     {
274         typedefsElement.reset(new sngxml::dom::Element(U"typedefs"));
275         std::sort(typedefs.begin()typedefs.end()ByName());
276         for (TypedefSymbol* typedef_ : typedefs)
277         {
278             std::unique_ptr<sngxml::dom::Element> typedefElement = typedef_->ToDomElement();
279             typedefsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(typedefElement.release()));
280         }
281     }
282     return typedefsElement;
283 }
284 
285 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Variables()
286 {
287     std::unique_ptr<sngxml::dom::Element> variablesElement;
288     std::vector<VariableSymbol*> variables;
289     for (const std::std::unique_ptr<Symbol>&member : members)
290     {
291         if (member->IsVariableSymbol())
292         {
293             VariableSymbol* variable = static_cast<VariableSymbol*>(member.get());
294             variables.push_back(variable);
295         }
296     }
297     if (!variables.empty())
298     {
299         variablesElement.reset(new sngxml::dom::Element(U"variables"));
300         std::sort(variables.begin()variables.end()ByName());
301         for (VariableSymbol* variable : variables)
302         {
303             std::unique_ptr<sngxml::dom::Element> variableElement = variable->ToDomElement();
304             variablesElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(variableElement.release()));
305         }
306     }
307     return variablesElement;
308 }
309 
310 std::std::unique_ptr<sngxml::dom::Element>ContainerSymbol::Grammars()
311 {
312     std::unique_ptr<sngxml::dom::Element> grammarsElement;
313     std::vector<GrammarSymbol*> grammars;
314     for (const std::std::unique_ptr<Symbol>&member : members)
315     {
316         if (member->IsGrammarSymbol())
317         {
318             GrammarSymbol* grammar = static_cast<GrammarSymbol*>(member.get());
319             grammars.push_back(grammar);
320         }
321     }
322     if (!grammars.empty())
323     {
324         grammarsElement.reset(new sngxml::dom::Element(U"grammars"));
325         std::sort(grammars.begin()grammars.end()ByName());
326         for (GrammarSymbol* grammar : grammars)
327         {
328             std::unique_ptr<sngxml::dom::Element> grammarElement = grammar->ToDomElement();
329             grammarsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(grammarElement.release()));
330         }
331     }
332     return grammarsElement;
333 }
334 
335 } } // namespace sngcpp::symbols