1
2
3
4
5
6 #include <gendoc/html/HtmlSourceCodeGenerator.hpp>
7 #include <sngcpp/symbols/ClassTemplateSpecializationSymbol.hpp>
8 #include <sngcpp/symbols/ExternalTypeSymbol.hpp>
9 #include <sngcpp/ast/Class.hpp>
10 #include <sngcpp/ast/Expression.hpp>
11 #include <sngcpp/ast/TypeExpr.hpp>
12 #include <sngcpp/ast/Template.hpp>
13 #include <sngcpp/parser/SourceLineParser.hpp>
14 #include <sngxml/dom/CharacterData.hpp>
15 #include <soulng/util/Path.hpp>
16 #include <soulng/util/Unicode.hpp>
17 #include <soulng/util/TextUtils.hpp>
18 #include <soulng/util/Util.hpp>
19 #include <fstream>
20
21 namespace gendoc { namespace html {
22
23 using namespace sngcpp::ast;
24 using namespace soulng::util;
25 using namespace soulng::unicode;
26
27 HtmlSourceCodeGenerator::HtmlSourceCodeGenerator(const std::u32string& projectName_, const std::std::vector<std::u32string>&inputLines_, intnumDigits_,
28 const std::string& styleDirName_, const std::string& styleFileName_, SymbolTable& symbolTable_, int inlineCodeLimit_,
29 std::std::unordered_map<std::u32string, std::std::unique_ptr<sngxml::dom::Element>>&inlineCodeMap_,
30 HtmlContentFilePathResolver* contentFilePathResolver_) :
31 projectName(projectName_), symbolTable(symbolTable_), currentFunction(nullptr), invokeSymbol(nullptr), inputLines(inputLines_), numDigits(numDigits_),
32 currentSourceLineNumber(1), styleFilePath(Path::Combine(Path::Combine("../..", styleDirName_), styleFileName_)), contentDirPath(".."),
33 lineStarts(nullptr), firstBaseClass(false), firstParam(false), firstTemplateParameter(false), firstTemplateArgument(false),
34 firstMemberInitializer(false), firstInitializer(false), firstEnumerator(false), rangeForDeclaration(false), blockLevel(0),
35 currentAccess(Specifier::private_), inlineCodeLimit(inlineCodeLimit_), inlineCodeOffset(0), inlineCodeMap(inlineCodeMap_), skip(false),
36 inBlockComment(false), contentFilePathResolver(contentFilePathResolver_)
37 {
38 htmlElement.reset(new sngxml::dom::Element(U"html"));
39 }
40
41 void HtmlSourceCodeGenerator::WriteDocument()
42 {
43 std::ofstream htmlFile(htmlFilePath);
44 CodeFormatter formatter(htmlFile);
45 formatter.SetIndentSize(1);
46 htmlElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(bodyElement.release()));
47 htmlSourceFileDocument.AppendChild(std::unique_ptr<sngxml::dom::Node>(htmlElement.release()));
48 htmlSourceFileDocument.Write(formatter);
49 }
50
51 void HtmlSourceCodeGenerator::Visit(SourceFileNode& sourceFileNode)
52 {
53 if (sourceFileNode.SourceFilePath().find("Json.hpp") != std::string::npos)
54 {
55 int x = 0;
56 }
57 lineStarts = sourceFileNode.LineStarts();
58 htmlFilePath = sourceFileNode.HtmlSourceFilePath();
59 std::unique_ptr<sngxml::dom::Element> headElement(new sngxml::dom::Element(U"head"));
60 std::unique_ptr<sngxml::dom::Element> metaElement(new sngxml::dom::Element(U"meta"));
61 metaElement->SetAttribute(U"charset", U"utf-8");
62 headElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(metaElement.release()));
63 std::unique_ptr<sngxml::dom::Element> titleElement(new sngxml::dom::Element(U"title"));
64 titleElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(sourceFileNode.ProjectName() + U"/" + ToUtf32(sourceFileNode.RelativeSourceFilePath()))));
65 std::unique_ptr<sngxml::dom::Element> linkElement(new sngxml::dom::Element(U"link"));
66 linkElement->SetAttribute(U"rel", U"stylesheet");
67 linkElement->SetAttribute(U"type", U"text/css");
68 std::u32string relativeStyleFilePath = ToUtf32(styleFilePath);
69 linkElement->SetAttribute(U"href", relativeStyleFilePath);
70 headElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(linkElement.release()));
71 htmlElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(headElement.release()));
72 bodyElement.reset(new sngxml::dom::Element(U"body"));
73 sourceFileNode.GlobalNs()->Accept(*this);
74 if (lineElement)
75 {
76 CloseLine();
77 }
78 WriteRestOfInput();
79 }
80
81 std::u32string HtmlSourceCodeGenerator::MakeSymbolRef(Symbol* symbol)
82 {
83 if (!symbol) return std::u32string();
84 if (symbol->IsParentSymbol())
85 {
86 if (symbol->IsClassTemplateSpecializationSymbol())
87 {
88 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(symbol);
89 return MakeSymbolRef(specialization->PrimaryClassTemplateSymbol());
90 }
91 else if (symbol->IsNamespaceSymbol())
92 {
93 if (symbol->ProjectName() == projectName)
94 {
95 return ToUtf32(Path::Combine(contentDirPath, ToUtf8(symbol->Id()) + ".html"));
96 }
97 else
98 {
99 NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(symbol);
100 if (ns->HasProject(projectName))
101 {
102 return ToUtf32(Path::Combine(contentDirPath, ToUtf8(symbol->Id()) + ".html"));
103 }
104 else
105 {
106 std::u32string project = ns->FirstProject();
107 if (project.empty()) return std::u32string();
108 return ToUtf32(contentFilePathResolver->ResolveContentFilePath(projectName, project, contentDirPath, symbol->Id()));
109 }
110 }
111 }
112 else
113 {
114 return ToUtf32(contentFilePathResolver->ResolveContentFilePath(projectName, symbol->ProjectName(), contentDirPath, symbol->Id()));
115 }
116 }
117 else if (symbol->IsFunctionGroupSymbol() || symbol->IsClassGroupSymbol() || !symbol->Parent() ||
118 symbol->Parent()->IsDeclarationBlockSymbol() || symbol->Parent()->IsFunctionSymbol())
119 {
120 return std::u32string();
121 }
122 else
123 {
124 return MakeSymbolRef(symbol->Parent()) + U"#" + symbol->Id();
125 }
126 }
127
128 std::u32string HtmlSourceCodeGenerator::MakeInlineSymbolRef(Symbol* symbol)
129 {
130 if (!symbol) return std::u32string();
131 if (symbol->IsParentSymbol())
132 {
133 if (symbol->IsClassTemplateSpecializationSymbol())
134 {
135 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(symbol);
136 return MakeInlineSymbolRef(specialization->PrimaryClassTemplateSymbol());
137 }
138 else if (symbol->IsNamespaceSymbol())
139 {
140 if (symbol->ProjectName() == projectName)
141 {
142 return ToUtf32(Path::Combine(".", ToUtf8(symbol->Id()) + ".html"));
143 }
144 else
145 {
146 NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(symbol);
147 if (ns->HasProject(projectName))
148 {
149 return ToUtf32(Path::Combine(".", ToUtf8(symbol->Id()) + ".html"));
150 }
151 else
152 {
153 std::u32string project = ns->FirstProject();
154 if (project.empty()) return std::u32string();
155 return ToUtf32(contentFilePathResolver->ResolveContentFilePath(projectName, project, ".", symbol->Id()));
156 }
157 }
158 }
159 else
160 {
161 return ToUtf32(contentFilePathResolver->ResolveContentFilePath(projectName, symbol->ProjectName(), ".", symbol->Id()));
162 }
163 }
164 else if (symbol->IsFunctionGroupSymbol() || symbol->IsClassGroupSymbol() || !symbol->Parent() ||
165 symbol->Parent()->IsDeclarationBlockSymbol() || symbol->Parent()->IsFunctionSymbol())
166 {
167 return std::u32string();
168 }
169 else
170 {
171 return MakeInlineSymbolRef(symbol->Parent()) + U"#" + symbol->Id();
172 }
173 }
174
175 void HtmlSourceCodeGenerator::WriteId(IdentifierNode* id, Symbol* symbol, bool writeType)
176 {
177 if (id->Identifier() == U"ReadBool")
178 {
179 int x = 0;
180 }
181 MoveTo(id->GetSpan());
182 if (symbol)
183 {
184 if (symbol->IsClassGroupSymbol())
185 {
186 ClassGroupSymbol* group = static_cast<ClassGroupSymbol*>(symbol);
187 symbol = group->GetClass(0);
188 }
189 else if (symbol->IsFunctionDeclarationSymbol())
190 {
191 FunctionDeclarationSymbol* functionDeclarationSymbol = static_cast<FunctionDeclarationSymbol*>(symbol);
192 if (functionDeclarationSymbol->FunctionDefinition())
193 {
194 symbol = functionDeclarationSymbol->FunctionDefinition();
195 }
196 else
197 {
198 symbol = nullptr;
199 }
200 }
201 writer.WriteLink(id->Identifier(), MakeSymbolRef(symbol));
202 writer.WriteInlineLink(id->Identifier(), MakeInlineSymbolRef(symbol));
203 }
204 else if (writeType)
205 {
206 writer.WriteType(id->Identifier());
207 }
208 else
209 {
210 if (id->IsDtorIdNode())
211 {
212 writer.WriteOther(U"~");
213 writer.WriteIdentifier(id->Identifier());
214 }
215 else if (id->IsOperatorFunctionIdNode())
216 {
217 OperatorFunctionIdNode* operatorFunctionIdNode = static_cast<OperatorFunctionIdNode*>(id);
218 writer.WriteKeyword(U"operator");
219 writer.WriteOther(operatorFunctionIdNode->OpStr());
220 }
221 else if (id->IsConversionFunctionIdNode())
222 {
223 writer.WriteKeyword(U"operator");
224 writer.WriteSpace(1);
225 }
226 else
227 {
228 writer.WriteIdentifier(id->Identifier());
229 }
230 }
231 }
232
233 void HtmlSourceCodeGenerator::WriteIdSequence(bool writeType, Symbol* terminalSymbol)
234 {
235 if (invokeSymbol && terminalSymbol && invokeSymbol != terminalSymbol&&(
236 terminalSymbol->IsClassGroupSymbol() || terminalSymbol->IsClassTypeSymbol() || terminalSymbol->IsFunctionGroupSymbol())) return;
237 int n = idSequence.size();
238 if (n > 0)
239 {
240 for (int i = 0; i < n - 1; ++i)
241 {
242 if (idSequence[i].first)
243 {
244 WriteId(idSequence[i].first, idSequence[i].second, false);
245 }
246 writer.WriteOther(U"::");
247 }
248 if (!terminalSymbol)
249 {
250 terminalSymbol = idSequence.back().second;
251 }
252 WriteId(idSequence.back().first, terminalSymbol, writeType);
253 idSequence.clear();
254 }
255 }
256
257 void HtmlSourceCodeGenerator::WriteType(TypeSymbol* type, const std::std::vector<IdentifierNode*>&idNodeSequence, TemplateIdNode*templateIdNode)
258 {
259 int n = idNodeSequence.size();
260 if (type->IsExternalTypeSymbol())
261 {
262 ExternalTypeSymbol* externalTypeSymbol = static_cast<ExternalTypeSymbol*>(type);
263 if (externalTypeSymbol->GetClassKey() != ClassKey::none)
264 {
265 writer.WriteKeyword(ToString(externalTypeSymbol->GetClassKey()));
266 writer.WriteSpace(1);
267 }
268 for (int i = 0; i < n - 1; ++i)
269 {
270 IdentifierNode* idNode = idNodeSequence[i];
271 if (idNode)
272 {
273 writer.WriteIdentifier(idNode->Identifier());
274 }
275 writer.WriteOther(U"::");
276 }
277 if (n > 0)
278 {
279 writer.WriteType(idNodeSequence.back()->Identifier());
280 }
281 else
282 {
283 writer.WriteType(type->Name());
284 }
285 }
286 else if (type->IsSimpleTypeSymbol())
287 {
288 SimpleTypeSymbol* simpleTypeSymbol = static_cast<SimpleTypeSymbol*>(type);
289 std::vector<std::u32string> components = Split(simpleTypeSymbol->Name(), ' ');
290 bool first = true;
291 for (const std::u32string& component : components)
292 {
293 if (first)
294 {
295 first = false;
296 }
297 else
298 {
299 writer.WriteSpace(1);
300 }
301 writer.WriteKeyword(component);
302 }
303 }
304 else if (type->IsDerivedTypeSymbol())
305 {
306 DerivedTypeSymbol* derivedTypeSymbol = static_cast<DerivedTypeSymbol*>(type);
307 for (Derivation derivation : derivedTypeSymbol->Derivations())
308 {
309 switch (derivation)
310 {
311 case Derivation::const_:
312 {
313 writer.WriteKeyword(U"const ");
314 break;
315 }
316 case Derivation::volatile_:
317 {
318 writer.WriteKeyword(U"volatile ");
319 break;
320 }
321 case Derivation::ptr:
322 {
323 writer.WriteOther(U"*");
324 break;
325 }
326 case Derivation::lvalueRef:
327 {
328 writer.WriteOther(U"&");
329 break;
330 }
331 case Derivation::rvalueRef:
332 {
333 writer.WriteOther(U"&&");
334 break;
335 }
336 case Derivation::base:
337 {
338 TypeSymbol* baseType = derivedTypeSymbol->BaseType();
339 WriteType(baseType, idNodeSequence, templateIdNode);
340 break;
341 }
342 }
343 }
344 }
345 else if (type->IsClassTemplateSpecializationSymbol())
346 {
347 ClassTemplateSpecializationSymbol* classTemplateSpecializationSymbol = static_cast<ClassTemplateSpecializationSymbol*>(type);
348 TypeSymbol* primaryType = classTemplateSpecializationSymbol->PrimaryClassTemplateSymbol();
349 WriteType(primaryType, symbolTable.GetIdNodeSequence(templateIdNode), templateIdNode);
350 writer.WriteOther(U"<");
351 int n = classTemplateSpecializationSymbol->TemplateArgumentSymbols().size();
352 std::vector<Node*> templateArgumentNodes = symbolTable.GetTemplateArgumentNodes(templateIdNode);
353 for (int i = 0; i < n; ++i)
354 {
355 if (i > 0)
356 {
357 writer.WriteOther(U", ");
358 }
359 TypeSymbol* templateArgumentSymbol = classTemplateSpecializationSymbol->TemplateArgumentSymbols()[i];
360 Node* templateArgumentNode = templateArgumentNodes[i];
361 templateArgumentNode->Accept(*this);
362 }
363 writer.WriteOther(U">");
364 }
365 else if (type->IsElaborateClassTypeSymbol())
366 {
367 ElaborateClassTypeSymbol* elaborateClassTypeSymbol = static_cast<ElaborateClassTypeSymbol*>(type);
368 writer.WriteKeyword(ToString(elaborateClassTypeSymbol->GetClassKey()));
369 writer.WriteSpace(1);
370 WriteType(elaborateClassTypeSymbol->GetClassType(), idNodeSequence, templateIdNode);
371 }
372 else
373 {
374 for (int i = 0; i < n - 1; ++i)
375 {
376 IdentifierNode* idNode = idNodeSequence[i];
377 writer.WriteIdentifier(idNode->Identifier());
378 writer.WriteOther(U"::");
379 }
380 writer.WriteLink(type->Name(), MakeSymbolRef(type));
381 writer.WriteInlineLink(type->Name(), MakeInlineSymbolRef(type));
382 }
383 }
384
385 void HtmlSourceCodeGenerator::MoveTo(const Span& span)
386 {
387 int lineNumber = span.line;
388 if (lineNumber == 77)
389 {
390 int x = 0;
391 }
392 while (lineNumber > currentSourceLineNumber)
393 {
394 if (!lineElement)
395 {
396 UseInputLine();
397 }
398 else
399 {
400 CloseLine();
401 }
402 }
403 if (!lineElement)
404 {
405 OpenLine();
406 }
407 if (inlineCodeElement && !inlineLineElement)
408 {
409 OpenInlineLine();
410 }
411 writer.MoveTo(span);
412 }
413
414 void HtmlSourceCodeGenerator::OpenLine()
415 {
416 lineElement.reset(new sngxml::dom::Element(U"span"));
417 writer.SetLineElement(lineElement.get());
418 lineElement->SetAttribute(U"class", U"code");
419 lineElement->SetAttribute(U"xml:space", U"preserve");
420 lineElement->SetAttribute(U"id", ToUtf32(std::to_string(currentSourceLineNumber)));
421 std::u32string lineNumberText = FormatNumber(currentSourceLineNumber, numDigits);
422 writer.WriteLineNumberKind(lineNumberText, WriteKind::line);
423 writer.WriteSpaceKind(1, WriteKind::line);
424 if (lineStarts->size() < currentSourceLineNumber)
425 {
426 throw std::runtime_error("invalid line starts vector");
427 }
428 int lineStart = (*lineStarts)[currentSourceLineNumber - 1];
429 writer.SetCurrentPos(lineStart);
430 }
431
432 void HtmlSourceCodeGenerator::OpenInlineLine()
433 {
434 inlineLineElement.reset(new sngxml::dom::Element(U"span"));
435 inlineLineElement->SetAttribute(U"class", U"code");
436 inlineLineElement->SetAttribute(U"xml:space", U"preserve");
437 writer.SetInlineLineElement(inlineLineElement.get());
438 std::u32string lineNumberText = FormatNumber(currentSourceLineNumber, numDigits);
439 writer.WriteLineNumberKind(lineNumberText, WriteKind::inlineLine);
440 writer.WriteSpaceKind(1, WriteKind::inlineLine);
441 if (lineStarts->size() < currentSourceLineNumber)
442 {
443 throw std::runtime_error("invalid line starts vector");
444 }
445 int inlineLineStart = (*lineStarts)[currentSourceLineNumber - 1] + inlineCodeOffset;
446 writer.SetInlineCurrentPos(inlineLineStart);
447 }
448
449 void HtmlSourceCodeGenerator::CloseLine()
450 {
451 bodyElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(lineElement.release()));
452 bodyElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Element(U"br")));
453 if (inlineCodeElement && inlineLineElement)
454 {
455 inlineCodeElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(inlineLineElement.release()));
456 inlineCodeElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Element(U"br")));
457 writer.SetInlineLineElement(nullptr);
458 }
459 ++currentSourceLineNumber;
460 }
461
462 void HtmlSourceCodeGenerator::UseInputLine()
463 {
464 const std::u32string& line = inputLines[currentSourceLineNumber - 1];
465 OpenLine();
466 ParseSourceLine(line, writer, inBlockComment);
467 CloseLine();
468 }
469
470 void HtmlSourceCodeGenerator::WriteRestOfInput()
471 {
472 int n = inputLines.size();
473 while (currentSourceLineNumber <= n)
474 {
475 UseInputLine();
476 }
477 }
478
479 void HtmlSourceCodeGenerator::WriteSpecifiers(Specifier specifiers)
480 {
481 if (specifiers != Specifier::none)
482 {
483 std::u32string specifierStr = SpecifierStr(specifiers);
484 std::vector<std::u32string> s = Split(specifierStr, ' ');
485 if (!s.empty())
486 {
487 bool first = true;
488 for (const std::u32string& sp : s)
489 {
490 if (first)
491 {
492 first = false;
493 }
494 else
495 {
496 writer.WriteOther(U", ");
497 }
498 if (sp == U"pure")
499 {
500 writer.WriteOther(U"= 0");
501 }
502 else if (sp == U"default" || sp == U"delete")
503 {
504 writer.WriteOther(U" = ");
505 writer.WriteKeyword(sp);
506 }
507 else
508 {
509 writer.WriteKeyword(sp);
510 }
511 }
512 }
513 }
514 }
515
516 void HtmlSourceCodeGenerator::WriteAccess(const Span& span, Specifier access)
517 {
518 MoveTo(span);
519 std::u32string accessStr = SpecifierStr(access & Specifier::access);
520 writer.WriteKeyword(accessStr);
521 writer.WriteOther(U":");
522 }
523
524 void HtmlSourceCodeGenerator::Visit(NamespaceNode& namespaceNode)
525 {
526 if (namespaceNode.Child())
527 {
528 namespaceNode.Child()->Accept(*this);
529 }
530 }
531
532 void HtmlSourceCodeGenerator::Visit(SimpleDeclarationNode& simpleDeclarationNode)
533 {
534 MoveTo(simpleDeclarationNode.GetSpan());
535 Specifier declSpecifiers = simpleDeclarationNode.Specifiers() & DeclSpecifierMask();
536 WriteSpecifiers(declSpecifiers);
537 simpleDeclarationNode.TypeExpr()->Accept(*this);
538 if (simpleDeclarationNode.Declarator())
539 {
540 simpleDeclarationNode.Declarator()->Accept(*this);
541 }
542 if (!rangeForDeclaration)
543 {
544 writer.WriteOther(U";");
545 }
546 }
547
548 void HtmlSourceCodeGenerator::Visit(AliasDeclarationNode& aliasDeclarationNode)
549 {
550 MoveTo(aliasDeclarationNode.GetSpan());
551 writer.WriteKeyword(U"using ");
552 writer.WriteIdentifier(aliasDeclarationNode.Id());
553 writer.WriteOther(U" = ");
554 aliasDeclarationNode.TypeExpr()->Accept(*this);
555 writer.WriteOther(U";");
556 }
557
558 void HtmlSourceCodeGenerator::Visit(DeclarationSequenceNode& declarationSequenceNode)
559 {
560 declarationSequenceNode.Left()->Accept(*this);
561 declarationSequenceNode.Right()->Accept(*this);
562 }
563
564 void HtmlSourceCodeGenerator::Visit(ForwardClassDeclarationNode& forwardClassDeclarationNode)
565 {
566 MoveTo(forwardClassDeclarationNode.GetSpan());
567 writer.WriteKeyword(ToString(forwardClassDeclarationNode.GetClassKey()));
568 writer.WriteSpace(1);
569 forwardClassDeclarationNode.ClassName()->Accept(*this);
570 writer.WriteOther(U";");
571 }
572
573 void HtmlSourceCodeGenerator::Visit(ElaborateClassNameNode& elaborateClassNameNode)
574 {
575 MoveTo(elaborateClassNameNode.GetSpan());
576 writer.WriteKeyword(ToString(elaborateClassNameNode.GetClassKey()));
577 writer.WriteSpace(1);
578 elaborateClassNameNode.ClassName()->Accept(*this);
579 }
580
581 void HtmlSourceCodeGenerator::Visit(ClassNode& classNode)
582 {
583 MoveTo(classNode.GetSpan());
584 writer.WriteKeyword(ToString(classNode.GetClassKey()));
585 writer.WriteSpace(1);
586 classNode.ClassName()->Accept(*this);
587 WriteSpecifiers(classNode.ClassVirtSpecifiers());
588 writer.WriteSpace(1);
589 if (classNode.BaseClasses())
590 {
591 firstBaseClass = true;
592 classNode.BaseClasses()->Accept(*this);
593 }
594 MoveTo(classNode.OpenBraceSpan());
595 writer.WriteOther(U"{");
596 if (classNode.Declarations())
597 {
598 currentAccess = Specifier::none;
599 classNode.Declarations()->Accept(*this);
600 }
601 MoveTo(classNode.CloseBraceSpan());
602 writer.WriteOther(U"};");
603 }
604
605 void HtmlSourceCodeGenerator::Visit(BaseClassSpecifierNode& baseClassSpecifierNode)
606 {
607 if (firstBaseClass)
608 {
609 firstBaseClass = false;
610 writer.WriteOther(U": ");
611 }
612 else
613 {
614 writer.WriteOther(U", ");
615 }
616 MoveTo(baseClassSpecifierNode.GetSpan());
617 WriteSpecifiers(baseClassSpecifierNode.BaseSpecifiers());
618 writer.WriteSpace(1);
619 Symbol* symbol = symbolTable.GetSymbol(&baseClassSpecifierNode);
620 if (symbol && symbol->IsTypeSymbol() && !symbol->IsClassTemplateSpecializationSymbol())
621 {
622 TypeSymbol* type = static_cast<TypeSymbol*>(symbol);
623 std::vector<IdentifierNode*> idNodeSequence = symbolTable.GetIdNodeSequence(baseClassSpecifierNode.ClassName());
624 WriteType(type, idNodeSequence, nullptr);
625 }
626 else
627 {
628 baseClassSpecifierNode.ClassName()->Accept(*this);
629 }
630 }
631
632 void HtmlSourceCodeGenerator::Visit(BaseClassSpecifierSequenceNode& baseClassSpecifierSequenceNode)
633 {
634 baseClassSpecifierSequenceNode.Left()->Accept(*this);
635 baseClassSpecifierSequenceNode.Right()->Accept(*this);
636 }
637
638 void HtmlSourceCodeGenerator::Visit(MemberAccessDeclarationNode& memberAccessDeclarationNode)
639 {
640 if (currentAccess != memberAccessDeclarationNode.AccessSpecifier())
641 {
642 if (memberAccessDeclarationNode.ExplicitAccess())
643 {
644 WriteAccess(memberAccessDeclarationNode.GetSpan(), memberAccessDeclarationNode.AccessSpecifier());
645 }
646 currentAccess = memberAccessDeclarationNode.AccessSpecifier();
647 }
648 if (memberAccessDeclarationNode.Declaration())
649 {
650 memberAccessDeclarationNode.Declaration()->Accept(*this);
651 }
652 }
653
654 void HtmlSourceCodeGenerator::Visit(MemberDeclarationNode& memberDeclarationNode)
655 {
656 MoveTo(memberDeclarationNode.GetSpan());
657 WriteSpecifiers(memberDeclarationNode.Specifiers() & DeclSpecifierMask());
658 if (memberDeclarationNode.TypeExpr())
659 {
660 memberDeclarationNode.TypeExpr()->Accept(*this);
661 }
662 memberDeclarationNode.Declarator()->Accept(*this);
663 Specifier virtPureSpecifiers = memberDeclarationNode.Specifiers() & VirtPureSpecifierMask();
664 if (virtPureSpecifiers != Specifier::none)
665 {
666 writer.WriteSpace(1);
667 WriteSpecifiers(virtPureSpecifiers);
668 }
669 if (memberDeclarationNode.Initializer())
670 {
671 memberDeclarationNode.Initializer()->Accept(*this);
672 }
673 writer.WriteOther(U";");
674 }
675
676 void HtmlSourceCodeGenerator::Visit(FloatingLiteralNode& floatingLiteralNode)
677 {
678 MoveTo(floatingLiteralNode.GetSpan());
679 writer.WriteOther(floatingLiteralNode.Rep());
680 }
681
682 void HtmlSourceCodeGenerator::Visit(IntegerLiteralNode& integerLiteralNode)
683 {
684 MoveTo(integerLiteralNode.GetSpan());
685 writer.WriteOther(integerLiteralNode.Rep());
686 }
687
688 void HtmlSourceCodeGenerator::Visit(CharacterLiteralNode& characterLiteralNode)
689 {
690 MoveTo(characterLiteralNode.GetSpan());
691 writer.WriteString(characterLiteralNode.Rep());
692 }
693
694 void HtmlSourceCodeGenerator::Visit(StringLiteralNode& stringLiteralNode)
695 {
696 MoveTo(stringLiteralNode.GetSpan());
697 writer.WriteString(stringLiteralNode.Rep());
698 }
699
700 void HtmlSourceCodeGenerator::Visit(BooleanLiteralNode& booleanLiteralNode)
701 {
702 MoveTo(booleanLiteralNode.GetSpan());
703 writer.WriteKeyword(booleanLiteralNode.Rep());
704 }
705
706 void HtmlSourceCodeGenerator::Visit(NullPtrLiteralNode& nullPtrLiteralNode)
707 {
708 MoveTo(nullPtrLiteralNode.GetSpan());
709 writer.WriteKeyword(nullPtrLiteralNode.Rep());
710 }
711
712 void HtmlSourceCodeGenerator::Visit(FunctionNode& functionNode)
713 {
714 if ((functionNode.Specifiers() & (Specifier::delete_ | Specifier::default_)) != Specifier::none) return;
715 FunctionSymbol* prevFunction = currentFunction;
716 Symbol* symbol = symbolTable.GetSymbolNothrow(&functionNode);
717 if (symbol && symbol->IsFunctionSymbol())
718 {
719 currentFunction = static_cast<FunctionSymbol*>(symbol);
720 }
721 MoveTo(functionNode.GetSpan());
722 WriteSpecifiers(functionNode.Specifiers() & DeclSpecifierMask());
723 if (functionNode.TypeExpr())
724 {
725 functionNode.TypeExpr()->Accept(*this);
726 }
727 functionNode.Declarator()->Accept(*this);
728 Specifier virtPureSpecifiers = functionNode.Specifiers() & VirtPureSpecifierMask();
729 if (virtPureSpecifiers != Specifier::none)
730 {
731 writer.WriteSpace(1);
732 WriteSpecifiers(virtPureSpecifiers);
733 }
734 if (functionNode.Body())
735 {
736 blockLevel = 0;
737 functionNode.Body()->Accept(*this);
738 if (inlineCodeElement)
739 {
740 if (inlineLineElement)
741 {
742 inlineCodeElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(inlineLineElement.release()));
743 writer.SetInlineLineElement(nullptr);
744 }
745 Symbol* symbol = symbolTable.GetSymbolNothrow(&functionNode);
746 if (symbol)
747 {
748 inlineCodeMap[symbol->Id()] = std::move(inlineCodeElement);
749 }
750 else
751 {
752 inlineCodeElement.reset();
753 }
754 }
755 }
756 else
757 {
758 Specifier defaultOrDeleteSpecifier = functionNode.Specifiers() & DefaultDeleteSpecifierMask();
759 if (defaultOrDeleteSpecifier != Specifier::none)
760 {
761 if (virtPureSpecifiers != Specifier::none)
762 {
763 writer.WriteSpace(1);
764 }
765 WriteSpecifiers(defaultOrDeleteSpecifier);
766 writer.WriteOther(U";");
767 }
768 }
769 currentFunction = prevFunction;
770 }
771
772 void HtmlSourceCodeGenerator::Visit(SpecialMemberFunctionNode& specialMemberFunctionNode)
773 {
774 if ((specialMemberFunctionNode.Specifiers() & (Specifier::delete_ | Specifier::default_)) != Specifier::none) return;
775 FunctionSymbol* prevFunction = currentFunction;
776 Symbol* symbol = symbolTable.GetSymbolNothrow(&specialMemberFunctionNode);
777 if (symbol && symbol->IsFunctionSymbol())
778 {
779 currentFunction = static_cast<FunctionSymbol*>(symbol);
780 }
781 MoveTo(specialMemberFunctionNode.GetSpan());
782 WriteSpecifiers(specialMemberFunctionNode.Specifiers() & DeclSpecifierMask());
783 specialMemberFunctionNode.Declarator()->Accept(*this);
784 blockLevel = 0;
785 if (specialMemberFunctionNode.CtorInitializer())
786 {
787 int firstLineNumber = specialMemberFunctionNode.CtorInitializer()->GetSpan().line;
788 int lastLineNumber = specialMemberFunctionNode.FunctionBody()->EndBraceSpan().line;
789 if (lastLineNumber - firstLineNumber + 1 <= inlineCodeLimit)
790 {
791 inlineCodeElement.reset(new sngxml::dom::Element(U"span"));
792 inlineCodeElement->SetAttribute(U"class", U"code");
793 inlineCodeOffset = specialMemberFunctionNode.CtorInitializer()->GetSpan().start - (*lineStarts)[firstLineNumber - 1];
794 }
795 blockLevel = 1;
796 specialMemberFunctionNode.CtorInitializer()->Accept(*this);
797 }
798 if (specialMemberFunctionNode.FunctionBody())
799 {
800 if (inlineCodeElement)
801 {
802 inlineCodeOffset = specialMemberFunctionNode.FunctionBody()->GetSpan().start - (*lineStarts)[specialMemberFunctionNode.FunctionBody()->GetSpan().line - 1];
803 }
804 specialMemberFunctionNode.FunctionBody()->Accept(*this);
805 if (inlineCodeElement)
806 {
807 if (inlineLineElement)
808 {
809 inlineCodeElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(inlineLineElement.release()));
810 writer.SetInlineLineElement(nullptr);
811 }
812 Symbol* symbol = symbolTable.GetSymbolNothrow(&specialMemberFunctionNode);
813 if (symbol)
814 {
815 inlineCodeMap[symbol->Id()] = std::move(inlineCodeElement);
816 }
817 else
818 {
819 inlineCodeElement.reset();
820 }
821 }
822 }
823 else
824 {
825 Specifier defaultOrDeleteSpecifier = specialMemberFunctionNode.Specifiers() & DefaultDeleteSpecifierMask();
826 if (defaultOrDeleteSpecifier != Specifier::none)
827 {
828 WriteSpecifiers(defaultOrDeleteSpecifier);
829 writer.WriteOther(U";");
830 }
831 }
832 currentFunction = prevFunction;
833 }
834
835 void HtmlSourceCodeGenerator::Visit(LabeledStatementNode& labeledStatementNode)
836 {
837 MoveTo(labeledStatementNode.GetSpan());
838 writer.WriteIdentifier(labeledStatementNode.Label());
839 writer.WriteOther(U":");
840 labeledStatementNode.Child()->Accept(*this);
841 }
842
843 void HtmlSourceCodeGenerator::Visit(CaseStatementNode& caseStatementNode)
844 {
845 MoveTo(caseStatementNode.GetSpan());
846 writer.WriteKeyword(U"case");
847 caseStatementNode.CaseExpr()->Accept(*this);
848 writer.WriteOther(U":");
849 caseStatementNode.Child()->Accept(*this);
850 }
851
852 void HtmlSourceCodeGenerator::Visit(DefaultStatementNode& defaultStatementNode)
853 {
854 MoveTo(defaultStatementNode.GetSpan());
855 writer.WriteKeyword(U"default");
856 writer.WriteOther(U":");
857 defaultStatementNode.Child()->Accept(*this);
858 }
859
860 void HtmlSourceCodeGenerator::Visit(ExpressionStatementNode& expressionStatementNode)
861 {
862 MoveTo(expressionStatementNode.GetSpan());
863 if (expressionStatementNode.Child())
864 {
865 firstInitializer = true;
866 expressionStatementNode.Child()->Accept(*this);
867 }
868 writer.WriteOther(U";");
869 }
870
871 void HtmlSourceCodeGenerator::Visit(CompoundStatementNode& compoundStatementNode)
872 {
873 if (blockLevel == 0)
874 {
875 int firstLineNumber = compoundStatementNode.GetSpan().line;
876 int lastLineNumber = compoundStatementNode.EndBraceSpan().line;
877 if (lastLineNumber - firstLineNumber + 1 <= inlineCodeLimit)
878 {
879 inlineCodeElement.reset(new sngxml::dom::Element(U"span"));
880 inlineCodeElement->SetAttribute(U"class", U"code");
881 inlineCodeOffset = compoundStatementNode.GetSpan().start - (*lineStarts)[firstLineNumber - 1];
882 }
883 else
884 {
885 inlineCodeElement.reset();
886 }
887 }
888 MoveTo(compoundStatementNode.GetSpan());
889 writer.WriteOther(U"{");
890 if (compoundStatementNode.Child())
891 {
892 ++blockLevel;
893 compoundStatementNode.Child()->Accept(*this);
894 --blockLevel;
895 }
896 MoveTo(compoundStatementNode.EndBraceSpan());
897 writer.WriteOther(U"}");
898 }
899
900 void HtmlSourceCodeGenerator::Visit(StatementSequenceNode& statementSequenceNode)
901 {
902 statementSequenceNode.Left()->Accept(*this);
903 statementSequenceNode.Right()->Accept(*this);
904 }
905
906 void HtmlSourceCodeGenerator::Visit(IfStatementNode& ifStatementNode)
907 {
908 MoveTo(ifStatementNode.GetSpan());
909 writer.WriteKeyword(U"if ");
910 writer.WriteOther(U"(");
911 ifStatementNode.Condition()->Accept(*this);
912 writer.WriteOther(U")");
913 ifStatementNode.ThenS()->Accept(*this);
914 if (ifStatementNode.ElseS())
915 {
916 MoveTo(ifStatementNode.ElseSpan());
917 writer.WriteKeyword(U"else");
918 ifStatementNode.ElseS()->Accept(*this);
919 }
920 }
921
922 void HtmlSourceCodeGenerator::Visit(SwitchStatementNode& switchStatementNode)
923 {
924 MoveTo(switchStatementNode.GetSpan());
925 writer.WriteKeyword(U"switch ");
926 writer.WriteOther(U"(");
927 switchStatementNode.Condition()->Accept(*this);
928 writer.WriteOther(U")");
929 switchStatementNode.Statement()->Accept(*this);
930 }
931
932 void HtmlSourceCodeGenerator::Visit(WhileStatementNode& whileStatementNode)
933 {
934 MoveTo(whileStatementNode.GetSpan());
935 writer.WriteKeyword(U"while ");
936 writer.WriteOther(U"(");
937 whileStatementNode.Condition()->Accept(*this);
938 writer.WriteOther(U")");
939 whileStatementNode.Statement()->Accept(*this);
940 }
941
942 void HtmlSourceCodeGenerator::Visit(DoStatementNode& doStatementNode)
943 {
944 MoveTo(doStatementNode.GetSpan());
945 writer.WriteKeyword(U"do");
946 doStatementNode.Statement()->Accept(*this);
947 MoveTo(doStatementNode.WhileSpan());
948 writer.WriteKeyword(U"while");
949 writer.WriteSpace(1);
950 writer.WriteOther(U"(");
951 doStatementNode.Condition()->Accept(*this);
952 writer.WriteOther(U");");
953 }
954
955 void HtmlSourceCodeGenerator::Visit(RangeForStatementNode& rangeForStatementNode)
956 {
957 MoveTo(rangeForStatementNode.GetSpan());
958 writer.WriteKeyword(U"for ");
959 writer.WriteOther(U"(");
960 bool prevRangeForDeclaration = rangeForDeclaration;
961 rangeForDeclaration = true;
962 rangeForStatementNode.ForRangeDeclaration()->Accept(*this);
963 rangeForDeclaration = prevRangeForDeclaration;
964 writer.WriteOther(U" : ");
965 rangeForStatementNode.ForRangeInitializer()->Accept(*this);
966 writer.WriteOther(U")");
967 rangeForStatementNode.Statement()->Accept(*this);
968 }
969
970 void HtmlSourceCodeGenerator::Visit(ForStatementNode& forStatementNode)
971 {
972 MoveTo(forStatementNode.GetSpan());
973 writer.WriteKeyword(U"for ");
974 writer.WriteOther(U"(");
975 if (forStatementNode.InitS())
976 {
977 forStatementNode.InitS()->Accept(*this);
978 }
979 else
980 {
981 writer.WriteOther(U";");
982 }
983 if (forStatementNode.Condition())
984 {
985 forStatementNode.Condition()->Accept(*this);
986 }
987 writer.WriteOther(U";");
988 if (forStatementNode.LoopExpr())
989 {
990 forStatementNode.LoopExpr()->Accept(*this);
991 }
992 writer.WriteOther(U")");
993 forStatementNode.ActionS()->Accept(*this);
994 }
995
996 void HtmlSourceCodeGenerator::Visit(BreakStatementNode& breakStatementNode)
997 {
998 MoveTo(breakStatementNode.GetSpan());
999 writer.WriteKeyword(U"break");
1000 writer.WriteOther(U";");
1001 }
1002
1003 void HtmlSourceCodeGenerator::Visit(ContinueStatementNode& continueStatementNode)
1004 {
1005 MoveTo(continueStatementNode.GetSpan());
1006 writer.WriteKeyword(U"continue");
1007 writer.WriteOther(U";");
1008 }
1009
1010 void HtmlSourceCodeGenerator::Visit(ReturnStatementNode& returnStatementNode)
1011 {
1012 MoveTo(returnStatementNode.GetSpan());
1013 writer.WriteKeyword(U"return");
1014 if (returnStatementNode.ReturnExpr())
1015 {
1016 returnStatementNode.ReturnExpr()->Accept(*this);
1017 }
1018 writer.WriteOther(U";");
1019 }
1020
1021 void HtmlSourceCodeGenerator::Visit(GotoStatementNode& gotoStatementNode)
1022 {
1023 MoveTo(gotoStatementNode.GetSpan());
1024 writer.WriteKeyword(U"goto");
1025 writer.WriteSpace(1);
1026 writer.WriteIdentifier(gotoStatementNode.Target());
1027 writer.WriteOther(U";");
1028 }
1029
1030 void HtmlSourceCodeGenerator::Visit(DeclarationStatementNode& declarationStatementNode)
1031 {
1032 MoveTo(declarationStatementNode.GetSpan());
1033 declarationStatementNode.Child()->Accept(*this);
1034 }
1035
1036 void HtmlSourceCodeGenerator::Visit(TryStatementNode& tryStatementNode)
1037 {
1038 MoveTo(tryStatementNode.GetSpan());
1039 writer.WriteKeyword(U"try");
1040 tryStatementNode.TryBlock()->Accept(*this);
1041 tryStatementNode.Handlers()->Accept(*this);
1042 }
1043
1044 void HtmlSourceCodeGenerator::Visit(HandlerNode& handlerNode)
1045 {
1046 MoveTo(handlerNode.GetSpan());
1047 writer.WriteKeyword(U"catch ");
1048 writer.WriteOther(U"(");
1049 handlerNode.ExceptionDeclaration()->Accept(*this);
1050 writer.WriteOther(U")");
1051 handlerNode.CatchBlock()->Accept(*this);
1052 }
1053
1054 void HtmlSourceCodeGenerator::Visit(HandlerSequenceNode& handlerSequenceNode)
1055 {
1056 handlerSequenceNode.Left()->Accept(*this);
1057 handlerSequenceNode.Right()->Accept(*this);
1058 }
1059
1060 void HtmlSourceCodeGenerator::Visit(CatchAllNode& catchAllNode)
1061 {
1062 MoveTo(catchAllNode.GetSpan());
1063 writer.WriteOther(U"...");
1064 }
1065
1066 void HtmlSourceCodeGenerator::Visit(CtorInitializerNode& ctorInitializerNode)
1067 {
1068 MoveTo(ctorInitializerNode.GetSpan());
1069 writer.WriteOther(U":");
1070 firstMemberInitializer = true;
1071 ctorInitializerNode.Child()->Accept(*this);
1072 }
1073
1074 void HtmlSourceCodeGenerator::Visit(ExpressionListInitializerNode& expressionListInitializer)
1075 {
1076 MoveTo(expressionListInitializer.GetSpan());
1077 writer.WriteOther(U"(");
1078 if (expressionListInitializer.Child())
1079 {
1080 firstInitializer = true;
1081 expressionListInitializer.Child()->Accept(*this);
1082 }
1083 writer.WriteOther(U")");
1084 }
1085
1086 void HtmlSourceCodeGenerator::Visit(ExpressionInitializerNode& expressionInitializerNode)
1087 {
1088 if (firstInitializer)
1089 {
1090 firstInitializer = false;
1091 }
1092 else
1093 {
1094 writer.WriteOther(U", ");
1095 }
1096 MoveTo(expressionInitializerNode.GetSpan());
1097 expressionInitializerNode.Child()->Accept(*this);
1098 }
1099
1100 void HtmlSourceCodeGenerator::Visit(EnumTypeNode& enumTypeNode)
1101 {
1102 MoveTo(enumTypeNode.GetSpan());
1103 EnumKey enumKey = enumTypeNode.GetEnumKey();
1104 writer.WriteKeyword(ToString(enumKey));
1105 writer.WriteSpace(1);
1106 enumTypeNode.EnumName()->Accept(*this);
1107 if (enumTypeNode.EnumBase())
1108 {
1109 writer.WriteOther(U" : ");
1110 enumTypeNode.EnumBase()->Accept(*this);
1111 writer.WriteSpace(1);
1112 }
1113 MoveTo(enumTypeNode.OpenBraceSpan());
1114 writer.WriteOther(U"{");
1115 if (enumTypeNode.Enumerators())
1116 {
1117 firstEnumerator = true;
1118 enumTypeNode.Enumerators()->Accept(*this);
1119 }
1120 MoveTo(enumTypeNode.CloseBraceSpan());
1121 writer.WriteOther(U"};");
1122 }
1123
1124 void HtmlSourceCodeGenerator::Visit(EnumeratorNode& enumeratorNode)
1125 {
1126 if (firstEnumerator)
1127 {
1128 firstEnumerator = false;
1129 }
1130 else
1131 {
1132 writer.WriteOther(U", ");
1133 }
1134 MoveTo(enumeratorNode.GetSpan());
1135 writer.WriteIdentifier(enumeratorNode.Enumerator());
1136 if (enumeratorNode.Value())
1137 {
1138 MoveTo(enumeratorNode.AssignmentSignSpan());
1139 writer.WriteOther(U"=");
1140 MoveTo(enumeratorNode.Value()->GetSpan());
1141 writer.WriteOther(enumeratorNode.ValueStr());
1142 }
1143 }
1144
1145 void HtmlSourceCodeGenerator::Visit(EnumeratorSequenceNode& enumeratorSequenceNode)
1146 {
1147 enumeratorSequenceNode.Left()->Accept(*this);
1148 enumeratorSequenceNode.Right()->Accept(*this);
1149 }
1150
1151 void HtmlSourceCodeGenerator::Visit(AssignmentInitializerNode& assignmentInitializerNode)
1152 {
1153 MoveTo(assignmentInitializerNode.GetSpan());
1154 writer.WriteOther(U"=");
1155 firstInitializer = true;
1156 assignmentInitializerNode.Child()->Accept(*this);
1157 }
1158
1159 void HtmlSourceCodeGenerator::Visit(BracedInitializerListNode& bracedInitializerListNode)
1160 {
1161 MoveTo(bracedInitializerListNode.GetSpan());
1162 writer.WriteOther(U"{");
1163 if (bracedInitializerListNode.Child())
1164 {
1165 bool prevFirstInitializer = firstInitializer;
1166 firstInitializer = true;
1167 bracedInitializerListNode.Child()->Accept(*this);
1168 firstInitializer = prevFirstInitializer;
1169 }
1170 MoveTo(bracedInitializerListNode.EndBraceSpan());
1171 writer.WriteOther(U"}");
1172 }
1173
1174 void HtmlSourceCodeGenerator::Visit(MemberInitializerNode& memberInitializerNode)
1175 {
1176 if (firstMemberInitializer)
1177 {
1178 firstMemberInitializer = false;
1179 }
1180 else
1181 {
1182 writer.WriteOther(U", ");
1183 }
1184 MoveTo(memberInitializerNode.GetSpan());
1185 Symbol* symbol = symbolTable.GetSymbolNothrow(memberInitializerNode.Id());
1186 if (symbol && symbol->IsTypeSymbol())
1187 {
1188 TypeSymbol* type = static_cast<TypeSymbol*>(symbol);
1189 std::vector<IdentifierNode*> idNodeSequence = symbolTable.GetIdNodeSequence(memberInitializerNode.Id());
1190 TemplateIdNode* templateIdNode = nullptr;
1191 if (memberInitializerNode.Id()->IsTemplateIdNode())
1192 {
1193 templateIdNode = static_cast<TemplateIdNode*>(memberInitializerNode.Id());
1194 }
1195 WriteType(type, idNodeSequence, templateIdNode);
1196 }
1197 else
1198 {
1199 memberInitializerNode.Id()->Accept(*this);
1200 }
1201 memberInitializerNode.Initializer()->Accept(*this);
1202 }
1203
1204 void HtmlSourceCodeGenerator::Visit(MemberInitializerSequenceNode& memberInitializerSequenceNode)
1205 {
1206 memberInitializerSequenceNode.Left()->Accept(*this);
1207 memberInitializerSequenceNode.Right()->Accept(*this);
1208 }
1209
1210 void HtmlSourceCodeGenerator::Visit(FunctionDeclaratorNode& functionDeclaratorNode)
1211 {
1212 MoveTo(functionDeclaratorNode.GetSpan());
1213 skip = false;
1214 functionDeclaratorNode.Declarator()->Accept(*this);
1215 if (!skip)
1216 {
1217 writer.WriteOther(U"(");
1218 if (functionDeclaratorNode.Parameters())
1219 {
1220 firstParam = true;
1221 functionDeclaratorNode.Parameters()->Accept(*this);
1222 }
1223 writer.WriteOther(U")");
1224 if (functionDeclaratorNode.CVSpecifiers() != Specifier::none)
1225 {
1226 writer.WriteSpace(1);
1227 WriteSpecifiers(functionDeclaratorNode.CVSpecifiers());
1228 }
1229 }
1230 }
1231
1232 void HtmlSourceCodeGenerator::Visit(FunctionPtrIdNode& functionPtrIdNode)
1233 {
1234 MoveTo(functionPtrIdNode.GetSpan());
1235 writer.WriteOther(U"(*");
1236 writer.WriteIdentifier(functionPtrIdNode.Id());
1237 writer.WriteOther(U")");
1238 skip = true;
1239 }
1240
1241 void HtmlSourceCodeGenerator::Visit(MemberFunctionPtrIdNode& memberFunctionPtrIdNode)
1242 {
1243 MoveTo(memberFunctionPtrIdNode.GetSpan());
1244 writer.WriteOther(U"(");
1245 memberFunctionPtrIdNode.ClassNameNode()->Accept(*this);
1246 writer.WriteOther(U"::*");
1247 writer.WriteIdentifier(memberFunctionPtrIdNode.Id());
1248 writer.WriteOther(U")");
1249 skip = true;
1250 }
1251
1252 void HtmlSourceCodeGenerator::Visit(ArrayDeclaratorNode& arrayDeclaratorNode)
1253 {
1254 MoveTo(arrayDeclaratorNode.GetSpan());
1255 arrayDeclaratorNode.Declarator()->Accept(*this);
1256 writer.WriteOther(U"[");
1257 if (arrayDeclaratorNode.Size())
1258 {
1259 arrayDeclaratorNode.Size()->Accept(*this);
1260 }
1261 writer.WriteOther(U"]");
1262 }
1263
1264 void HtmlSourceCodeGenerator::Visit(InitDeclaratorNode& initDeclaratorNode)
1265 {
1266 MoveTo(initDeclaratorNode.GetSpan());
1267 initDeclaratorNode.Declarator()->Accept(*this);
1268 initDeclaratorNode.Initializer()->Accept(*this);
1269 }
1270
1271 void HtmlSourceCodeGenerator::Visit(IdDeclaratorNode& idDeclaratorNode)
1272 {
1273 MoveTo(idDeclaratorNode.GetSpan());
1274 idDeclaratorNode.IdNode()->Accept(*this);
1275 }
1276
1277 void HtmlSourceCodeGenerator::Visit(ParameterNode& parameterNode)
1278 {
1279 if (firstParam)
1280 {
1281 firstParam = false;
1282 }
1283 else
1284 {
1285 writer.WriteOther(U", ");
1286 }
1287 MoveTo(parameterNode.GetSpan());
1288 parameterNode.TypeExpr()->Accept(*this);
1289 if (parameterNode.Declarator())
1290 {
1291 parameterNode.Declarator()->Accept(*this);
1292 }
1293 }
1294
1295 void HtmlSourceCodeGenerator::Visit(ParameterSequenceNode& parameterSequenceNode)
1296 {
1297 parameterSequenceNode.Left()->Accept(*this);
1298 parameterSequenceNode.Right()->Accept(*this);
1299 }
1300
1301 void HtmlSourceCodeGenerator::Visit(SimpleTypeNode& simpleTypeNode)
1302 {
1303 MoveTo(simpleTypeNode.GetSpan());
1304 std::u32string str = simpleTypeNode.Str();
1305 std::vector<std::u32string> s = Split(str, ' ');
1306 bool first = true;
1307 for (const std::u32string& sp : s)
1308 {
1309 if (first)
1310 {
1311 first = false;
1312 }
1313 else
1314 {
1315 writer.WriteSpace(1);
1316 }
1317 writer.WriteKeyword(sp);
1318 }
1319 }
1320
1321 void HtmlSourceCodeGenerator::Visit(TypeParameterNode& typeParameterNode)
1322 {
1323 MoveTo(typeParameterNode.GetSpan());
1324 if (typeParameterNode.TypenameUsed())
1325 {
1326 writer.WriteKeyword(U"typename");
1327 }
1328 else
1329 {
1330 writer.WriteKeyword(U"class");
1331 }
1332 writer.WriteSpace(1);
1333 writer.WriteIdentifier(typeParameterNode.Id());
1334 if (typeParameterNode.DefaultTemplateParameter())
1335 {
1336 writer.WriteOther(U" = ");
1337 typeParameterNode.DefaultTemplateParameter()->Accept(*this);
1338 }
1339 }
1340
1341 void HtmlSourceCodeGenerator::Visit(TemplateParameterSequenceNode& templateParameterSequenceNode)
1342 {
1343 templateParameterSequenceNode.Left()->Accept(*this);
1344 templateParameterSequenceNode.Right()->Accept(*this);
1345 }
1346
1347 void HtmlSourceCodeGenerator::Visit(TemplateDeclarationNode& templateDeclarationNode)
1348 {
1349 MoveTo(templateDeclarationNode.GetSpan());
1350 writer.WriteKeyword(U"template");
1351 writer.WriteOther(U"<");
1352 if (templateDeclarationNode.TemplateParameters())
1353 {
1354 firstTemplateParameter = true;
1355 templateDeclarationNode.TemplateParameters()->Accept(*this);
1356 }
1357 writer.WriteOther(U">");
1358 templateDeclarationNode.Declaration()->Accept(*this);
1359 }
1360
1361 void HtmlSourceCodeGenerator::Visit(TemplateArgumentSequenceNode& templateArgumentSequenceNode)
1362 {
1363 MoveTo(templateArgumentSequenceNode.GetSpan());
1364 templateArgumentSequenceNode.Left()->Accept(*this);
1365 templateArgumentSequenceNode.Right()->Accept(*this);
1366 }
1367
1368 void HtmlSourceCodeGenerator::Visit(TemplateIdNode& templateIdNode)
1369 {
1370 MoveTo(templateIdNode.GetSpan());
1371 Symbol* symbol = symbolTable.GetSymbolNothrow(&templateIdNode);
1372 if (symbol && symbol->IsClassTemplateSpecializationSymbol())
1373 {
1374 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(symbol);
1375 WriteType(specialization, symbolTable.GetIdNodeSequence(&templateIdNode), &templateIdNode);
1376 return;
1377 }
1378 templateIdNode.Id()->Accept(*this);
1379 writer.WriteOther(U"<");
1380 if (templateIdNode.TemplateArguments())
1381 {
1382 firstTemplateArgument = true;
1383 templateIdNode.TemplateArguments()->Accept(*this);
1384 }
1385 writer.WriteOther(U">");
1386 }
1387
1388 void HtmlSourceCodeGenerator::Visit(TemplateArgumentNode& templateArgumentNode)
1389 {
1390 if (firstTemplateArgument)
1391 {
1392 firstTemplateArgument = false;
1393 }
1394 else
1395 {
1396 writer.WriteOther(U", ");
1397 }
1398 MoveTo(templateArgumentNode.GetSpan());
1399 templateArgumentNode.Arg()->Accept(*this);
1400 }
1401
1402 void HtmlSourceCodeGenerator::Visit(IdentifierNode& identifierNode)
1403 {
1404 Symbol* symbol = symbolTable.GetSymbolNothrow(&identifierNode);
1405 bool isType = symbol && symbol->IsTypeSymbol();
1406 WriteId(&identifierNode, symbol, isType);
1407 }
1408
1409 void HtmlSourceCodeGenerator::Visit(NestedIdNode& nestedIdNode)
1410 {
1411 if (nestedIdNode.Left())
1412 {
1413 nestedIdNode.Left()->Accept(*this);
1414 writer.WriteOther(U"::");
1415 }
1416 else
1417 {
1418 writer.WriteOther(U"::");
1419 }
1420 nestedIdNode.Right()->Accept(*this);
1421 }
1422
1423 void HtmlSourceCodeGenerator::Visit(OperatorFunctionIdNode& operatorFunctionIdNode)
1424 {
1425 WriteId(&operatorFunctionIdNode, symbolTable.GetSymbolNothrow(&operatorFunctionIdNode), false);
1426
1427 }
1428
1429 void HtmlSourceCodeGenerator::Visit(ConversionFunctionIdNode& conversionFunctionIdNode)
1430 {
1431 WriteId(&conversionFunctionIdNode, symbolTable.GetSymbolNothrow(&conversionFunctionIdNode), false);
1432 conversionFunctionIdNode.TypeExpr()->Accept(*this);
1433 }
1434
1435 void HtmlSourceCodeGenerator::Visit(DtorIdNode& dtorIdNode)
1436 {
1437 WriteId(&dtorIdNode, symbolTable.GetSymbolNothrow(&dtorIdNode), false);
1438 }
1439
1440 void HtmlSourceCodeGenerator::Visit(ExpressionSequenceNode& expressionSequenceNode)
1441 {
1442 expressionSequenceNode.Left()->Accept(*this);
1443 expressionSequenceNode.Right()->Accept(*this);
1444 }
1445
1446 void HtmlSourceCodeGenerator::Visit(CommaExpressionNode& commaExpressionNode)
1447 {
1448 MoveTo(commaExpressionNode.GetSpan());
1449 commaExpressionNode.Left()->Accept(*this);
1450 writer.WriteOther(U", ");
1451 commaExpressionNode.Right()->Accept(*this);
1452 }
1453
1454 void HtmlSourceCodeGenerator::Visit(AssignmentExpressionNode& assignmentExpressionNode)
1455 {
1456 MoveTo(assignmentExpressionNode.GetSpan());
1457 assignmentExpressionNode.Left()->Accept(*this);
1458 writer.WriteOther(OpStr(assignmentExpressionNode.Op()));
1459 firstInitializer = true;
1460 assignmentExpressionNode.Right()->Accept(*this);
1461 }
1462
1463 void HtmlSourceCodeGenerator::Visit(ConditionalExpressionNode& conditionalExpressionNode)
1464 {
1465 MoveTo(conditionalExpressionNode.GetSpan());
1466 conditionalExpressionNode.Condition()->Accept(*this);
1467 writer.WriteOther(U" ? ");
1468 conditionalExpressionNode.ThenExpr()->Accept(*this);
1469 writer.WriteOther(U" : ");
1470 conditionalExpressionNode.ElseExpr()->Accept(*this);
1471 }
1472
1473 void HtmlSourceCodeGenerator::Visit(ThrowExpressionNode& throwExpressionNode)
1474 {
1475 MoveTo(throwExpressionNode.GetSpan());
1476 writer.WriteKeyword(U"throw ");
1477 if (throwExpressionNode.Child())
1478 {
1479 throwExpressionNode.Child()->Accept(*this);
1480 }
1481 }
1482
1483 void HtmlSourceCodeGenerator::Visit(LogicalOrExpressionNode& logicalOrExpressionNode)
1484 {
1485 MoveTo(logicalOrExpressionNode.GetSpan());
1486 logicalOrExpressionNode.Left()->Accept(*this);
1487 writer.WriteOther(U" || ");
1488 logicalOrExpressionNode.Right()->Accept(*this);
1489 }
1490
1491 void HtmlSourceCodeGenerator::Visit(LogicalAndExpressionNode& logicalAndExpressionNode)
1492 {
1493 MoveTo(logicalAndExpressionNode.GetSpan());
1494 logicalAndExpressionNode.Left()->Accept(*this);
1495 writer.WriteOther(U" && ");
1496 logicalAndExpressionNode.Right()->Accept(*this);
1497 }
1498
1499 void HtmlSourceCodeGenerator::Visit(InclusiveOrExpressionNode& inclusiveOrExpressionNode)
1500 {
1501 MoveTo(inclusiveOrExpressionNode.GetSpan());
1502 inclusiveOrExpressionNode.Left()->Accept(*this);
1503 writer.WriteOther(U" | ");
1504 inclusiveOrExpressionNode.Right()->Accept(*this);
1505 }
1506
1507 void HtmlSourceCodeGenerator::Visit(ExclusiveOrExpressionNode& exclusiveOrExpressionNode)
1508 {
1509 MoveTo(exclusiveOrExpressionNode.GetSpan());
1510 exclusiveOrExpressionNode.Left()->Accept(*this);
1511 writer.WriteOther(U" ^ ");
1512 exclusiveOrExpressionNode.Right()->Accept(*this);
1513 }
1514
1515 void HtmlSourceCodeGenerator::Visit(AndExpressionNode& andExpressionNode)
1516 {
1517 MoveTo(andExpressionNode.GetSpan());
1518 andExpressionNode.Left()->Accept(*this);
1519 writer.WriteOther(U" & ");
1520 andExpressionNode.Right()->Accept(*this);
1521 }
1522
1523 void HtmlSourceCodeGenerator::Visit(EqualityExpressionNode& equalityExpressionNode)
1524 {
1525 MoveTo(equalityExpressionNode.GetSpan());
1526 equalityExpressionNode.Left()->Accept(*this);
1527 writer.WriteOther(OpStr(equalityExpressionNode.Op()));
1528 equalityExpressionNode.Right()->Accept(*this);
1529 }
1530
1531 void HtmlSourceCodeGenerator::Visit(RelationalExpressionNode& relationalExpressionNode)
1532 {
1533 MoveTo(relationalExpressionNode.GetSpan());
1534 relationalExpressionNode.Left()->Accept(*this);
1535 writer.WriteOther(OpStr(relationalExpressionNode.Op()));
1536 relationalExpressionNode.Right()->Accept(*this);
1537 }
1538
1539 void HtmlSourceCodeGenerator::Visit(ShiftExpressionNode& shiftExpressionNode)
1540 {
1541 MoveTo(shiftExpressionNode.GetSpan());
1542 shiftExpressionNode.Left()->Accept(*this);
1543 writer.WriteOther(OpStr(shiftExpressionNode.Op()));
1544 shiftExpressionNode.Right()->Accept(*this);
1545 }
1546
1547 void HtmlSourceCodeGenerator::Visit(AdditiveExpressionNode& additiveExpressionNode)
1548 {
1549 MoveTo(additiveExpressionNode.GetSpan());
1550 additiveExpressionNode.Left()->Accept(*this);
1551 writer.WriteOther(OpStr(additiveExpressionNode.Op()));
1552 additiveExpressionNode.Right()->Accept(*this);
1553 }
1554
1555 void HtmlSourceCodeGenerator::Visit(MultiplicativeExpressionNode& multiplicativeExpressionNode)
1556 {
1557 MoveTo(multiplicativeExpressionNode.GetSpan());
1558 multiplicativeExpressionNode.Left()->Accept(*this);
1559 writer.WriteOther(OpStr(multiplicativeExpressionNode.Op()));
1560 multiplicativeExpressionNode.Right()->Accept(*this);
1561 }
1562
1563 void HtmlSourceCodeGenerator::Visit(PMExpressionNode& pmExpressionNode)
1564 {
1565 MoveTo(pmExpressionNode.GetSpan());
1566 pmExpressionNode.Left()->Accept(*this);
1567 writer.WriteOther(OpStr(pmExpressionNode.Op()));
1568 pmExpressionNode.Right()->Accept(*this);
1569 }
1570
1571 void HtmlSourceCodeGenerator::Visit(CastExpressionNode& castExpressionNode)
1572 {
1573 MoveTo(castExpressionNode.GetSpan());
1574 writer.WriteOther(U"(");
1575 castExpressionNode.TypeExpr()->Accept(*this);
1576 writer.WriteOther(U")");
1577 castExpressionNode.Expr()->Accept(*this);
1578 }
1579
1580 void HtmlSourceCodeGenerator::Visit(UnaryExpressionNode& unaryExpressionNode)
1581 {
1582 MoveTo(unaryExpressionNode.GetSpan());
1583 writer.WriteOther(OpStr(unaryExpressionNode.Op()));
1584 unaryExpressionNode.Child()->Accept(*this);
1585 }
1586
1587 void HtmlSourceCodeGenerator::Visit(NewExpressionNode& newExpressionNode)
1588 {
1589 MoveTo(newExpressionNode.GetSpan());
1590 writer.WriteKeyword(U"new ");
1591 if (newExpressionNode.Placement())
1592 {
1593 writer.WriteOther(U"(");
1594 firstInitializer = true;
1595 newExpressionNode.Placement()->Accept(*this);
1596 writer.WriteOther(U")");
1597 }
1598 newExpressionNode.TypeExpr()->Accept(*this);
1599 writer.WriteOther(U"(");
1600 if (newExpressionNode.Initializer())
1601 {
1602 firstInitializer = true;
1603 newExpressionNode.Initializer()->Accept(*this);
1604 }
1605 writer.WriteOther(U")");
1606 }
1607
1608 void HtmlSourceCodeGenerator::Visit(DeleteExpressionNode& deleteExpressionNode)
1609 {
1610 MoveTo(deleteExpressionNode.GetSpan());
1611 writer.WriteKeyword(U"delete");
1612 if (deleteExpressionNode.Array())
1613 {
1614 writer.WriteOther(U"[]");
1615 }
1616 writer.WriteSpace(1);
1617 deleteExpressionNode.Child()->Accept(*this);
1618 }
1619
1620 void HtmlSourceCodeGenerator::Visit(SubscriptExpressionNode& subscriptExpressionNode)
1621 {
1622 MoveTo(subscriptExpressionNode.GetSpan());
1623 subscriptExpressionNode.Child()->Accept(*this);
1624 writer.WriteOther(U"[");
1625 subscriptExpressionNode.Index()->Accept(*this);
1626 writer.WriteOther(U"]");
1627 }
1628
1629 void HtmlSourceCodeGenerator::Visit(InvokeExpressionNode& invokeExpressionNode)
1630 {
1631 MoveTo(invokeExpressionNode.GetSpan());
1632 Symbol* prevInvokeSymbol = invokeSymbol;
1633 invokeSymbol = symbolTable.GetSymbolNothrow(&invokeExpressionNode);
1634 invokeExpressionNode.Child()->Accept(*this);
1635 invokeSymbol = prevInvokeSymbol;
1636 writer.WriteOther(U"(");
1637 if (invokeExpressionNode.Arguments())
1638 {
1639 firstInitializer = true;
1640 invokeExpressionNode.Arguments()->Accept(*this);
1641 }
1642 writer.WriteOther(U")");
1643 }
1644
1645 void HtmlSourceCodeGenerator::Visit(DotNode& dotNode)
1646 {
1647 MoveTo(dotNode.GetSpan());
1648 dotNode.Child()->Accept(*this);
1649 writer.WriteOther(U".");
1650 dotNode.Id()->Accept(*this);
1651 }
1652
1653 void HtmlSourceCodeGenerator::Visit(ArrowNode& arrowNode)
1654 {
1655 MoveTo(arrowNode.GetSpan());
1656 arrowNode.Child()->Accept(*this);
1657 writer.WriteOther(U"->");
1658 arrowNode.Id()->Accept(*this);
1659 }
1660
1661 void HtmlSourceCodeGenerator::Visit(PostfixIncNode& postfixIncNode)
1662 {
1663 MoveTo(postfixIncNode.GetSpan());
1664 postfixIncNode.Child()->Accept(*this);
1665 writer.WriteOther(U"++");
1666 }
1667
1668 void HtmlSourceCodeGenerator::Visit(PostfixDecNode& postfixDecNode)
1669 {
1670 MoveTo(postfixDecNode.GetSpan());
1671 postfixDecNode.Child()->Accept(*this);
1672 writer.WriteOther(U"--");
1673 }
1674
1675 void HtmlSourceCodeGenerator::Visit(CppCastExpressionNode& cppCastExpressionNode)
1676 {
1677 MoveTo(cppCastExpressionNode.GetSpan());
1678 writer.WriteKeyword(OpStr(cppCastExpressionNode.Op()));
1679 writer.WriteOther(U"<");
1680 cppCastExpressionNode.TypeExpr()->Accept(*this);
1681 writer.WriteOther(U">");
1682 writer.WriteOther(U"(");
1683 firstInitializer = true;
1684 cppCastExpressionNode.Expr()->Accept(*this);
1685 writer.WriteOther(U")");
1686 }
1687
1688 void HtmlSourceCodeGenerator::Visit(TypeIdExpressionNode& typeIdExpressionNode)
1689 {
1690 MoveTo(typeIdExpressionNode.GetSpan());
1691 writer.WriteKeyword(U"typeid");
1692 writer.WriteOther(U" (");
1693 typeIdExpressionNode.Child()->Accept(*this);
1694 writer.WriteOther(U")");
1695 }
1696
1697 void HtmlSourceCodeGenerator::Visit(ThisNode& thisNode)
1698 {
1699 MoveTo(thisNode.GetSpan());
1700 writer.WriteKeyword(U"this");
1701 }
1702
1703 void HtmlSourceCodeGenerator::Visit(ParenthesizedExprNode& parenthesizedExprNode)
1704 {
1705 MoveTo(parenthesizedExprNode.GetSpan());
1706 writer.WriteOther(U"(");
1707 parenthesizedExprNode.Child()->Accept(*this);
1708 writer.WriteOther(U")");
1709 }
1710
1711 void HtmlSourceCodeGenerator::Visit(LambdaExpressionNode& lambdaExpressionNode)
1712 {
1713 MoveTo(lambdaExpressionNode.GetSpan());
1714 writer.WriteOther(U"[");
1715 if (lambdaExpressionNode.Captures())
1716 {
1717 lambdaExpressionNode.Captures()->Accept(*this);
1718 }
1719 writer.WriteOther(U"]");
1720 if (lambdaExpressionNode.Parameters())
1721 {
1722 firstParam = true;
1723 writer.WriteOther(U"(");
1724 lambdaExpressionNode.Parameters()->Accept(*this);
1725 writer.WriteOther(U")");
1726 }
1727 lambdaExpressionNode.Body()->Accept(*this);
1728 }
1729
1730 void HtmlSourceCodeGenerator::Visit(CaptureSequenceNode& captureSequenceNode)
1731 {
1732 captureSequenceNode.Left()->Accept(*this);
1733 captureSequenceNode.Right()->Accept(*this);
1734 }
1735
1736 void HtmlSourceCodeGenerator::Visit(AssignCaptureNode& assignCaptureNode)
1737 {
1738 MoveTo(assignCaptureNode.GetSpan());
1739 writer.WriteOther(U"=");
1740 }
1741
1742 void HtmlSourceCodeGenerator::Visit(RefCaptureNode& refCaptureNode)
1743 {
1744 MoveTo(refCaptureNode.GetSpan());
1745 writer.WriteOther(U"&");
1746 }
1747
1748 void HtmlSourceCodeGenerator::Visit(ThisCaptureNode& thisCaptureNode)
1749 {
1750 MoveTo(thisCaptureNode.GetSpan());
1751 writer.WriteKeyword(U"this");
1752 }
1753
1754 void HtmlSourceCodeGenerator::Visit(IdentifierCaptureNode& identifierCaptureNode)
1755 {
1756 MoveTo(identifierCaptureNode.GetSpan());
1757 identifierCaptureNode.Child()->Accept(*this);
1758 }
1759
1760 void HtmlSourceCodeGenerator::Visit(ConstNode& constNode)
1761 {
1762 MoveTo(constNode.GetSpan());
1763 writer.WriteKeyword(U"const");
1764 constNode.Child()->Accept(*this);
1765 }
1766
1767 void HtmlSourceCodeGenerator::Visit(VolatileNode& volatileNode)
1768 {
1769 MoveTo(volatileNode.GetSpan());
1770 writer.WriteKeyword(U"volatile");
1771 volatileNode.Child()->Accept(*this);
1772 }
1773
1774 void HtmlSourceCodeGenerator::Visit(PointerNode& pointerNode)
1775 {
1776 MoveTo(pointerNode.GetSpan());
1777 pointerNode.Child()->Accept(*this);
1778 writer.WriteOther(U"*");
1779 }
1780
1781 void HtmlSourceCodeGenerator::Visit(RValueRefNode& rValueRefNode)
1782 {
1783 MoveTo(rValueRefNode.GetSpan());
1784 rValueRefNode.Child()->Accept(*this);
1785 writer.WriteOther(U"&&");
1786 }
1787
1788 void HtmlSourceCodeGenerator::Visit(LValueRefNode& lValueRefNode)
1789 {
1790 MoveTo(lValueRefNode.GetSpan());
1791 lValueRefNode.Child()->Accept(*this);
1792 writer.WriteOther(U"&");
1793 }
1794
1795 } }