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