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