1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.RegularExpressions
10 {
11 [nodiscard]
12 public Result<bool> ParseHexChar(const string& fileName, uchar& value, const uchar*& p, const uchar* e, const System.Lex.Token& token)
13 {
14 if (p != e)
15 {
16 bool notHex = false;
17 uchar c = *p;
18 switch (c)
19 {
20 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
21 {
22 value = cast<uchar>(16 * cast<int>(value) + cast<int>(c) - cast<int>('0'));
23 break;
24 }
25 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
26 {
27 value = cast<uchar>(16 * cast<int>(value) + 10 + cast<int>(c) - cast<int>('A'));
28 break;
29 }
30 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
31 {
32 value = cast<uchar>(16 * cast<int>(value) + 10 + cast<int>(c) - cast<int>('a'));
33 break;
34 }
35 default:
36 {
37 notHex = true;
38 break;
39 }
40 }
41 if (notHex)
42 {
43 string errorMessage = "hex character expected at " + fileName + ":" + ToString(token.line);
44 int errorId = AllocateError(errorMessage);
45 return Result<bool>(ErrorId(errorId));
46 }
47 ++p;
48 }
49 else
50 {
51 string errorMessage = "hex character expected at " + fileName + ":" + ToString(token.line);
52 int errorId = AllocateError(errorMessage);
53 return Result<bool>(ErrorId(errorId));
54 }
55 return Result<bool>(true);
56 }
57
58 [nodiscard]
59 public Result<uchar> ParseEscape(const string& fileName, const uchar*& p, const uchar* e, const System.Lex.Token& token)
60 {
61 uchar value;
62 if (p != e && (*p == 'x' || *p == 'X'))
63 {
64 ++p;
65 while (p != e && ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))
66 {
67 auto hexCharResult = ParseHexChar(fileName, value, p, e, token);
68 if (hexCharResult.Error())
69 {
70 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
71 }
72 }
73 }
74 else if (p != e && (*p == 'd' || *p == 'D'))
75 {
76 ++p;
77 while (p != e && *p >= '0' && *p <= '9')
78 {
79 value = cast<uchar>(10 * cast<int>(value) + (cast<int>(*p) - cast<int>('0')));
80 ++p;
81 }
82 }
83 else if (p != e && (*p >= '0' && *p <= '7'))
84 {
85 while (p != e && *p >= '0' && *p <= '7')
86 {
87 value = cast<uchar>(8 * cast<int>(value) + (cast<int>(*p) - cast<int>('0')));
88 ++p;
89 }
90 }
91 else if (p != e && *p == 'u')
92 {
93 ++p;
94 auto hexCharResult = ParseHexChar(fileName, value, p, e, token);
95 if (hexCharResult.Error())
96 {
97 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
98 }
99 hexCharResult = ParseHexChar(fileName, value, p, e, token);
100 if (hexCharResult.Error())
101 {
102 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
103 }
104 hexCharResult = ParseHexChar(fileName, value, p, e, token);
105 if (hexCharResult.Error())
106 {
107 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
108 }
109 hexCharResult = ParseHexChar(fileName, value, p, e, token);
110 if (hexCharResult.Error())
111 {
112 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
113 }
114 }
115 else if (p != e && *p == 'U')
116 {
117 ++p;
118 auto hexCharResult = ParseHexChar(fileName, value, p, e, token);
119 if (hexCharResult.Error())
120 {
121 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
122 }
123 hexCharResult = ParseHexChar(fileName, value, p, e, token);
124 if (hexCharResult.Error())
125 {
126 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
127 }
128 hexCharResult = ParseHexChar(fileName, value, p, e, token);
129 if (hexCharResult.Error())
130 {
131 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
132 }
133 hexCharResult = ParseHexChar(fileName, value, p, e, token);
134 if (hexCharResult.Error())
135 {
136 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
137 }
138 hexCharResult = ParseHexChar(fileName, value, p, e, token);
139 if (hexCharResult.Error())
140 {
141 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
142 }
143 hexCharResult = ParseHexChar(fileName, value, p, e, token);
144 if (hexCharResult.Error())
145 {
146 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
147 }
148 hexCharResult = ParseHexChar(fileName, value, p, e, token);
149 if (hexCharResult.Error())
150 {
151 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
152 }
153 hexCharResult = ParseHexChar(fileName, value, p, e, token);
154 if (hexCharResult.Error())
155 {
156 return Result<uchar>(ErrorId(hexCharResult.GetErrorId()));
157 }
158 }
159 else if (p != e)
160 {
161 uchar c = *p;
162 switch (c)
163 {
164 case 'a': value = '\a'; break;
165 case 'b': value = '\b'; break;
166 case 'f': value = '\f'; break;
167 case 'n': value = '\n'; break;
168 case 'r': value = '\r'; break;
169 case 't': value = '\t'; break;
170 case 'v': value = '\v'; break;
171 default: value = c; break;
172 }
173 ++p;
174 }
175 return Result<uchar>(value);
176 }
177
178 [nodiscard]
179 public Result<uchar> MakeEscapeValue(const string& fileName, const System.Lex.Token& token)
180 {
181 uchar* p = token.match.begin;
182 uchar* e = token.match.end;
183 Result<uchar> escapeValue;
184 if (*p == '\\')
185 {
186 ++p;
187 escapeValue = ParseEscape(fileName, p, e, token);
188 if (escapeValue.Error())
189 {
190 return Result<uchar>(ErrorId(escapeValue.GetErrorId()));
191 }
192 }
193 if (p != e)
194 {
195 string matchValue;
196 auto utf8Result = ToUtf8(token.match.ToString());
197 if (!utf8Result.Error())
198 {
199 matchValue = utf8Result.Value();
200 }
201 int errorId = AllocateError("invalid escape value at " + fileName + ":" + ToString(token.line) + ": " + matchValue);
202 return Result<uchar>(ErrorId(errorId));
203 }
204 return escapeValue;
205 }
206