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