OSDN Git Service

crystaledit: Organize the directory structure
[winmerge-jp/winmerge-jp.git] / Externals / crystaledit / editlib / parsers / asp.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 //  File:    asp.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 //  ASP 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 "../utils/string_util.h"
21
22 #ifdef _DEBUG
23 #define new DEBUG_NEW
24 #endif
25
26 static LPCTSTR s_apszAspKeywordList[] =
27   {
28     _T ("Abs"),
29     _T ("AppActivate"),
30     _T ("As"),
31     _T ("Asc"),
32     _T ("Atn"),
33     _T ("Base"),
34     _T ("Beep"),
35     _T ("CDbl"),
36     _T ("CInt"),
37     _T ("CLng"),
38     _T ("CSng"),
39     _T ("CStr"),
40     _T ("CVar"),
41     _T ("Call"),
42     _T ("ChDir"),
43     _T ("ChDrive"),
44     _T ("CheckBox"),
45     _T ("Chr"),
46     _T ("Close"),
47     _T ("Const"),
48     _T ("Cos"),
49     _T ("CreateObject"),
50     _T ("CreateVerifyItem"),
51     _T ("CurDir"),
52     _T ("Date"),
53     _T ("Declare"),
54     _T ("Dialog"),
55     _T ("Dim"),
56     _T ("Dir"),
57     _T ("DlgEnable"),
58     _T ("DlgText"),
59     _T ("DlgVisible"),
60     _T ("Do"),
61     _T ("Double"),
62     _T ("EOF"),
63     _T ("Else"),
64     _T ("Else"),
65     _T ("End"),
66     _T ("End"),
67     _T ("Erase"),
68     _T ("Error"),
69     _T ("Exit"),
70     _T ("Exp"),
71     _T ("FileCopy"),
72     _T ("FileLen"),
73     _T ("Fix"),
74     _T ("For"),
75     _T ("For"),
76     _T ("Format"),
77     _T ("Function"),
78     _T ("Function"),
79     _T ("GetAttrName"),
80     _T ("GetAttrType"),
81     _T ("GetAttrValBool"),
82     _T ("GetAttrValEnumInt"),
83     _T ("GetAttrValEnumString"),
84     _T ("GetAttrValFloat"),
85     _T ("GetAttrValInt"),
86     _T ("GetAttrValString"),
87     _T ("GetClassId"),
88     _T ("GetGeoType"),
89     _T ("GetObject"),
90     _T ("Global"),
91     _T ("GoSub"),
92     _T ("GoTo"),
93     _T ("Hex"),
94     _T ("Hour"),
95     _T ("If"),
96     _T ("If"),
97     _T ("InStr"),
98     _T ("Input"),
99     _T ("Input#"),
100     _T ("InputBox"),
101     _T ("Int"),
102     _T ("IsDate"),
103     _T ("IsEmpty"),
104     _T ("IsNull"),
105     _T ("IsNumeric"),
106     _T ("Kill"),
107     _T ("LBound"),
108     _T ("LCase"),
109     _T ("LCase$"),
110     _T ("LTrim"),
111     _T ("Left"),
112     _T ("Left$"),
113     _T ("Len"),
114     _T ("Let"),
115     _T ("Line"),
116     _T ("Log"),
117     _T ("Long"),
118     _T ("Loop"),
119     _T ("Mid"),
120     _T ("Minute"),
121     _T ("MkDir"),
122     _T ("Month"),
123     _T ("MsgBox"),
124     _T ("Name"),
125     _T ("Next"),
126     _T ("Next"),
127     _T ("Now"),
128     _T ("Oct"),
129     _T ("On"),
130     _T ("Open"),
131     _T ("Option"),
132     _T ("Print"),
133     _T ("Print"),
134     _T ("RTrim"),
135     _T ("Rem"),
136     _T ("Return"),
137     _T ("Right"),
138     _T ("RmDir"),
139     _T ("Rnd"),
140     _T ("SMDoMenu"),
141     _T ("Second"),
142     _T ("Seek"),
143     _T ("Seek"),
144     _T ("Select Case"),
145     _T ("SendKeys"),
146     _T ("Set"),
147     _T ("SetAttrValBool"),
148     _T ("SetAttrValEnumInt"),
149     _T ("SetAttrValEnumString"),
150     _T ("SetAttrValFloat"),
151     _T ("SetAttrValInt"),
152     _T ("SetAttrValString"),
153     _T ("Shell"),
154     _T ("Sin"),
155     _T ("Space"),
156     _T ("Sqr"),
157     _T ("Static"),
158     _T ("Step"),
159     _T ("Stop"),
160     _T ("Str"),
161     _T ("StrComp"),
162     _T ("String"),
163     _T ("StringFunction"),
164     _T ("Sub"),
165     _T ("Tan"),
166     _T ("Text"),
167     _T ("TextBox"),
168     _T ("Then"),
169     _T ("Time"),
170     _T ("TimeSerial"),
171     _T ("TimeValue"),
172     _T ("To"),
173     _T ("Trim"),
174     _T ("Type"),
175     _T ("UBound"),
176     _T ("UCase"),
177     _T ("Val"),
178     _T ("VarType"),
179     _T ("VerifyCardinalities"),
180     _T ("Wend"),
181     _T ("Wend"),
182     _T ("While"),
183     _T ("While"),
184     _T ("With"),
185     _T ("Write"),
186     _T ("Year"),
187   };
188
189 static bool
190 IsAspKeyword (LPCTSTR pszChars, int nLength)
191 {
192   return ISXKEYWORDI (s_apszAspKeywordList, pszChars, nLength);
193 }
194
195 DWORD
196 CrystalLineParser::ParseLineAsp (DWORD dwCookie, const TCHAR *pszChars, int nLength, TEXTBLOCK * pBuf, int &nActualItems)
197 {
198   if (nLength == 0)
199     return dwCookie & (COOKIE_EXT_COMMENT|COOKIE_EXT_USER1);
200
201   bool bFirstChar = (dwCookie & ~(COOKIE_EXT_COMMENT|COOKIE_EXT_USER1)) == 0;
202   bool bRedefineBlock = true;
203   bool bDecIndex = false;
204   int nIdentBegin = -1;
205   int nPrevI = -1;
206   int I=0;
207   for (I = 0;; nPrevI = I, I = static_cast<int>(::CharNext(pszChars+I) - pszChars))
208     {
209       if (I == nPrevI)
210         {
211           // CharNext did not advance, so we're at the end of the string
212           // and we already handled this character, so stop
213           break;
214         }
215
216       if (bRedefineBlock)
217         {
218           int nPos = I;
219           if (bDecIndex)
220             nPos = nPrevI;
221           if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
222             {
223               DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
224             }
225           else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
226             {
227               DEFINE_BLOCK (nPos, COLORINDEX_STRING);
228             }
229           else if (dwCookie & COOKIE_PREPROCESSOR)
230             {
231               DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
232             }
233           else if (dwCookie & COOKIE_EXT_USER1)
234             {
235               DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
236             }
237           else
238             {
239               if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
240                 {
241                   DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
242                 }
243               else
244                 {
245                   DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
246                   bRedefineBlock = true;
247                   bDecIndex = true;
248                   goto out;
249                 }
250             }
251           bRedefineBlock = false;
252           bDecIndex = false;
253         }
254 out:
255
256       // Can be bigger than length if there is binary data
257       // See bug #1474782 Crash when comparing SQL with with binary data
258       if (I >= nLength || pszChars[I] == 0)
259         break;
260
261       if (dwCookie & COOKIE_COMMENT)
262         {
263           DEFINE_BLOCK (I, COLORINDEX_COMMENT);
264           dwCookie |= COOKIE_COMMENT;
265           break;
266         }
267
268       //  String constant "...."
269       if (dwCookie & COOKIE_STRING)
270         {
271           if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
272             {
273               dwCookie &= ~COOKIE_STRING;
274               bRedefineBlock = true;
275             }
276           continue;
277         }
278
279       //  Char constant '..'
280       if (dwCookie & COOKIE_CHAR)
281         {
282           if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
283             {
284               dwCookie &= ~COOKIE_CHAR;
285               bRedefineBlock = true;
286             }
287           continue;
288         }
289
290       //  Extended comment <!--....-->
291       if (dwCookie & COOKIE_EXT_COMMENT)
292         {
293           if (!(dwCookie & COOKIE_EXT_USER1))
294             {
295               if (I > 1 && pszChars[I] == '>' && pszChars[nPrevI] == '-' && *::CharPrev(pszChars, pszChars + nPrevI) == '-')
296                 {
297                   dwCookie &= ~COOKIE_EXT_COMMENT;
298                   bRedefineBlock = true;
299                 }
300             }
301           continue;
302         }
303
304       if ((dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '\'')
305         {
306           DEFINE_BLOCK (I, COLORINDEX_COMMENT);
307           dwCookie |= COOKIE_COMMENT;
308           break;
309         }
310
311       //  Extended comment <?....?>
312       if (dwCookie & COOKIE_EXT_USER1)
313         {
314           if (I > 0 && pszChars[I] == '>' && (pszChars[nPrevI] == '?' || pszChars[nPrevI] == '%'))
315             {
316               dwCookie &= ~COOKIE_EXT_USER1;
317               bRedefineBlock = true;
318               continue;
319             }
320         }
321
322       //  Normal text
323       if ((dwCookie & (COOKIE_PREPROCESSOR|COOKIE_EXT_USER1)) && pszChars[I] == '"')
324         {
325           DEFINE_BLOCK (I, COLORINDEX_STRING);
326           dwCookie |= COOKIE_STRING;
327           continue;
328         }
329
330       if ((dwCookie & (COOKIE_PREPROCESSOR|COOKIE_EXT_USER1)) && pszChars[I] == '\'')
331         {
332           // 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] == '\'')
333           if (!I || !xisalnum (pszChars[nPrevI]))
334             {
335               DEFINE_BLOCK (I, COLORINDEX_STRING);
336               dwCookie |= COOKIE_CHAR;
337               continue;
338             }
339         }
340
341       if (!(dwCookie & COOKIE_EXT_USER1))
342         {
343           if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength - 3 && pszChars[I] == '<' && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')
344             {
345               DEFINE_BLOCK (I, COLORINDEX_COMMENT);
346               I += 3;
347               dwCookie |= COOKIE_EXT_COMMENT;
348               dwCookie &= ~COOKIE_PREPROCESSOR;
349               continue;
350             }
351         }
352
353       if (bFirstChar)
354         {
355           if (!xisspace (pszChars[I]))
356             bFirstChar = false;
357         }
358
359       //  User1 start: <?
360       if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
361         {
362           DEFINE_BLOCK (I, COLORINDEX_NORMALTEXT);
363           dwCookie |= COOKIE_EXT_USER1;
364           nIdentBegin = -1;
365           continue;
366         }
367
368       if (pBuf == nullptr)
369         continue;               //  We don't need to extract keywords,
370       //  for faster parsing skip the rest of loop
371
372       if (xisalnum (pszChars[I]) || pszChars[I] == '.')
373         {
374           if (nIdentBegin == -1)
375             nIdentBegin = I;
376         }
377       else
378         {
379           if (nIdentBegin >= 0)
380             {
381               if (dwCookie & COOKIE_PREPROCESSOR)
382                 {
383                   if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
384                     {
385                       DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
386                     }
387                   else if (IsHtmlUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
388                     {
389                       DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
390                     }
391                   else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
392                     {
393                       DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
394                     }
395                   else
396                     {
397                       goto next;
398                     }
399                 }
400               else if (dwCookie & COOKIE_EXT_USER1)
401                 {
402                   if (IsAspKeyword (pszChars + nIdentBegin, I - nIdentBegin))
403                     {
404                       DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
405                     }
406                   else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
407                     {
408                       DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
409                     }
410                   else
411                     {
412                       bool bFunction = false;
413
414                       for (int j = I; j < nLength; j++)
415                         {
416                           if (!xisspace (pszChars[j]))
417                             {
418                               if (pszChars[j] == '(')
419                                 {
420                                   bFunction = true;
421                                 }
422                               break;
423                             }
424                         }
425                       if (bFunction)
426                         {
427                           DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
428                         }
429                       else
430                         {
431                           goto next;
432                         }
433                     }
434                 }
435               else if (dwCookie & COOKIE_USER1)
436                 {
437                   if (IsHtmlUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
438                     {
439                       DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
440                     }
441                   else
442                     {
443                       goto next;
444                     }
445                 }
446               bRedefineBlock = true;
447               bDecIndex = true;
448               nIdentBegin = -1;
449 next:
450               ;
451             }
452
453           //  Preprocessor start: < or bracket
454           if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-'))
455             {
456               DEFINE_BLOCK (I, COLORINDEX_OPERATOR);
457               DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
458               dwCookie |= COOKIE_PREPROCESSOR;
459               nIdentBegin = -1;
460               continue;
461             }
462
463           //  User1 end: ?>
464           if (dwCookie & COOKIE_EXT_USER1)
465             {
466               if (I > 0 && pszChars[I] == '>' && (pszChars[nPrevI] == '?' || pszChars[nPrevI] == '%'))
467                 {
468                   dwCookie &= ~COOKIE_EXT_USER1;
469                   nIdentBegin = -1;
470                   bRedefineBlock = true;
471                   bDecIndex = true;
472                   continue;
473                 }
474             }
475
476           //  Preprocessor end: > or bracket
477           if (dwCookie & COOKIE_PREPROCESSOR)
478             {
479               if (pszChars[I] == '>')
480                 {
481                   dwCookie &= ~COOKIE_PREPROCESSOR;
482                   nIdentBegin = -1;
483                   bRedefineBlock = true;
484                   bDecIndex = true;
485                   continue;
486                 }
487             }
488
489           //  Preprocessor start: &
490           if (!(dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '&')
491             {
492               dwCookie |= COOKIE_USER1;
493               nIdentBegin = -1;
494               continue;
495             }
496
497           //  Preprocessor end: ;
498           if (dwCookie & COOKIE_USER1)
499             {
500               if (pszChars[I] == ';')
501                 {
502                   dwCookie &= ~COOKIE_USER1;
503                   nIdentBegin = -1;
504                   continue;
505                 }
506             }
507
508         }
509     }
510
511   if (nIdentBegin >= 0 && (dwCookie & COOKIE_PREPROCESSOR))
512     {
513       if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
514         {
515           DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
516         }
517       else if (IsHtmlUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
518         {
519           DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
520         }
521       else if (IsHtmlUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
522         {
523           DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
524         }
525       else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
526         {
527           DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
528         }
529       else
530         {
531           bool bFunction = false;
532
533           for (int j = I; j < nLength; j++)
534             {
535               if (!xisspace (pszChars[j]))
536                 {
537                   if (pszChars[j] == '(')
538                     {
539                       bFunction = true;
540                     }
541                   break;
542                 }
543             }
544           if (bFunction)
545             {
546               DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
547             }
548         }
549     }
550   else if (nIdentBegin >= 0 && (dwCookie & COOKIE_EXT_USER1))
551     {
552       if (IsAspKeyword (pszChars + nIdentBegin, I - nIdentBegin))
553         {
554           DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
555         }
556       else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
557         {
558           DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
559         }
560       else
561         {
562           bool bFunction = false;
563
564           for (int j = I; j < nLength; j++)
565             {
566               if (!xisspace (pszChars[j]))
567                 {
568                   if (pszChars[j] == '(')
569                     {
570                       bFunction = true;
571                     }
572                   break;
573                 }
574             }
575           if (bFunction)
576             {
577               DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
578             }
579         }
580     }
581
582   dwCookie &= (COOKIE_EXT_COMMENT | COOKIE_STRING | COOKIE_PREPROCESSOR | COOKIE_EXT_USER1);
583   return dwCookie;
584 }