OSDN Git Service

crystaledit: Make almost the same code into a common function
[winmerge-jp/winmerge-jp.git] / Externals / crystaledit / editlib / parsers / vhdl.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 //  File:       vhdl.cpp
3 //  Version:    1.0
4 //  Created:    8-Nov-2017
5 //
6 //  Copyright:  H.Saido, portions by Tim Gerundt, Stcherbatchenko Andrei
7 //  E-mail:     saido.nv@gmail.com
8 //
9 //  VHDL 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 //  VHDL keywords
27 static LPCTSTR s_apszVhdlKeywordList[] =
28   {
29     _T ("abs"),
30     _T ("access"),
31     _T ("after"),
32     _T ("alias"),
33     _T ("all"),
34     _T ("and"),
35     _T ("architecture"),
36     _T ("array"),
37     _T ("assert"),
38     _T ("attribute"),
39     _T ("begin"),
40     _T ("block"),
41     _T ("body"),
42     _T ("true"),
43     _T ("buffer"),
44     _T ("bus"),
45     _T ("case"),
46     _T ("component"),
47     _T ("configuration"),
48     _T ("constant"),
49     _T ("disconnect"),
50     _T ("downto"),
51     _T ("else"),
52     _T ("elsif"),
53     _T ("end"),
54     _T ("entity"),
55     _T ("exit"),
56     _T ("false"),
57     _T ("file"),
58     _T ("for"),
59     _T ("function"),
60     _T ("generate"),
61     _T ("generic"),
62     _T ("guarded"),
63     _T ("if"),
64     _T ("in"),
65     _T ("inout"),
66     _T ("is"),
67     _T ("label"),
68     _T ("library"),
69     _T ("linkage"),
70     _T ("loop"),
71     _T ("map"),
72     _T ("mod"),
73     _T ("nand"),
74     _T ("new"),
75     _T ("next"),
76     _T ("nor"),
77     _T ("not"),
78     _T ("null"),
79     _T ("of"),
80     _T ("on"),
81     _T ("open"),
82     _T ("or"),
83     _T ("others"),
84     _T ("out"),
85     _T ("pakage"),
86     _T ("port"),
87     _T ("procedure"),
88     _T ("process"),
89     _T ("range"),
90     _T ("record"),
91     _T ("register"),
92     _T ("rem"),
93     _T ("report"),
94     _T ("return"),
95     _T ("select"),
96     _T ("severity"),
97     _T ("signal"),
98     _T ("subtype"),
99     _T ("then"),
100     _T ("to"),
101     _T ("transport"),
102     _T ("true"),
103     _T ("type"),
104     _T ("units"),
105     _T ("until"),
106     _T ("use"),
107     _T ("variable"),
108     _T ("wait"),
109     _T ("when"),
110     _T ("while"),
111     _T ("with"),
112     _T ("xor")
113   };
114
115 static LPCTSTR s_apszVhdlAttributeList[] =
116   {
117     _T ("'active"),
118     _T ("'ascending"),
119     _T ("'base"),
120     _T ("'delayed"),
121     _T ("'driving"),
122     _T ("'driving_value"),
123     _T ("'event"),
124     _T ("'high"),
125     _T ("'image"),
126     _T ("'instance_name"),
127     _T ("'last_active"),
128     _T ("'last_event"),
129     _T ("'last_value"),
130     _T ("'left"),
131     _T ("'leftof"),
132     _T ("'length"),
133     _T ("'low"),
134     _T ("'path_name"),
135     _T ("'pos"),
136     _T ("'pred"),
137     _T ("'quiet"),
138     _T ("'range"),
139     _T ("'reverse_range"),
140     _T ("'right"),
141     _T ("'rightof"),
142     _T ("'simple_name"),
143     _T ("'stable"),
144     _T ("'succ"),
145     _T ("'transaction"),
146     _T ("'val"),
147     _T ("'value")
148   };
149
150 //  VHDL Types
151 static LPCTSTR s_apszVhdlTypeList[] =
152   {
153     _T ("bit"),
154     _T ("bit_vector"),
155     _T ("boolean"),
156     _T ("character"),
157     _T ("fs"),
158     _T ("hr"),
159     _T ("integer"),
160     _T ("line"),
161     _T ("min"),
162     _T ("ms"),
163     _T ("natural"),
164     _T ("now"),
165     _T ("ns"),
166     _T ("positive"),
167     _T ("ps"),
168     _T ("real"),
169     _T ("sec"),
170     _T ("side"),
171     _T ("signed"),
172     _T ("std_logic"),
173     _T ("std_logic_vector"),
174     _T ("std_ulogic"),
175     _T ("std_ulogic_vector"),
176     _T ("string"),
177     _T ("text"),
178     _T ("time"),
179     _T ("unsigned"),
180     _T ("us"),
181     _T ("width")
182   };
183
184 //  VHDL functions
185 static LPCTSTR s_apszVhdlFunctionList[] =
186   {
187     _T ("conv_integer"),
188     _T ("conv_signed"),
189     _T ("conv_std_logic_vector"),
190     _T ("conv_unsigned"),
191     _T ("falling_edge"),
192     _T ("hread"),
193     _T ("hwrite"),
194     _T ("oread"),
195     _T ("owrite"),
196     _T ("read"),
197     _T ("readline"),
198     _T ("rising_edge"),
199     _T ("to_bit"),
200     _T ("to_bitvector"),
201     _T ("to_signed"),
202     _T ("to_stdlogicvector"),
203     _T ("to_stdulogic"),
204     _T ("to_stdulogicvector"),
205     _T ("to_unsigned"),
206     _T ("write"),
207     _T ("writeline"),
208   };
209
210 static bool
211 IsVhdlKeyword (LPCTSTR pszChars, int nLength)
212 {
213   return ISXKEYWORDI(s_apszVhdlKeywordList, pszChars, nLength);
214 }
215
216 static bool
217 IsVhdlAttribute (LPCTSTR pszChars, int nLength, int *nAttributeBegin)
218 {
219   for (int I = 0; I < nLength; I++)
220     {
221       if (pszChars[I] == '\'')
222         {
223           *nAttributeBegin = I;
224           return ISXKEYWORDI(s_apszVhdlAttributeList, &pszChars[I], nLength-I);
225         }
226    }
227   return false;
228 }
229
230 static bool
231 IsVhdlType (LPCTSTR pszChars, int nLength)
232 {
233   return ISXKEYWORDI(s_apszVhdlTypeList, pszChars, nLength);
234 }
235
236 static bool
237 IsVhdlFunction (LPCTSTR pszChars, int nLength)
238 {
239   return ISXKEYWORDI(s_apszVhdlFunctionList, pszChars, nLength);
240 }
241
242 static bool
243 IsVhdlNumber (LPCTSTR pszChars, int nLength)
244 {
245   if (nLength == 3 && pszChars[0] == '\'' && pszChars[2] == '\'')
246     {
247       if (pszChars[1] == '0' ||
248           pszChars[1] == '1' ||
249           pszChars[1] == 'u' ||
250           pszChars[1] == 'U' ||
251           pszChars[1] == 'x' ||
252           pszChars[1] == 'X' ||
253           pszChars[1] == 'w' ||
254           pszChars[1] == 'W' ||
255           pszChars[1] == 'l' ||
256           pszChars[1] == 'L' ||
257           pszChars[1] == 'h' ||
258           pszChars[1] == 'H' ||
259           pszChars[1] == 'z' ||
260           pszChars[1] == 'Z' ||
261           pszChars[1] == '-' ||
262           pszChars[1] == '_' )
263         return true;
264     }
265   if (nLength > 4 && pszChars[1] == '"' && pszChars[nLength-1] == '"')
266     {
267       if (pszChars[0] == 'x' ||
268           pszChars[0] == 'X' ||
269           pszChars[0] == 'b' ||
270           pszChars[0] == 'B' ||
271           pszChars[0] == 'o' ||
272           pszChars[0] == 'O' )
273       {
274         for (int I = 2; I < nLength-1; I++)
275           {
276             if (_istdigit (pszChars[I]) ||
277                   (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
278                   (pszChars[I] >= 'a' && pszChars[I] <= 'f') ||
279                   pszChars[I] == 'u' || pszChars[I] == 'U' ||
280                   pszChars[I] == 'x' || pszChars[I] == 'X' ||
281                   pszChars[I] == 'w' || pszChars[I] == 'W' ||
282                   pszChars[I] == 'l' || pszChars[I] == 'L' ||
283                   pszChars[I] == 'h' || pszChars[I] == 'H' ||
284                   pszChars[I] == 'z' || pszChars[I] == 'Z' ||
285                   // FIXME: Could not display "----", yet.
286                   /* pszChars[I] == '-' || */ pszChars[I] == '_' )
287               continue;
288             return false;
289           }
290         return true;
291       }
292     }
293   if (nLength > 3 && pszChars[0] == '"' && pszChars[nLength-1] == '"')
294     {
295       for (int I = 1; I < nLength-1; I++)
296         {
297           if (_istdigit (pszChars[I]) ||
298                 (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
299                 (pszChars[I] >= 'a' && pszChars[I] <= 'f') ||
300                 pszChars[I] == 'u' || pszChars[I] == 'U' ||
301                 pszChars[I] == 'x' || pszChars[I] == 'X' ||
302                 pszChars[I] == 'w' || pszChars[I] == 'W' ||
303                 pszChars[I] == 'l' || pszChars[I] == 'L' ||
304                 pszChars[I] == 'h' || pszChars[I] == 'H' ||
305                 pszChars[I] == 'z' || pszChars[I] == 'Z' ||
306                 // FIXME: Could not display "----", yet.
307                 /* pszChars[I] == '-' || */ pszChars[I] == '_' )
308             continue;
309           return false;
310         }
311       return true;
312     }
313   for (int I = 0; I < nLength; I++)
314     {
315       if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
316             pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
317             pszChars[I] != 'E' && pszChars[I] != '_')
318         return false;
319     }
320   return true;
321 }
322
323 static bool
324 IsVhdlString (LPCTSTR pszChars, int nLength)
325 {
326   if (nLength > 3 && pszChars[0] == '"' && pszChars[nLength-1] == '"')
327     return true;
328   return false;
329 }
330
331 static bool
332 IsVhdlChar (LPCTSTR pszChars, int nLength)
333 {
334   if (nLength == 3 && pszChars[0] == '\'' && pszChars[2] == '\'')
335     return true;
336   return false;
337 }
338
339 DWORD
340 CrystalLineParser::ParseLineVhdl (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 bRedefineBlock = true;
346   bool bDecIndex = false;
347   bool bNum = false;
348   int nIdentBegin = -1;
349   int nAttributeBegin = 0;
350   int nPrevI = -1;
351   int I=0;
352   for (I = 0;; nPrevI = I, I = static_cast<int>(::CharNext(pszChars+I) - pszChars))
353     {
354       if (I == nPrevI)
355         {
356           // CharNext did not advance, so we're at the end of the string
357           // and we already handled this character, so stop
358           break;
359         }
360
361       if (bRedefineBlock)
362         {
363           int nPos = I;
364           if (bDecIndex)
365             nPos = nPrevI;
366           if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
367             {
368               DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
369             }
370           else if (dwCookie & (COOKIE_STRING))
371             {
372               DEFINE_BLOCK (nPos, COLORINDEX_STRING);
373             }
374           else if (dwCookie & COOKIE_PREPROCESSOR)
375             {
376               DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
377             }
378           else
379             {
380               if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (*::CharPrev(pszChars, pszChars + nPos)) && !xisalpha (*::CharNext(pszChars + nPos))))
381                 {
382                   DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
383                 }
384               else if (pszChars[nPos] == '"' || pszChars[nPos] == '\'')
385                 {
386                   DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
387                 }
388               else
389                 {
390                   DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
391                   bRedefineBlock = true;
392                   bDecIndex = true;
393                   goto out;
394                 }
395             }
396           bRedefineBlock = false;
397           bDecIndex = false;
398         }
399 out:
400
401       // Can be bigger than length if there is binary data
402       // See bug #1474782 Crash when comparing SQL with with binary data
403       if (I >= nLength)
404         break;
405
406       if (dwCookie & COOKIE_COMMENT)
407         {
408           DEFINE_BLOCK (I, COLORINDEX_COMMENT);
409           dwCookie |= COOKIE_COMMENT;
410           break;
411         }
412
413       // Line comment --...
414       if (I > 0 && pszChars[I] == '-' && pszChars[nPrevI] == '-')
415         {
416           DEFINE_BLOCK (nPrevI, COLORINDEX_COMMENT);
417           dwCookie |= COOKIE_COMMENT;
418           break;
419         }
420
421       //  String constant "...."
422       if (dwCookie & COOKIE_STRING)
423         {
424           if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
425             {
426               dwCookie &= ~COOKIE_STRING;
427               bRedefineBlock = true;
428             }
429           continue;
430         }
431
432       // //  Normal text
433       // if (pszChars[I] == '"')
434       //   {
435       //     DEFINE_BLOCK (I, COLORINDEX_STRING);
436       //     dwCookie |= COOKIE_STRING;
437       //     continue;
438       //   }
439
440       if (pBuf == nullptr)
441         continue;               //  We don't need to extract keywords,
442       //  for faster parsing skip the rest of loop
443
444       if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[nPrevI]) && !xisalpha (pszChars[I + 1])))
445         {
446           if (nIdentBegin == -1)
447             nIdentBegin = I;
448         }
449       else if (pszChars[I] == '"' || pszChars[I] == '\'')
450         {
451           if (nIdentBegin == -1)
452             nIdentBegin = I;
453         }
454       else
455         {
456           if (nIdentBegin >= 0)
457             {
458               if (IsVhdlNumber (pszChars + nIdentBegin, I - nIdentBegin))
459                 {
460                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
461                 }
462               else if (pszChars[nIdentBegin] == '"')
463                 {
464                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_STRING);
465                   dwCookie |= COOKIE_STRING;
466                   continue;
467                 }
468               else if (IsVhdlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
469                 {
470                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
471                 }
472               else if (IsVhdlAttribute (pszChars + nIdentBegin, I - nIdentBegin, &nAttributeBegin))
473                 {
474                   DEFINE_BLOCK (nIdentBegin + nAttributeBegin, COLORINDEX_FUNCNAME);
475                 }
476               else if (IsVhdlType (pszChars + nIdentBegin, I - nIdentBegin))
477                 {
478                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_PREPROCESSOR);
479                 }
480               else if (IsVhdlFunction (pszChars + nIdentBegin, I - nIdentBegin))
481                 {
482                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
483                 }
484               else if (IsVhdlChar (pszChars + nIdentBegin, I - nIdentBegin))
485                 {
486                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_STRING);
487                 }
488               bRedefineBlock = true;
489               bDecIndex = true;
490               nIdentBegin = -1;
491             }
492         }
493     }
494
495   if (nIdentBegin >= 0)
496     {
497       if (IsVhdlNumber (pszChars + nIdentBegin, I - nIdentBegin))
498         {
499           DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
500         }
501       else if (pszChars[nIdentBegin] == '"')
502         {
503           DEFINE_BLOCK (nIdentBegin, COLORINDEX_STRING);
504           dwCookie |= COOKIE_STRING;
505         }
506       else if (IsVhdlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
507         {
508           DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
509         }
510       else if (IsVhdlAttribute (pszChars + nIdentBegin, I - nIdentBegin, &nAttributeBegin))
511         {
512           DEFINE_BLOCK (nIdentBegin + nAttributeBegin, COLORINDEX_FUNCNAME);
513         }
514       else if (IsVhdlType (pszChars + nIdentBegin, I - nIdentBegin))
515         {
516           DEFINE_BLOCK (nIdentBegin, COLORINDEX_PREPROCESSOR);
517         }
518       else if (IsVhdlFunction (pszChars + nIdentBegin, I - nIdentBegin))
519         {
520           DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
521         }
522       else if (IsVhdlChar (pszChars + nIdentBegin, I - nIdentBegin))
523         {
524           DEFINE_BLOCK (nIdentBegin, COLORINDEX_STRING);
525         }
526     }
527
528   dwCookie &= COOKIE_EXT_COMMENT;
529   return dwCookie;
530 }