1
2
3
4
5
6 using System;
7 using System.Collections;
8 using System.IO;
9 using System.Text;
10
11 namespace System.Lex
12 {
13 public class XmlParsingLog : ParsingLog
14 {
15 public XmlParsingLog(StreamWriter& stream_) : base(), formatter(stream_)
16 {
17 formatter.SetIndentSize(1);
18 }
19 public XmlParsingLog(StreamWriter& stream_, int maxLineLength_) : base(maxLineLength_), formatter(stream_)
20 {
21 formatter.SetIndentSize(1);
22 }
23 public inline CodeFormatter& Formatter()
24 {
25 return formatter;
26 }
27 [nodiscard]
28 public Result<bool> WriteElement(const ustring& elementName, const ustring& elementContent)
29 {
30 if (formatter.Error())
31 {
32 return Result<bool>(ErrorId(formatter.GetErrorId()));
33 }
34 auto convertedResult = XmlEscape(elementContent);
35 if (convertedResult.Error())
36 {
37 return Result<bool>(ErrorId(convertedResult.GetErrorId()));
38 }
39 ustring converted = convertedResult.Value();
40 int convertedLength = cast<int>(converted.Length());
41 int lineLength = 2 * cast<int>(elementName.Length()) + 5 + convertedLength;
42 ustring s = converted;
43 if (lineLength > MaxLineLength())
44 {
45 lineLength = lineLength + 3;
46 s = converted.Substring(0, Max(cast<int>(0), convertedLength - (lineLength - MaxLineLength()))) + u"...";
47 }
48 return Write(u"<" + elementName + u">" + s + u"</" + elementName + u">");
49 }
50 [nodiscard]
51 public Result<bool> Write(const ustring& s)
52 {
53 if (formatter.Error())
54 {
55 return Result<bool>(ErrorId(formatter.GetErrorId()));
56 }
57 auto utf8Result = ToUtf8(s);
58 if (utf8Result.Error())
59 {
60 return Result<bool>(ErrorId(utf8Result.GetErrorId()));
61 }
62 return formatter.WriteLine(utf8Result.Value());
63 }
64 public override void IncIndent()
65 {
66 formatter.IncIndent();
67 }
68 public override void DecIndent()
69 {
70 formatter.DecIndent();
71 }
72 [nodiscard]
73 public override Result<bool> WriteBeginRule(const ustring& ruleName)
74 {
75 return Write(u"<" + ruleName + u">");
76 }
77 [nodiscard]
78 public override Result<bool> WriteEndRule(const ustring& ruleName)
79 {
80 return Write(u"</" + ruleName + u">");
81 }
82 [nodiscard]
83 public override Result<bool> WriteTry(const ustring& s)
84 {
85 return WriteElement(u"try", s);
86 }
87 [nodiscard]
88 public override Result<bool> WriteSuccess(const ustring& match)
89 {
90 return WriteElement(u"success", match);
91 }
92 [nodiscard]
93 public override Result<bool> WriteFail()
94 {
95 return Write(u"<fail/>");
96 }
97 private CodeFormatter formatter;
98 }
99
100 [nodiscard]
101 public Result<ustring> XmlHexEscape(uchar c)
102 {
103 StringWriter writer;
104 auto hex = ToHexString(cast<uint>(c));
105 if (hex.Error())
106 {
107 return Result<ustring>(ErrorId(hex.GetErrorId()));
108 }
109 writer << "&#x" << hex.Value() << ";";
110 if (writer.Error())
111 {
112 return Result<ustring>(ErrorId(writer.GetErrorId()));
113 }
114 auto result = ToUtf32(writer.GetString());
115 if (result.Error())
116 {
117 return Result<ustring>(ErrorId(result.GetErrorId()));
118 }
119 return Result<ustring>(result.Value());
120 }
121
122 [nodiscard]
123 public Result<ustring> XmlCharStr(uchar c)
124 {
125 switch (c)
126 {
127 case '&': return Result<ustring>(u"&");
128 case '<': return Result<ustring>(u"<");
129 case '>': return Result<ustring>(u">");
130 case '\a': return Result<ustring>(u"\\a");
131 case '\b': return Result<ustring>(u"\\b");
132 case '\f': return Result<ustring>(u"\\f");
133 case '\n': return Result<ustring>(u"\\n");
134 case '\r': return Result<ustring>(u"\\r");
135 case '\t': return Result<ustring>(u"\\t");
136 case '\v': return Result<ustring>(u"\\v");
137 default:
138 {
139 if (cast<int>(c) >= 32 && cast<int>(c) <= 126)
140 {
141 return Result<ustring>(ustring(c, 1));
142 }
143 else
144 {
145 return XmlHexEscape(c);
146 }
147 }
148 }
149 return Result<ustring>();
150 }
151
152 [nodiscard]
153 public Result<ustring> XmlEscape(const ustring& s)
154 {
155 ustring result;
156 result.Reserve(2 * s.Length());
157 auto e = s.CEnd();
158 for (auto i = s.CBegin(); i != e; ++i;)
159 {
160 auto xmlCharStr = XmlCharStr(*i);
161 if (xmlCharStr.Error())
162 {
163 return Result<ustring>(ErrorId(xmlCharStr.GetErrorId()));
164 }
165 result.Append(xmlCharStr.Value());
166 }
167 return Result<ustring>(result);
168 }
169