1 using System;
  2 using System.Collections;
  3 using System.IO;
  4 
  5 namespace soulcm.scm2html
  6 {
  7     public const int noPrefix = 0;
  8 
  9     public const int utf16Prefix = 1;
 10 
 11     public const int utf32Prefix = 2;
 12 
 13     public void ParseHexChar(const string& fileNameuchar& valueconst uchar*& pconst uchar* econst System.Lex.Token& token)
 14     {
 15         if (p != e)
 16         {
 17             switch (cast<uchar>(*p))
 18             {
 19                 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
 20                 {
 21                     value = cast<uchar>(16 * cast<int>(value) + cast<int>(*p) - cast<int>('0'));
 22                     break;
 23                 }
 24                 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 25                 {
 26                     value = cast<uchar>(16 * cast<int>(value) + 10 + cast<int>(*p) - cast<int>('A'));
 27                     break;
 28                 }
 29                 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 30                 {
 31                     value = cast<uchar>(16 * cast<int>(value) + 10 + cast<int>(*p) - cast<int>('a'));
 32                     break;
 33                 }
 34             }
 35             ++p;
 36         }
 37         else
 38         {
 39             throw Exception("hex character expected at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(token.match.ToString()));
 40         }
 41     }
 42 
 43     public uchar ParseEscape(const string& fileNameconst uchar*& pconst uchar* econst System.Lex.Token& token)
 44     {
 45         uchar value = '\0';
 46         if (p != e && (*p == 'x' || *p == 'X'))
 47         {
 48             ++p;
 49             while (p != e && ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))
 50             {
 51                 ParseHexChar(fileNamevaluepetoken);
 52             }
 53         }
 54         else if (p != e && (*p == 'd' || *p == 'D'))
 55         {
 56             ++p;
 57             while (p != e && *p >= '0' && *p <= '9')
 58             {
 59                 value = cast<uchar>(10 * cast<int>(value) + cast<int>(*p) - cast<int>('0'));
 60                 ++p;
 61             }
 62         }
 63         else if (p != e && (*p >= '0' && *p <= '7'))
 64         {
 65             while (p != e && *p >= '0' && *p <= '7')
 66             {
 67                 value = cast<uchar>(8 * cast<int>(value) + cast<int>(*p) - cast<int>('0'));
 68                 ++p;
 69             }
 70         }
 71         else if (p != e && *p == 'u')
 72         {
 73             ++p;
 74             ParseHexChar(fileNamevaluepetoken);
 75             ParseHexChar(fileNamevaluepetoken);
 76             ParseHexChar(fileNamevaluepetoken);
 77             ParseHexChar(fileNamevaluepetoken);
 78         }
 79         else if (p != e && *p == 'U')
 80         {
 81             ++p;
 82             ParseHexChar(fileNamevaluepetoken);
 83             ParseHexChar(fileNamevaluepetoken);
 84             ParseHexChar(fileNamevaluepetoken);
 85             ParseHexChar(fileNamevaluepetoken);
 86             ParseHexChar(fileNamevaluepetoken);
 87             ParseHexChar(fileNamevaluepetoken);
 88             ParseHexChar(fileNamevaluepetoken);
 89             ParseHexChar(fileNamevaluepetoken);
 90         }
 91         else if (p != e)
 92         {
 93             switch (cast<uchar>(*p))
 94             {
 95                 case 'a': value = '\a';
 96                 break;
 97                 case 'b': value = '\b';
 98                 break;
 99                 case 'f': value = '\f';
100                 break;
101                 case 'n': value = '\n';
102                 break;
103                 case 'r': value = '\r';
104                 break;
105                 case 't': value = '\t';
106                 break;
107                 case 'v': value = '\v';
108                 break;
109                 default: value = *p;
110                 break;
111             }
112             ++p;
113         }
114         return value;
115     }
116 
117     public ustring MakeStrValue(const string& fileNameconst System.Lex.Token& token)
118     {
119         ustring strValue;
120         const uchar* p = token.match.begin;
121         const uchar* e = token.match.end;
122         if (p != e && *p == '\"')
123         {
124             ++p;
125         }
126         while (p != e && *p != '\r' && *p != '\n' && *p != '\"')
127         {
128             if (*p == '\\')
129             {
130                 ++p;
131                 strValue.Append(ParseEscape(fileNamepetoken)1);
132             }
133             else
134             {
135                 strValue.Append(*p1);
136                 ++p;
137             }
138         }
139         if (p != e && *p == '\"')
140         {
141             ++p;
142         }
143         if (p != e)
144         {
145             throw Exception("invalid string literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(token.match.ToString()));
146         }
147         return strValue;
148     }
149 
150     public ustring MakeExprStringValue(const string& fileNameconst System.Lex.Token& token)
151     {
152         ustring strValue;
153         const uchar* p = token.match.begin;
154         const uchar* e = token.match.end;
155         if (p != e && *p == '\"')
156         {
157             ++p;
158         }
159         while (p != e && *p != '\r' && *p != '\n' && *p != '\"')
160         {
161             if (*p == '\\')
162             {
163                 ++p;
164                 if (p != e && *p == '\"')
165                 {
166                     strValue.Append('\"'1);
167                     ++p;
168                 }
169                 else
170                 {
171                     strValue.Append('\\'1);
172                     strValue.Append(*p1);
173                     ++p;
174                 }
175             }
176             else
177             {
178                 strValue.Append(*p1);
179                 ++p;
180             }
181         }
182         if (p != e && *p == '\"')
183         {
184             ++p;
185         }
186         if (p != e)
187         {
188             throw Exception("invalid expression string literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(token.match.ToString()));
189         }
190         return strValue;
191     }
192 
193     public ustring MakePathValue(const string& fileNameconst System.Lex.Token& token)
194     {
195         ustring pathValue;
196         const uchar* p = token.match.begin;
197         const uchar* e = token.match.end;
198         if (p != e && *p == '<')
199         {
200             ++p;
201         }
202         while (p != e && *p != '\r' && *p != '\n' && *p != '>')
203         {
204             pathValue.Append(*p1);
205             ++p;
206         }
207         if (p != e && *p == '>')
208         {
209             ++p;
210         }
211         if (p != e)
212         {
213             throw Exception("invalid path literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(token.match.ToString()));
214         }
215         return pathValue;
216     }
217 
218     public int MakeActionIntValue(const string& fileNameconst System.Lex.Token& token)
219     {
220         int actionIntValue = 0;
221         const uchar* p = token.match.begin;
222         const uchar* e = token.match.end;
223         if (p == e)
224         {
225             throw Exception("invalid action integer value at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(token.match.ToString()));
226         }
227         while (p != e && *p >= '0' && *p <= '9')
228         {
229             actionIntValue = 10 * actionIntValue + cast<int>(*p) - cast<int>('0');
230             ++p;
231         }
232         if (p != e)
233         {
234             throw Exception("invalid action integer value at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(token.match.ToString()));
235         }
236         return actionIntValue;
237     }
238 
239     public ustring MakeExprRefId(const string& fileNameconst ustring& matchint line)
240     {
241         ustring exprRefId;
242         const uchar* p = match.Chars();
243         const uchar* e = match.Chars() + match.Length();
244         if (p != e && *p == '{')
245         {
246             ++p;
247         }
248         while (p != e && *p != '\r' && *p != '\n' && *p != '}')
249         {
250             exprRefId.Append(*p1);
251             ++p;
252         }
253         if (p != e && *p == '}')
254         {
255             ++p;
256         }
257         if (p != e)
258         {
259             throw Exception("invalid expression reference at " + fileName + ":" + ToString(line) + ": " + ToUtf8(match));
260         }
261         return exprRefId;
262     }
263 
264     public uchar MakeEscapeValue(const string& fileNameconst System.Lex.Token& token)
265     {
266         uchar escapeValue = '\0';
267         const uchar* p = token.match.begin;
268         const uchar* e = token.match.end;
269         if (p != e && *p == '\\')
270         {
271             ++p;
272         }
273         escapeValue = ParseEscape(fileNamepetoken);
274         if (p != e)
275         {
276             throw Exception("invalid escape at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(token.match.ToString()));
277         }
278         return escapeValue;
279     }
280 
281     public void ParseFloatingLiteral(const string& fileNameconst System.Lex.Token& tokendouble& floatingLitbool& floatingLitFloat)
282     {
283         floatingLit = 0.000000;
284         floatingLitFloat = false;
285         const uchar* p = token.match.begin;
286         const uchar* e = token.match.end;
287         string str;
288         while (p != e && ((*p >= '0' && *p <= '9') || *p == '.' || *p == 'e' || *p == 'E' || *p == '-' || *p == '+'))
289         {
290             str.Append(cast<char>(*p)1);
291             ++p;
292         }
293         if (p != e && (*p == 'f' || *p == 'F'))
294         {
295             ++p;
296             floatingLitFloat = true;
297         }
298         if (p != e)
299         {
300             throw Exception("invalid floating literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
301         }
302         if (floatingLitFloat) floatingLit = ParseFloat(str);
303         else floatingLit = ParseDouble(str);
304     }
305 
306     public void ParseIntegerLiteral(const string& fileNameconst System.Lex.Token& tokenulong& intLitbool& intLitUnsigned)
307     {
308         intLit = 0u;
309         intLitUnsigned = false;
310         const uchar* p = token.match.begin;
311         const uchar* e = token.match.end;
312         if (p != e && *p == '0')
313         {
314             ++p;
315             if (p != e && (*p == 'x' || *p == 'X'))
316             {
317                 ++p;
318                 while (p != e && ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')))
319                 {
320                     switch (cast<uchar>(*p))
321                     {
322                         case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
323                         {
324                             intLit = 16u * intLit + cast<ulong>(*p) - cast<ulong>('0');
325                             break;
326                         }
327                         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
328                         {
329                             intLit = 16u * intLit + 10u + cast<ulong>(*p) - cast<ulong>('A');
330                             break;
331                         }
332                         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
333                         {
334                             intLit = 16u * intLit + 10u + cast<ulong>(*p) - cast<ulong>('a');
335                             break;
336                         }
337                     }
338                     ++p;
339                 }
340             }
341             else
342             {
343                 while (p != e && *p >= '0' && *p <= '7')
344                 {
345                     intLit = 8u * intLit + cast<ulong>(*p) - cast<ulong>('0');
346                     ++p;
347                 }
348             }
349         }
350         else if (p != e && *p >= '1' && *p <= '9')
351         {
352             while (p != e && *p >= '0' && *p <= '9')
353             {
354                 intLit = 10u * intLit + cast<ulong>(*p) - cast<ulong>('0');
355                 ++p;
356             }
357         }
358         else
359         {
360             throw Exception("invalid integer literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
361         }
362         if (p != e && (*p == 'u' || *p == 'U'))
363         {
364             ++p;
365             intLitUnsigned = true;
366         }
367         if (p != e)
368         {
369             throw Exception("invalid integer literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
370         }
371     }
372 
373     public void ParseCharacterLiteral(const string& fileNameconst System.Lex.Token& tokenuchar& charLitint& charLitPrefix)
374     {
375         charLit = '\0';
376         charLitPrefix = noPrefix;
377         const uchar* p = token.match.begin;
378         const uchar* e = token.match.end;
379         if (p != e && *p == 'w')
380         {
381             charLitPrefix = utf16Prefix;
382             ++p;
383         }
384         else if (p != e && *p == 'u')
385         {
386             charLitPrefix = utf32Prefix;
387             ++p;
388         }
389         if (p != e && *p == '\'')
390         {
391             ++p;
392             if (p != e && *p == '\\')
393             {
394                 ++p;
395                 charLit = ParseEscape(fileNamepetoken);
396             }
397             else
398             {
399                 string s;
400                 while (p != e && *p != '\r' && *p != '\n' && *p != '\'')
401                 {
402                     s.Append(cast<char>(*p)1);
403                     ++p;
404                 }
405                 ustring u = ToUtf32(s);
406                 if (u.Length() != 1)
407                 {
408                     throw Exception("invalid character literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
409                 }
410                 charLit = u[0];
411             }
412             if (p != e && *p == '\'')
413             {
414                 ++p;
415             }
416             if (p != e)
417             {
418                 throw Exception("invalid character literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
419             }
420         }
421         else
422         {
423             throw Exception("invalid character literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
424         }
425     }
426 
427     public void ParseStringLiteral(const string& fileNameconst System.Lex.Token& tokenustring& stringLitint& stringLitPrefix)
428     {
429         stringLit.Clear();
430         stringLitPrefix = noPrefix;
431         const uchar* p = token.match.begin;
432         const uchar* e = token.match.end;
433         if (p != e && *p == 'w')
434         {
435             stringLitPrefix = utf16Prefix;
436             ++p;
437         }
438         else if (p != e && *p == 'u')
439         {
440             stringLitPrefix = utf32Prefix;
441             ++p;
442         }
443         if (p != e && *p == '@')
444         {
445             ++p;
446             if (p != e && *p == '\"')
447             {
448                 ++p;
449                 while (p != e && *p != '\"')
450                 {
451                     stringLit.Append(*p1);
452                     ++p;
453                 }
454                 if (p != e && *p == '\"')
455                 {
456                     ++p;
457                 }
458                 if (p != e)
459                 {
460                     throw Exception("invalid string literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
461                 }
462             }
463         }
464         else
465         {
466             if (p != e && *p == '\"')
467             {
468                 ++p;
469                 while (p != e && *p != '\r' && *p != '\n' && *p != '\"')
470                 {
471                     if (*p == '\\')
472                     {
473                         ++p;
474                         stringLit.Append(ParseEscape(fileNamepetoken)1);
475                     }
476                     else
477                     {
478                         stringLit.Append(*p1);
479                         ++p;
480                     }
481                 }
482                 if (p != e && *p == '\"')
483                 {
484                     ++p;
485                 }
486                 if (p != e)
487                 {
488                     throw Exception("invalid string literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
489                 }
490             }
491             else
492             {
493                 throw Exception("invalid string literal at " + fileName + ":" + ToString(token.line) + ": " + ToUtf8(ustring(token.match.begintoken.match.end)));
494             }
495         }
496     }
497 
498     public string MakeFilePath(const System.Lex.Lexeme& lexeme)
499     {
500         ustring s;
501         const uchar* p = lexeme.begin;
502         const uchar* e = lexeme.end;
503         if (p != e && *p == '<')
504         {
505             ++p;
506         }
507         while (p != e && *p != '>')
508         {
509             s.Append(*p1);
510             ++p;
511         }
512         if (p != e && *p == '>')
513         {
514             ++p;
515         }
516         if (p != e)
517         {
518             throw Exception("invalid file path \'" + ToUtf8(ustring(lexeme.beginlexeme.end)));
519         }
520         return ToUtf8(s);
521     }
522 } // namespace soulcm.scm2html