OSDN Git Service

crystaledit: Make almost the same code into a common function
[winmerge-jp/winmerge-jp.git] / Externals / crystaledit / editlib / siod.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 //  File:    siod.cpp
3 //  Version: 1.1.0.4
4 //  Updated: 19-Jul-1998
5 //
6 //  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
7 //  E-mail:     prantl@ff.cuni.cz
8 //
9 //  SIOD syntax highlighing definition
10 //
11 //  You are free to use or modify this code to the following restrictions:
12 //  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
13 //  will be enough. If you can't (or don't want to), contact me personally.
14 //  - LEAVE THIS HEADER INTACT
15 ////////////////////////////////////////////////////////////////////////////
16
17 #include "StdAfx.h"
18 #include "crystallineparser.h"
19 #include "SyntaxColors.h"
20 #include "string_util.h"
21
22 #ifdef _DEBUG
23 #define new DEBUG_NEW
24 #endif
25
26 //  C++ keywords (MSVC5.0 + POET5.0)
27 static LPCTSTR s_apszSiodKeywordList[] =
28   {
29     _T("abs"),
30     _T("alarm"),
31     _T("and"),
32     _T("append"),
33     _T("apply"),
34     _T("ass"),
35     _T("assoc"),
36     _T("assq"),
37     _T("assv"),
38     _T("base64decode"),
39     _T("base64encode"),
40     _T("begin"),
41     _T("caaar"),
42     _T("caadr"),
43     _T("caar"),
44     _T("cadar"),
45     _T("caddr"),
46     _T("cadr"),
47     _T("car"),
48     _T("cdaar"),
49     _T("cdadr"),
50     _T("cdar"),
51     _T("cddar"),
52     _T("cdddr"),
53     _T("cddr"),
54     _T("cdr"),
55     _T("cond"),
56     _T("cons-array"),
57     _T("define"),
58     _T("eq?"),
59     _T("equal?"),
60     _T("eqv?"),
61     _T("eval"),
62     _T("exec"),
63     _T("exit"),
64     _T("fclose"),
65     _T("fopen"),
66     _T("if"),
67     _T("lambda"),
68     _T("length"),
69     _T("let"),
70     _T("let*"),
71     _T("letrec"),
72     _T("list"),
73     _T("load"),
74     _T("max"),
75     _T("member"),
76     _T("memq"),
77     _T("memv"),
78     _T("min"),
79     _T("nil"),
80     _T("not"),
81     _T("null?"),
82     _T("number->string"),
83     _T("number?"),
84     _T("or"),
85     _T("pair?"),
86     _T("quit"),
87     _T("quote"),
88     _T("read"),
89     _T("reverse"),
90     _T("set!"),
91     _T("set-car!"),
92     _T("set-cdr!"),
93     _T("string->number"),
94     _T("string-append"),
95     _T("string-length"),
96     _T("string?"),
97     _T("substring"),
98     _T("symbol?"),
99   };
100
101 static LPCTSTR s_apszUser1KeywordList[] =
102   {
103     _T("acos"),
104     _T("asin"),
105     _T("atan"),
106     _T("cos"),
107     _T("exp"),
108     _T("log"),
109     _T("sin"),
110     _T("sqrt"),
111     _T("tan"),
112   };
113
114 static LPCTSTR s_apszUser2KeywordList[] =
115   {
116     _T("%%%memref"),
117     _T("%%closure-code"),
118     _T("%%closure-env"),
119     _T("%%closure"),
120     _T("%%stack-limit"),
121     _T("*after-gc*"),
122     _T("*args*"),
123     _T("*catch"),
124     _T("*env*"),
125     _T("*eval-history-ptr*"),
126     _T("*pi*"),
127     _T("*plists*"),
128     _T("*throw"),
129     _T("*traced*"),
130     _T("access-problem?"),
131     _T("allocate-heap"),
132     _T("apropos"),
133     _T("aref"),
134     _T("array->hexstr"),
135     _T("aset"),
136     _T("ash"),
137     _T("atan2"),
138     _T("benchmark-eval"),
139     _T("benchmark-funcall1"),
140     _T("benchmark-funcall2"),
141     _T("bit-and"),
142     _T("bit-not"),
143     _T("bit-or"),
144     _T("bit-xor"),
145     _T("butlast"),
146     _T("bytes-append"),
147     _T("chdir"),
148     _T("chmod"),
149     _T("chown"),
150     _T("closedir"),
151     _T("copy-list"),
152     _T("cpu-usage-limits"),
153     _T("crypt"),
154     _T("current-resource-usage"),
155     _T("datlength"),
156     _T("datref"),
157     _T("decode-file-mode"),
158     _T("delete-file"),
159     _T("delq"),
160     _T("encode-file-mode"),
161     _T("encode-open-flags"),
162     _T("endpwent"),
163     _T("env-lookup"),
164     _T("eof-val"),
165     _T("errobj"),
166     _T("error"),
167     _T("F_GETLK"),
168     _T("F_SETLK"),
169     _T("F_SETLKW"),
170     _T("fast-load"),
171     _T("fast-print"),
172     _T("fast-read"),
173     _T("fast-save"),
174     _T("fchmod"),
175     _T("fflush"),
176     _T("file-times"),
177     _T("first"),
178     _T("fmod"),
179     _T("fnmatch"),
180     _T("fork"),
181     _T("fread"),
182     _T("fseek"),
183     _T("fstat"),
184     _T("ftell"),
185     _T("fwrite"),
186     _T("gc-info"),
187     _T("gc-status"),
188     _T("gc"),
189     _T("get"),
190     _T("getc"),
191     _T("getcwd"),
192     _T("getenv"),
193     _T("getgid"),
194     _T("getgrgid"),
195     _T("getpass"),
196     _T("getpgrp"),
197     _T("getpid"),
198     _T("getppid"),
199     _T("getpwent"),
200     _T("getpwnam"),
201     _T("getpwuid"),
202     _T("gets"),
203     _T("getuid"),
204     _T("gmtime"),
205     _T("hexstr->bytes"),
206     _T("href"),
207     _T("hset"),
208     _T("html-encode"),
209     _T("intern"),
210     _T("kill"),
211     _T("larg-default"),
212     _T("last-c-error"),
213     _T("last"),
214     _T("lchown"),
215     _T("link"),
216     _T("lkey-default"),
217     _T("load-so"),
218     _T("localtime"),
219     _T("lref-default"),
220     _T("lstat"),
221     _T("make-list"),
222     _T("mapcar"),
223     _T("md5-final"),
224     _T("md5-init"),
225     _T("md5-update"),
226     _T("mkdatref"),
227     _T("mkdir"),
228     _T("mktime"),
229     _T("nconc"),
230     _T("nice"),
231     _T("nreverse"),
232     _T("nth"),
233     _T("opendir"),
234     _T("os-classification"),
235     _T("parse-number"),
236     _T("pclose"),
237     _T("popen"),
238     _T("pow"),
239     _T("prin1"),
240     _T("print-to-string"),
241     _T("print"),
242     _T("prog1"),
243     _T("putc"),
244     _T("putenv"),
245     _T("putprop"),
246     _T("puts"),
247     _T("qsort"),
248     _T("rand"),
249     _T("random"),
250     _T("read-from-string"),
251     _T("readdir"),
252     _T("readline"),
253     _T("readlink"),
254     _T("realtime"),
255     _T("rename"),
256     _T("require-so"),
257     _T("require"),
258     _T("rest"),
259     _T("rld-pathnames"),
260     _T("rmdir"),
261     _T("runtime"),
262     _T("save-forms"),
263     _T("sdatref"),
264     _T("set-eval-history"),
265     _T("set-symbol-value!"),
266     _T("setprop"),
267     _T("setpwent"),
268     _T("setuid"),
269     _T("siod-lib"),
270     _T("sleep"),
271     _T("so-ext"),
272     _T("srand"),
273     _T("srandom"),
274     _T("stat"),
275     _T("strbreakup"),
276     _T("strcat"),
277     _T("strcmp"),
278     _T("strcpy"),
279     _T("strcspn"),
280     _T("strftime"),
281     _T("string-dimension"),
282     _T("string-downcase"),
283     _T("string-lessp"),
284     _T("string-search"),
285     _T("string-trim-left"),
286     _T("string-trim-right"),
287     _T("string-trim"),
288     _T("string-upcase"),
289     _T("strptime"),
290     _T("strspn"),
291     _T("subset"),
292     _T("substring-equal?"),
293     _T("swrite"),
294     _T("sxhash"),
295     _T("symbol-bound?"),
296     _T("symbol-value"),
297     _T("symbolconc"),
298     _T("symlink"),
299     _T("system"),
300     _T("t"),
301     _T("the-environment"),
302     _T("trace"),
303     _T("trunc"),
304     _T("typeof"),
305     _T("unbreakupstr"),
306     _T("ungetc"),
307     _T("unix-ctime"),
308     _T("unix-time->strtime"),
309     _T("unix-time"),
310     _T("unlink"),
311     _T("untrace"),
312     _T("url-decode"),
313     _T("url-encode"),
314     _T("utime"),
315     _T("verbose"),
316     _T("wait"),
317     _T("while"),
318     _T("writes"),
319   };
320
321 static bool
322 IsSiodKeyword (LPCTSTR pszChars, int nLength)
323 {
324   return ISXKEYWORDI (s_apszSiodKeywordList, pszChars, nLength);
325 }
326
327 static bool
328 IsUser1Keyword (LPCTSTR pszChars, int nLength)
329 {
330   return ISXKEYWORDI (s_apszUser1KeywordList, pszChars, nLength);
331 }
332
333 static bool
334 IsUser2Keyword (LPCTSTR pszChars, int nLength)
335 {
336   return ISXKEYWORDI (s_apszUser2KeywordList, pszChars, nLength);
337 }
338
339 DWORD
340 CrystalLineParser::ParseLineSiod (DWORD dwCookie, const TCHAR *pszChars, int nLength, TEXTBLOCK * pBuf, int &nActualItems)
341 {
342   if (nLength == 0)
343     return dwCookie & COOKIE_EXT_COMMENT;
344
345   bool bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
346   bool bRedefineBlock = true;
347   bool bWasCommentStart = false;
348   bool bDecIndex = false;
349   int nIdentBegin = -1;
350   bool bDefun = false;
351
352   int nPrevI = -1;
353   int I=0;
354   for (I = 0;; nPrevI = I, I = static_cast<int>(::CharNext(pszChars+I) - pszChars))
355     {
356       if (I == nPrevI)
357         {
358           // CharNext did not advance, so we're at the end of the string
359           // and we already handled this character, so stop
360           break;
361         }
362
363       if (bRedefineBlock)
364         {
365           int nPos = I;
366           if (bDecIndex)
367             nPos = nPrevI;
368           if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
369             {
370               DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
371             }
372           else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
373             {
374               DEFINE_BLOCK (nPos, COLORINDEX_STRING);
375             }
376           else
377             {
378               if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
379                 {
380                   DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
381                 }
382               else
383                 {
384                   DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
385                   bRedefineBlock = true;
386                   bDecIndex = true;
387                   goto out;
388                 }
389             }
390           bRedefineBlock = false;
391           bDecIndex = false;
392         }
393 out:
394
395       // Can be bigger than length if there is binary data
396       // See bug #1474782 Crash when comparing SQL with with binary data
397       if (I >= nLength || pszChars[I] == 0)
398         break;
399
400       if (dwCookie & COOKIE_COMMENT)
401         {
402           DEFINE_BLOCK (I, COLORINDEX_COMMENT);
403           dwCookie |= COOKIE_COMMENT;
404           break;
405         }
406
407       //  String constant "...."
408       if (dwCookie & COOKIE_STRING)
409         {
410           if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
411             {
412               dwCookie &= ~COOKIE_STRING;
413               bRedefineBlock = true;
414             }
415           continue;
416         }
417
418       //  Char constant '..'
419       if (dwCookie & COOKIE_CHAR)
420         {
421           if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
422             {
423               dwCookie &= ~COOKIE_CHAR;
424               bRedefineBlock = true;
425             }
426           continue;
427         }
428
429       //  Extended comment /*....*/
430       if (dwCookie & COOKIE_EXT_COMMENT)
431         {
432           // if (I > 0 && pszChars[I] == ';' && pszChars[nPrevI] == '|')
433           if ((I > 1 && pszChars[I] == ';' && pszChars[nPrevI] == '|' /*&& *::CharPrev(pszChars, pszChars + nPrevI) != ';'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == ';' && pszChars[nPrevI] == '|'))
434             {
435               dwCookie &= ~COOKIE_EXT_COMMENT;
436               bRedefineBlock = true;
437             }
438           bWasCommentStart = false;
439           continue;
440         }
441
442       if (I > 0 && pszChars[I] != '|' && pszChars[nPrevI] == ';')
443         {
444           DEFINE_BLOCK (I, COLORINDEX_COMMENT);
445           dwCookie |= COOKIE_COMMENT;
446           break;
447         }
448
449       //  Normal text
450       if (pszChars[I] == '"')
451         {
452           DEFINE_BLOCK (I, COLORINDEX_STRING);
453           dwCookie |= COOKIE_STRING;
454           continue;
455         }
456       if (pszChars[I] == '\'')
457         {
458           // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
459           if (!I || !xisalnum (pszChars[nPrevI]))
460             {
461               DEFINE_BLOCK (I, COLORINDEX_STRING);
462               dwCookie |= COOKIE_CHAR;
463               continue;
464             }
465         }
466       if (I > 0 && pszChars[I] == '|' && pszChars[nPrevI] == ';')
467         {
468           DEFINE_BLOCK (nPrevI, COLORINDEX_COMMENT);
469           dwCookie |= COOKIE_EXT_COMMENT;
470           bWasCommentStart = true;
471           continue;
472         }
473
474       bWasCommentStart = false;
475
476       if (bFirstChar)
477         {
478           if (!xisspace (pszChars[I]))
479             bFirstChar = false;
480         }
481
482       if (pBuf == nullptr)
483         continue;               //  We don't need to extract keywords,
484       //  for faster parsing skip the rest of loop
485
486       if (xisalnum (pszChars[I]) || pszChars[I] == '.')
487         {
488           if (nIdentBegin == -1)
489             nIdentBegin = I;
490         }
491       else
492         {
493           if (nIdentBegin >= 0)
494             {
495               if (IsSiodKeyword (pszChars + nIdentBegin, I - nIdentBegin))
496                 {
497                   if (!_tcsnicmp (_T ("defun"), pszChars + nIdentBegin, 5))
498                     {
499                       bDefun = true;
500                     }
501                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
502                 }
503               else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
504                 {
505                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
506                 }
507               else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
508                 {
509                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
510                 }
511               else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
512                 {
513                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
514                 }
515               else
516                 {
517                   bool bFunction = false;
518
519                   if (!bDefun)
520                     {
521                       for (int j = nIdentBegin; --j >= 0;)
522                         {
523                           if (!xisspace (pszChars[j]))
524                             {
525                               if (pszChars[j] == '(')
526                                 {
527                                   bFunction = true;
528                                 }
529                               break;
530                             }
531                         }
532                     }
533                   if (!bFunction)
534                     {
535                       for (int j = I; j >= 0; j--)
536                         {
537                           if (!xisspace (pszChars[j]))
538                             {
539                               if (pszChars[j] == '(')
540                                 {
541                                   bFunction = true;
542                                 }
543                               break;
544                             }
545                         }
546                     }
547                   if (bFunction)
548                     {
549                       DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
550                     }
551                 }
552               bRedefineBlock = true;
553               bDecIndex = true;
554               nIdentBegin = -1;
555             }
556         }
557     }
558
559   if (nIdentBegin >= 0)
560     {
561       if (IsSiodKeyword (pszChars + nIdentBegin, I - nIdentBegin))
562         {
563           if (!_tcsnicmp (_T ("defun"), pszChars + nIdentBegin, 5))
564             {
565               bDefun = true;
566             }
567           DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
568         }
569       else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
570         {
571           DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
572         }
573       else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
574         {
575           DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
576         }
577       else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
578         {
579           DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
580         }
581       else
582         {
583           bool bFunction = false;
584
585           if (!bDefun)
586             {
587               for (int j = nIdentBegin; --j >= 0;)
588                 {
589                   if (!xisspace (pszChars[j]))
590                     {
591                       if (pszChars[j] == '(')
592                         {
593                           bFunction = true;
594                         }
595                       break;
596                     }
597                 }
598             }
599           if (!bFunction)
600             {
601               for (int j = I; j >= 0; j--)
602                 {
603                   if (!xisspace (pszChars[j]))
604                     {
605                       if (pszChars[j] == '(')
606                         {
607                           bFunction = true;
608                         }
609                       break;
610                     }
611                 }
612             }
613           if (bFunction)
614             {
615               DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
616             }
617         }
618     }
619
620   dwCookie &= COOKIE_EXT_COMMENT;
621   return dwCookie;
622 }