1
2
3
4
5
6 #include <sng2html/sng2html/GrammarHtmlGenerator.hpp>
7 #include <sng2html/sng2html/Domain.hpp>
8 #include <sng2html/sng2html/Symbol.hpp>
9 #include <sng2html/sng2html/RegEx.hpp>
10 #include <sngxml/dom/Document.hpp>
11 #include <sngxml/dom/Element.hpp>
12 #include <sngxml/dom/CharacterData.hpp>
13 #include <soulng/util/Unicode.hpp>
14 #include <soulng/util/TextUtils.hpp>
15 #include <fstream>
16 #include <iostream>
17
18 namespace sng2html { namespace sng2html {
19
20 using namespace soulng::util;
21 using namespace soulng::unicode;
22
23 void AppendRuleName(sngxml::dom::Element* parent, const std::u32string& name)
24 {
25 for (char32_t c : name)
26 {
27 switch (c)
28 {
29 case '-': parent->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"#8209"))); break;
30 default: parent->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(std::u32string(1, c))));
31 }
32 }
33 }
34
35 GrammarHtmlGeneratorVisitor::GrammarHtmlGeneratorVisitor(bool verbose_, std::std::unordered_map<GrammarParser*, Grammar*>&parserGrammarMap_, std::std::unordered_map<RuleParser*, Rule*>&parserRuleMap_,
36 std::std::unordered_map<LexerFile*, Grammar*>&lexerGrammarMap_, std::std::unordered_map<Expression*, Rule*>&lexerRuleMap_,
37 std::std::unordered_map<std::u32string, LexerFile*>&lexerMap_, conststd::u32string&styleFilePath_):
38 verbose(verbose_), parserGrammarMap(parserGrammarMap_), parserRuleMap(parserRuleMap_),
39 lexerGrammarMap(lexerGrammarMap_), lexerRuleMap(lexerRuleMap_),
40 lexerMap(lexerMap_), styleFilePath(styleFilePath_), ruleTable(nullptr), ruleBodyElement(nullptr), currentGrammar(nullptr),
41 lexerFile(nullptr)
42 {
43 }
44
45 void GrammarHtmlGeneratorVisitor::Visit(Char& symbol)
46 {
47 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
48 spanElement->SetAttribute(U"class", U"ruleChar");
49 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(CharStr(symbol.Chr()))));
50 ruleBodyElement->AppendChild(std::move(spanElement));
51 }
52
53 void GrammarHtmlGeneratorVisitor::Visit(Any& symbol)
54 {
55 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
56 spanElement->SetAttribute(U"class", U"ruleOp");
57 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U".")));
58 ruleBodyElement->AppendChild(std::move(spanElement));
59 }
60
61 void GrammarHtmlGeneratorVisitor::Visit(Range& symbol)
62 {
63 if (symbol.Start() == symbol.End())
64 {
65 std::unique_ptr<sngxml::dom::Element> startSpanElement(new sngxml::dom::Element(U"span"));
66 startSpanElement->SetAttribute(U"class", U"ruleCharSet");
67 startSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(CharStr(symbol.Start()))));
68 ruleBodyElement->AppendChild(std::move(startSpanElement));
69 }
70 else
71 {
72 std::unique_ptr<sngxml::dom::Element> startSpanElement(new sngxml::dom::Element(U"span"));
73 startSpanElement->SetAttribute(U"class", U"ruleCharSet");
74 startSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(CharStr(symbol.Start()))));
75 ruleBodyElement->AppendChild(std::move(startSpanElement));
76 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
77 spanElement->SetAttribute(U"class", U"ruleOp");
78 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"#8209")));
79 ruleBodyElement->AppendChild(std::move(spanElement));
80 std::unique_ptr<sngxml::dom::Element> endSpanElement(new sngxml::dom::Element(U"span"));
81 endSpanElement->SetAttribute(U"class", U"ruleCharSet");
82 endSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(CharStr(symbol.End()))));
83 ruleBodyElement->AppendChild(std::move(endSpanElement));
84 }
85 }
86
87 void GrammarHtmlGeneratorVisitor::Visit(Class& symbol)
88 {
89 std::unique_ptr<sngxml::dom::Element> leftSpanElement(new sngxml::dom::Element(U"span"));
90 leftSpanElement->SetAttribute(U"class", U"ruleOp");
91 leftSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"[")));
92 if (symbol.Inverse())
93 {
94 leftSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"^")));
95 }
96 ruleBodyElement->AppendChild(std::move(leftSpanElement));
97 for (const auto& symbol : symbol.Symbols())
98 {
99 symbol->Accept(*this);
100 }
101 std::unique_ptr<sngxml::dom::Element> rightSpanElement(new sngxml::dom::Element(U"span"));
102 rightSpanElement->SetAttribute(U"class", U"ruleOp");
103 rightSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"]")));
104 ruleBodyElement->AppendChild(std::move(rightSpanElement));
105 }
106
107 void GrammarHtmlGeneratorVisitor::Visit(Alt& alt)
108 {
109 alt.Left()->Accept(*this);
110 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
111 spanElement->SetAttribute(U"class", U"ruleOp");
112 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U" | ")));
113 ruleBodyElement->AppendChild(std::move(spanElement));
114 alt.Right()->Accept(*this);
115 }
116
117 void GrammarHtmlGeneratorVisitor::Visit(Cat& cat)
118 {
119 bool chars = cat.Left()->IsCharSymbolExpr() && cat.Right()->IsCharSymbolExpr();
120 cat.Left()->Accept(*this);
121 if (!chars)
122 {
123 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
124 spanElement->SetAttribute(U"class", U"ruleOp");
125 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U" ")));
126 ruleBodyElement->AppendChild(std::move(spanElement));
127 }
128 cat.Right()->Accept(*this);
129 }
130
131 void GrammarHtmlGeneratorVisitor::Visit(Kleene& kleene)
132 {
133 kleene.Child()->Accept(*this);
134 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
135 spanElement->SetAttribute(U"class", U"ruleOp");
136 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"*")));
137 ruleBodyElement->AppendChild(std::move(spanElement));
138 }
139
140 void GrammarHtmlGeneratorVisitor::Visit(Pos& pos)
141 {
142 pos.Child()->Accept(*this);
143 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
144 spanElement->SetAttribute(U"class", U"ruleOp");
145 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"+")));
146 ruleBodyElement->AppendChild(std::move(spanElement));
147 }
148
149 void GrammarHtmlGeneratorVisitor::Visit(Opt& opt)
150 {
151 opt.Child()->Accept(*this);
152 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
153 spanElement->SetAttribute(U"class", U"ruleOp");
154 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"?")));
155 ruleBodyElement->AppendChild(std::move(spanElement));
156 }
157
158 void GrammarHtmlGeneratorVisitor::Visit(ParenExpr& parenExpr)
159 {
160 std::unique_ptr<sngxml::dom::Element> leftSpanElement(new sngxml::dom::Element(U"span"));
161 leftSpanElement->SetAttribute(U"class", U"ruleOp");
162 leftSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"(")));
163 ruleBodyElement->AppendChild(std::move(leftSpanElement));
164 parenExpr.Child()->Accept(*this);
165 std::unique_ptr<sngxml::dom::Element> rightSpanElement(new sngxml::dom::Element(U"span"));
166 rightSpanElement->SetAttribute(U"class", U"ruleOp");
167 rightSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U")")));
168 ruleBodyElement->AppendChild(std::move(rightSpanElement));
169 }
170
171 void GrammarHtmlGeneratorVisitor::Visit(SymbolExpr& symbolExpr)
172 {
173 symbolExpr.GetSymbol()->Accept(*this);
174 }
175
176 void GrammarHtmlGeneratorVisitor::Visit(RefExpr& refExpr)
177 {
178 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
179 spanElement->SetAttribute(U"class", U"lexerRule");
180 std::unique_ptr<sngxml::dom::Element> linkElement(new sngxml::dom::Element(U"a"));
181 linkElement->SetAttribute(U"class", U"lexerRule");
182 std::u32string linkText;
183 auto grammarIt = lexerGrammarMap.find(lexerFile);
184 if (grammarIt != lexerGrammarMap.cend())
185 {
186 Grammar* grammar = grammarIt->second;
187 linkText.append(grammar->HtmlFileName());
188 }
189 else
190 {
191 throw std::runtime_error("lexical grammar not found");
192 }
193 Expression* expression = lexerFile->GetExpressions()->Get(refExpr.ExprId());
194 Rule* rule = nullptr;
195 auto ruleIt = lexerRuleMap.find(expression);
196 if (ruleIt != lexerRuleMap.cend())
197 {
198 rule = ruleIt->second;
199 linkText.append(U"#").append(rule->Name());
200 }
201 else
202 {
203 throw std::runtime_error("lexical rule not found");
204 }
205 linkElement->SetAttribute(U"href", linkText);
206 AppendRuleName(linkElement.get(), rule->Name());
207 spanElement->AppendChild(std::move(linkElement));
208 ruleBodyElement->AppendChild(std::move(spanElement));
209 }
210
211 void GrammarHtmlGeneratorVisitor::Visit(EmptyParser& parser)
212 {
213 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
214 spanElement->SetAttribute(U"class", U"ruleOp");
215 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"<empty>")));
216 ruleBodyElement->AppendChild(std::move(spanElement));
217 }
218
219 void GrammarHtmlGeneratorVisitor::Visit(TokenParser& parser)
220 {
221 std::u32string keyword;
222 if (lexerFile)
223 {
224 Keywords* keywords = lexerFile->GetKeywords();
225 if (keywords)
226 {
227 keyword = keywords->GetKeyword(parser.TokenName());
228 }
229 }
230 if (!keyword.empty())
231 {
232 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
233 spanElement->SetAttribute(U"class", U"ruleKeyword");
234 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(keyword)));
235 ruleBodyElement->AppendChild(std::move(spanElement));
236 }
237 else
238 {
239 RegExpression* regEx = nullptr;
240 if (lexerFile)
241 {
242 LexerStatement* statement = lexerFile->GetLexer()->GetStatement(parser.TokenName());
243 if (statement)
244 {
245 regEx = statement->RegEx();
246 }
247 }
248 if (regEx)
249 {
250 regEx->Accept(*this);
251 }
252 else
253 {
254 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
255 spanElement->SetAttribute(U"class", U"ruleString");
256 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(parser.TokenName())));
257 ruleBodyElement->AppendChild(std::move(spanElement));
258 }
259 }
260 }
261
262 void GrammarHtmlGeneratorVisitor::Visit(CharParser& parser)
263 {
264 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
265 spanElement->SetAttribute(U"class", U"ruleChar");
266 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(CharStr(parser.Chr()))));
267 ruleBodyElement->AppendChild(std::move(spanElement));
268 }
269
270 void GrammarHtmlGeneratorVisitor::Visit(StringParser& parser)
271 {
272 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
273 spanElement->SetAttribute(U"class", U"ruleString");
274 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(StringStr(parser.Str()))));
275 ruleBodyElement->AppendChild(std::move(spanElement));
276 }
277
278 void GrammarHtmlGeneratorVisitor::Visit(CharSetParser& parser)
279 {
280 std::u32string text = U"[";
281 if (parser.Set().Inverse())
282 {
283 text.append(U"^");
284 }
285 for (const auto& range : parser.Set().Ranges())
286 {
287 text.append(CharStr(static_cast<char32_t>(range.first)));
288 if (range.last != range.first)
289 {
290 text.append(1, '-').append(CharStr(static_cast<char32_t>(range.last)));
291 }
292 }
293 text.append(1, ']');
294 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
295 spanElement->SetAttribute(U"class", U"ruleCharSet");
296 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(text)));
297 ruleBodyElement->AppendChild(std::move(spanElement));
298 }
299
300 void GrammarHtmlGeneratorVisitor::Visit(OptionalParser& parser)
301 {
302 parser.Child()->Accept(*this);
303 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
304 spanElement->SetAttribute(U"class", U"ruleOp");
305 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"?")));
306 ruleBodyElement->AppendChild(std::move(spanElement));
307 }
308
309 void GrammarHtmlGeneratorVisitor::Visit(KleeneParser& parser)
310 {
311 parser.Child()->Accept(*this);
312 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
313 spanElement->SetAttribute(U"class", U"ruleOp");
314 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"*")));
315 ruleBodyElement->AppendChild(std::move(spanElement));
316 }
317
318 void GrammarHtmlGeneratorVisitor::Visit(PositiveParser& parser)
319 {
320 parser.Child()->Accept(*this);
321 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
322 spanElement->SetAttribute(U"class", U"ruleOp");
323 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"+")));
324 ruleBodyElement->AppendChild(std::move(spanElement));
325 }
326
327 void GrammarHtmlGeneratorVisitor::Visit(ExpectationParser& parser)
328 {
329 parser.Child()->Accept(*this);
330 }
331
332 void GrammarHtmlGeneratorVisitor::Visit(GroupingParser& parser)
333 {
334 if (!parser.Parent() || parser.Parent()->IsAction() || ((parser.Parent()->IsPostfix() || parser.ParentIsList()) && parser.Child()->IsAction()))
335 {
336 parser.Child()->Accept(*this);
337 }
338 else
339 {
340 std::unique_ptr<sngxml::dom::Element> leftSpanElement(new sngxml::dom::Element(U"span"));
341 leftSpanElement->SetAttribute(U"class", U"ruleOp");
342 leftSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U"(")));
343 ruleBodyElement->AppendChild(std::move(leftSpanElement));
344 parser.Child()->Accept(*this);
345 std::unique_ptr<sngxml::dom::Element> rightSpanElement(new sngxml::dom::Element(U"span"));
346 rightSpanElement->SetAttribute(U"class", U"ruleOp");
347 rightSpanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U")")));
348 ruleBodyElement->AppendChild(std::move(rightSpanElement));
349 }
350 }
351
352 void GrammarHtmlGeneratorVisitor::Visit(SequenceParser& parser)
353 {
354 if (parser.Left()->IsEmptyOrEmptyActionParser())
355 {
356 if (!parser.Right()->IsEmptyOrEmptyActionParser())
357 {
358 parser.Right()->Accept(*this);
359 }
360 }
361 else if (parser.Right()->IsEmptyOrEmptyActionParser())
362 {
363 if (!parser.Left()->IsEmptyOrEmptyActionParser())
364 {
365 parser.Left()->Accept(*this);
366 }
367 }
368 else
369 {
370 parser.Left()->Accept(*this);
371 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
372 spanElement->SetAttribute(U"class", U"ruleOp");
373 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U" ")));
374 ruleBodyElement->AppendChild(std::move(spanElement));
375 parser.Right()->Accept(*this);
376 }
377 }
378
379 void GrammarHtmlGeneratorVisitor::Visit(AlternativeParser& parser)
380 {
381 parser.Left()->Accept(*this);
382 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
383 spanElement->SetAttribute(U"class", U"ruleOp");
384 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U" | ")));
385 ruleBodyElement->AppendChild(std::move(spanElement));
386 parser.Right()->Accept(*this);
387 }
388
389 void GrammarHtmlGeneratorVisitor::Visit(DifferenceParser& parser)
390 {
391 parser.Left()->Accept(*this);
392 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
393 spanElement->SetAttribute(U"class", U"ruleOp");
394 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U" ")));
395 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"minus")));
396 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U" ")));
397 ruleBodyElement->AppendChild(std::move(spanElement));
398 parser.Right()->Accept(*this);
399 }
400
401 void GrammarHtmlGeneratorVisitor::Visit(ListParser& parser)
402 {
403 parser.Left()->Accept(*this);
404 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
405 spanElement->SetAttribute(U"class", U"ruleOp");
406 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(U" % ")));
407 ruleBodyElement->AppendChild(std::move(spanElement));
408 parser.Right()->Accept(*this);
409 }
410
411 void GrammarHtmlGeneratorVisitor::Visit(ActionParser& parser)
412 {
413 parser.Child()->Accept(*this);
414 }
415
416 void GrammarHtmlGeneratorVisitor::Visit(NonterminalParser& parser)
417 {
418 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
419 spanElement->SetAttribute(U"class", U"ruleLink");
420 std::unique_ptr<sngxml::dom::Element> linkElement(new sngxml::dom::Element(U"a"));
421 linkElement->SetAttribute(U"class", U"ruleLink");
422 RuleParser* ruleParser = parser.Rule();
423 GrammarParser* grammarParser = ruleParser->GetGrammar();
424 Rule* rule = GetRule(ruleParser);
425 std::u32string linkText;
426 if (grammarParser == currentGrammar)
427 {
428 linkText.append(U"#").append(rule->Name());
429 }
430 else
431 {
432 Grammar* grammar = GetGrammar(grammarParser);
433 linkText.append(grammar->HtmlFileName()).append(U"#").append(rule->Name());
434 }
435 linkElement->SetAttribute(U"href", linkText);
436 AppendRuleName(linkElement.get(), rule->Name());
437 spanElement->AppendChild(std::move(linkElement));
438 ruleBodyElement->AppendChild(std::move(spanElement));
439 }
440
441 void GrammarHtmlGeneratorVisitor::Visit(RuleParser& parser)
442 {
443 std::unique_ptr<sngxml::dom::Element> trElement(new sngxml::dom::Element(U"tr"));
444 Rule* rule = GetRule(&parser);
445 trElement->SetAttribute(U"id", rule->Name());
446 std::unique_ptr<sngxml::dom::Element> tdNameElement(new sngxml::dom::Element(U"td"));
447 tdNameElement->SetAttribute(U"class", U"grammarFirstCol");
448 std::unique_ptr<sngxml::dom::Element> ruleSpanElement(new sngxml::dom::Element(U"span"));
449 ruleSpanElement->SetAttribute(U"class", U"rule");
450 AppendRuleName(ruleSpanElement.get(), rule->Name());
451 tdNameElement->AppendChild(std::move(ruleSpanElement));
452 trElement->AppendChild(std::move(tdNameElement));
453 std::unique_ptr<sngxml::dom::Element> tdArrowElement(new sngxml::dom::Element(U"td"));
454 tdArrowElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"rarr")));
455 tdArrowElement->SetAttribute(U"class", U"grammarSecondCol");
456 trElement->AppendChild(std::move(tdArrowElement));
457 std::unique_ptr<sngxml::dom::Element> tdRuleBodyElement(new sngxml::dom::Element(U"td"));
458 tdRuleBodyElement->SetAttribute(U"class", U"grammarThirdCol");
459 tdRuleBodyElement->SetAttribute(U"xml:space", U"preserve");
460 ruleBodyElement = tdRuleBodyElement.get();
461 parser.Definition()->Accept(*this);
462 trElement->AppendChild(std::move(tdRuleBodyElement));
463 ruleTable->AppendChild(std::move(trElement));
464 }
465
466 void GrammarHtmlGeneratorVisitor::Visit(GrammarParser& parser)
467 {
468 Grammar* grammar = GetGrammar(&parser);
469 GrammarParser* prevGrammar = currentGrammar;
470 currentGrammar = &parser;
471 LexerFile* prevLexerFile = lexerFile;
472 auto it = lexerMap.find(parser.Lexer());
473 if (it != lexerMap.cend())
474 {
475 lexerFile = it->second;
476 }
477 std::unique_ptr<sngxml::dom::Document> grammarDoc(new sngxml::dom::Document());
478 std::unique_ptr<sngxml::dom::Element> htmlElement(new sngxml::dom::Element(U"html"));
479 std::unique_ptr<sngxml::dom::Element> headElement(new sngxml::dom::Element(U"head"));
480 std::unique_ptr<sngxml::dom::Element> metaElement(new sngxml::dom::Element(U"meta"));
481 metaElement->SetAttribute(U"charset", U"utf-8");
482 headElement->AppendChild(std::move(metaElement));
483 std::unique_ptr<sngxml::dom::Element> titleElement(new sngxml::dom::Element(U"title"));
484 titleElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(grammar->Title())));
485 headElement->AppendChild(std::move(titleElement));
486 std::unique_ptr<sngxml::dom::Element> linkElement(new sngxml::dom::Element(U"link"));
487 linkElement->SetAttribute(U"rel", U"stylesheet");
488 linkElement->SetAttribute(U"type", U"text/css");
489 linkElement->SetAttribute(U"href", styleFilePath);
490 headElement->AppendChild(std::move(linkElement));
491 htmlElement->AppendChild(std::move(headElement));
492 std::unique_ptr<sngxml::dom::Element> bodyElement(new sngxml::dom::Element(U"body"));
493 std::unique_ptr<sngxml::dom::Element> headerElement(new sngxml::dom::Element(U"h1"));
494 headerElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(grammar->Title())));
495 bodyElement->AppendChild(std::move(headerElement));
496 std::unique_ptr<sngxml::dom::Element> tableElement(new sngxml::dom::Element(U"table"));
497 tableElement->SetAttribute(U"class", U"grammar");
498 ruleTable = tableElement.get();
499 int n = parser.Rules().size();
500 for (int i = 0; i < n; ++i)
501 {
502 parser.Rules()[i]->Accept(*this);
503 }
504 bodyElement->AppendChild(std::move(tableElement));
505 htmlElement->AppendChild(std::move(bodyElement));
506 grammarDoc->AppendChild(std::move(htmlElement));
507 std::ofstream htmlFile(grammar->HtmlFilePath());
508 CodeFormatter formatter(htmlFile);
509 formatter.SetIndentSize(1);
510 grammarDoc->Write(formatter);
511 currentGrammar = prevGrammar;
512 lexerFile = prevLexerFile;
513 if (verbose)
514 {
515 std::cout << "==> " << grammar->HtmlFilePath() << std::endl;
516 }
517 }
518
519 void GrammarHtmlGeneratorVisitor::Visit(ParserFile& parserFile)
520 {
521 for (const auto& grammar : parserFile.Parsers())
522 {
523 grammar->Accept(*this);
524 }
525 }
526
527 void GrammarHtmlGeneratorVisitor::Visit(Domain& domain)
528 {
529 for (const auto& parserFile : domain.ParserFiles())
530 {
531 parserFile->Accept(*this);
532 }
533 }
534
535 void GrammarHtmlGeneratorVisitor::Visit(LexerFile& lexerFile)
536 {
537 this->lexerFile = &lexerFile;
538 auto it = lexerGrammarMap.find(this->lexerFile);
539 if (it != lexerGrammarMap.cend())
540 {
541 Grammar* grammar = it->second;
542 std::unique_ptr<sngxml::dom::Document> grammarDoc(new sngxml::dom::Document());
543 std::unique_ptr<sngxml::dom::Element> htmlElement(new sngxml::dom::Element(U"html"));
544 std::unique_ptr<sngxml::dom::Element> headElement(new sngxml::dom::Element(U"head"));
545 std::unique_ptr<sngxml::dom::Element> metaElement(new sngxml::dom::Element(U"meta"));
546 metaElement->SetAttribute(U"charset", U"utf-8");
547 headElement->AppendChild(std::move(metaElement));
548 std::unique_ptr<sngxml::dom::Element> titleElement(new sngxml::dom::Element(U"title"));
549 titleElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(grammar->Title())));
550 headElement->AppendChild(std::move(titleElement));
551 std::unique_ptr<sngxml::dom::Element> linkElement(new sngxml::dom::Element(U"link"));
552 linkElement->SetAttribute(U"rel", U"stylesheet");
553 linkElement->SetAttribute(U"type", U"text/css");
554 linkElement->SetAttribute(U"href", styleFilePath);
555 headElement->AppendChild(std::move(linkElement));
556 htmlElement->AppendChild(std::move(headElement));
557 std::unique_ptr<sngxml::dom::Element> bodyElement(new sngxml::dom::Element(U"body"));
558 std::unique_ptr<sngxml::dom::Element> headerElement(new sngxml::dom::Element(U"h1"));
559 headerElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(grammar->Title())));
560 bodyElement->AppendChild(std::move(headerElement));
561 std::unique_ptr<sngxml::dom::Element> tableElement(new sngxml::dom::Element(U"table"));
562 tableElement->SetAttribute(U"class", U"grammar");
563 ruleTable = tableElement.get();
564 int n = grammar->Rules().size();
565 for (int i = 0; i < n; ++i)
566 {
567 Rule* rule = grammar->Rules()[i].get();
568 std::unique_ptr<sngxml::dom::Element> trElement(new sngxml::dom::Element(U"tr"));
569 trElement->SetAttribute(U"id", rule->Name());
570 std::unique_ptr<sngxml::dom::Element> tdNameElement(new sngxml::dom::Element(U"td"));
571 tdNameElement->SetAttribute(U"class", U"grammarFirstCol");
572 std::unique_ptr<sngxml::dom::Element> ruleSpanElement(new sngxml::dom::Element(U"span"));
573 ruleSpanElement->SetAttribute(U"class", U"rule");
574 AppendRuleName(ruleSpanElement.get(), rule->Name());
575 tdNameElement->AppendChild(std::move(ruleSpanElement));
576 trElement->AppendChild(std::move(tdNameElement));
577 std::unique_ptr<sngxml::dom::Element> tdArrowElement(new sngxml::dom::Element(U"td"));
578 tdArrowElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"rarr")));
579 tdArrowElement->SetAttribute(U"class", U"grammarSecondCol");
580 trElement->AppendChild(std::move(tdArrowElement));
581 std::unique_ptr<sngxml::dom::Element> tdRuleBodyElement(new sngxml::dom::Element(U"td"));
582 tdRuleBodyElement->SetAttribute(U"class", U"grammarThirdCol");
583 tdRuleBodyElement->SetAttribute(U"xml:space", U"preserve");
584 ruleBodyElement = tdRuleBodyElement.get();
585 rule->GetExpression()->RegEx()->Accept(*this);
586 trElement->AppendChild(std::move(tdRuleBodyElement));
587 ruleTable->AppendChild(std::move(trElement));
588 }
589 bodyElement->AppendChild(std::move(tableElement));
590 htmlElement->AppendChild(std::move(bodyElement));
591 grammarDoc->AppendChild(std::move(htmlElement));
592 std::ofstream htmlFile(grammar->HtmlFilePath());
593 CodeFormatter formatter(htmlFile);
594 formatter.SetIndentSize(1);
595 grammarDoc->Write(formatter);
596 if (verbose)
597 {
598 std::cout << "==> " << grammar->HtmlFilePath() << std::endl;
599 }
600
601 }
602 else
603 {
604 throw std::runtime_error("lexical grammar not found");
605 }
606 }
607
608 Grammar* GrammarHtmlGeneratorVisitor::GetGrammar(GrammarParser* parser) const
609 {
610 auto it = parserGrammarMap.find(parser);
611 if (it != parserGrammarMap.cend())
612 {
613 return it->second;
614 }
615 else
616 {
617 throw std::runtime_error("grammar for parser '" + ToUtf8(parser->Name()) + "' not found");
618 }
619 }
620
621 Rule* GrammarHtmlGeneratorVisitor::GetRule(RuleParser* parser) const
622 {
623 auto it = parserRuleMap.find(parser);
624 if (it != parserRuleMap.cend())
625 {
626 return it->second;
627 }
628 else
629 {
630 throw std::runtime_error("rule for parser '" + ToUtf8(parser->Name()) + "' not found");
631 }
632 }
633
634 } }