Merge pull request #11 from esorton/bugfix/add-constexpr-keyword-to-arduino-ctags
[arduino-ctags.git] / vhdl.c
blob994d2e1424fc13df555ca5159daa5ab4806e0c9e
1 /*
2 * $Id: vhdl.c 652 2008-04-18 03:51:47Z elliotth $
3 *
4 * Copyright (c) 2008, Nicolas Vincent
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * This module contains functions for generating tags for VHDL files.
13 * INCLUDE FILES
15 #include "general.h" /* must always come first */
17 #include <ctype.h> /* to define isalpha () */
18 #include <string.h>
19 #include <setjmp.h>
21 #include "debug.h"
22 #include "entry.h"
23 #include "keyword.h"
24 #include "parse.h"
25 #include "read.h"
26 #include "routines.h"
27 #include "vstring.h"
30 * MACROS
32 #define isType(token,t) (boolean) ((token)->type == (t))
33 #define isKeyword(token,k) (boolean) ((token)->keyword == (k))
36 * DATA DECLARATIONS
38 typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
41 * Used to specify type of keyword.
43 typedef enum eKeywordId {
44 KEYWORD_NONE = -1,
45 KEYWORD_ABS,
46 KEYWORD_ACCESS,
47 KEYWORD_AFTER,
48 KEYWORD_ALIAS,
49 KEYWORD_ALL,
50 KEYWORD_AND,
51 KEYWORD_ARCHITECTURE,
52 KEYWORD_ARRAY,
53 KEYWORD_ASSERT,
54 KEYWORD_ATTRIBUTE,
55 KEYWORD_BEGIN,
56 KEYWORD_BLOCK,
57 KEYWORD_BODY,
58 KEYWORD_BUFFER,
59 KEYWORD_BUS,
60 KEYWORD_CASE,
61 KEYWORD_COMPONENT,
62 KEYWORD_CONFIGURATION,
63 KEYWORD_CONSTANT,
64 KEYWORD_DISCONNECT,
65 KEYWORD_DOWNTO,
66 KEYWORD_ELSE,
67 KEYWORD_ELSIF,
68 KEYWORD_END,
69 KEYWORD_ENTITY,
70 KEYWORD_EXIT,
71 KEYWORD_FILE,
72 KEYWORD_FOR,
73 KEYWORD_FUNCTION,
74 KEYWORD_GENERATE,
75 KEYWORD_GENERIC,
76 KEYWORD_GROUP,
77 KEYWORD_GUARDED,
78 KEYWORD_IF,
79 KEYWORD_IMPURE,
80 KEYWORD_IN,
81 KEYWORD_INERTIAL,
82 KEYWORD_INOUT,
83 KEYWORD_IS,
84 KEYWORD_LABEL,
85 KEYWORD_LIBRARY,
86 KEYWORD_LINKAGE,
87 KEYWORD_LITERAL,
88 KEYWORD_LOOP,
89 KEYWORD_MAP,
90 KEYWORD_MOD,
91 KEYWORD_NAND,
92 KEYWORD_NEW,
93 KEYWORD_NEXT,
94 KEYWORD_NOR,
95 KEYWORD_NOT,
96 KEYWORD_NULL,
97 KEYWORD_OF,
98 KEYWORD_ON,
99 KEYWORD_OPEN,
100 KEYWORD_OR,
101 KEYWORD_OTHERS,
102 KEYWORD_OUT,
103 KEYWORD_PACKAGE,
104 KEYWORD_PORT,
105 KEYWORD_POSTPONED,
106 KEYWORD_PROCEDURE,
107 KEYWORD_PROCESS,
108 KEYWORD_PURE,
109 KEYWORD_RANGE,
110 KEYWORD_RECORD,
111 KEYWORD_REGISTER,
112 KEYWORD_REJECT,
113 KEYWORD_RETURN,
114 KEYWORD_ROL,
115 KEYWORD_ROR,
116 KEYWORD_SELECT,
117 KEYWORD_SEVERITY,
118 KEYWORD_SIGNAL,
119 KEYWORD_SHARED,
120 KEYWORD_SLA,
121 KEYWORD_SLI,
122 KEYWORD_SRA,
123 KEYWORD_SRL,
124 KEYWORD_SUBTYPE,
125 KEYWORD_THEN,
126 KEYWORD_TO,
127 KEYWORD_TRANSPORT,
128 KEYWORD_TYPE,
129 KEYWORD_UNAFFECTED,
130 KEYWORD_UNITS,
131 KEYWORD_UNTIL,
132 KEYWORD_USE,
133 KEYWORD_VARIABLE,
134 KEYWORD_WAIT,
135 KEYWORD_WHEN,
136 KEYWORD_WHILE,
137 KEYWORD_WITH,
138 KEYWORD_XNOR,
139 KEYWORD_XOR
140 } keywordId;
142 /* Used to determine whether keyword is valid for the current language and
143 * what its ID is.
145 typedef struct sKeywordDesc {
146 const char *name;
147 keywordId id;
148 } keywordDesc;
150 typedef enum eTokenType {
151 TOKEN_NONE, /* none */
152 TOKEN_OPEN_PAREN, /* ( */
153 TOKEN_CLOSE_PAREN, /* ) */
154 TOKEN_COMMA, /* the comma character */
155 TOKEN_IDENTIFIER,
156 TOKEN_KEYWORD,
157 TOKEN_PERIOD, /* . */
158 TOKEN_OPERATOR,
159 TOKEN_SEMICOLON, /* the semicolon character */
160 TOKEN_STRING
161 } tokenType;
163 typedef struct sTokenInfo {
164 tokenType type;
165 keywordId keyword;
166 vString *string; /* the name of the token */
167 vString *scope;
168 unsigned long lineNumber; /* line number of tag */
169 fpos_t filePosition; /* file position of line containing name */
170 } tokenInfo;
173 * DATA DEFINITIONS
175 static int Lang_vhdl;
176 static jmp_buf Exception;
178 /* Used to index into the VhdlKinds table. */
179 typedef enum {
180 VHDLTAG_UNDEFINED = -1,
181 VHDLTAG_CONSTANT,
182 VHDLTAG_TYPE,
183 VHDLTAG_SUBTYPE,
184 VHDLTAG_RECORD,
185 VHDLTAG_ENTITY,
186 VHDLTAG_COMPONENT,
187 VHDLTAG_PROTOTYPE,
188 VHDLTAG_FUNCTION,
189 VHDLTAG_PROCEDURE,
190 VHDLTAG_PACKAGE,
191 VHDLTAG_LOCAL
192 } vhdlKind;
194 static kindOption VhdlKinds[] = {
195 {TRUE, 'c', "constant", "constant declarations"},
196 {TRUE, 't', "type", "type definitions"},
197 {TRUE, 'T', "subtype", "subtype definitions"},
198 {TRUE, 'r', "record", "record names"},
199 {TRUE, 'e', "entity", "entity declarations"},
200 {FALSE, 'C', "component", "component declarations"},
201 {FALSE, 'd', "prototype", "prototypes"},
202 {TRUE, 'f', "function", "function prototypes and declarations"},
203 {TRUE, 'p', "procedure", "procedure prototypes and declarations"},
204 {TRUE, 'P', "package", "package definitions"},
205 {FALSE, 'l', "local", "local definitions"}
208 static keywordDesc VhdlKeywordTable[] = {
209 {"abs", KEYWORD_ABS},
210 {"access", KEYWORD_ACCESS},
211 {"after", KEYWORD_AFTER},
212 {"alias", KEYWORD_ALIAS},
213 {"all", KEYWORD_ALL},
214 {"and", KEYWORD_AND},
215 {"architecture", KEYWORD_ARCHITECTURE},
216 {"array", KEYWORD_ARRAY},
217 {"assert", KEYWORD_ASSERT},
218 {"attribute", KEYWORD_ATTRIBUTE},
219 {"begin", KEYWORD_BEGIN},
220 {"block", KEYWORD_BLOCK},
221 {"body", KEYWORD_BODY},
222 {"buffer", KEYWORD_BUFFER},
223 {"bus", KEYWORD_BUS},
224 {"case", KEYWORD_CASE},
225 {"component", KEYWORD_COMPONENT},
226 {"configuration", KEYWORD_CONFIGURATION},
227 {"constant", KEYWORD_CONSTANT},
228 {"disconnect", KEYWORD_DISCONNECT},
229 {"downto", KEYWORD_DOWNTO},
230 {"else", KEYWORD_ELSE},
231 {"elsif", KEYWORD_ELSIF},
232 {"end", KEYWORD_END},
233 {"entity", KEYWORD_ENTITY},
234 {"exit", KEYWORD_EXIT},
235 {"file", KEYWORD_FILE},
236 {"for", KEYWORD_FOR},
237 {"function", KEYWORD_FUNCTION},
238 {"generate", KEYWORD_GENERATE},
239 {"generic", KEYWORD_GENERIC},
240 {"group", KEYWORD_GROUP},
241 {"guarded", KEYWORD_GUARDED},
242 {"if", KEYWORD_IF},
243 {"impure", KEYWORD_IMPURE},
244 {"in", KEYWORD_IN},
245 {"inertial", KEYWORD_INERTIAL},
246 {"inout", KEYWORD_INOUT},
247 {"is", KEYWORD_IS},
248 {"label", KEYWORD_LABEL},
249 {"library", KEYWORD_LIBRARY},
250 {"linkage", KEYWORD_LINKAGE},
251 {"literal", KEYWORD_LITERAL},
252 {"loop", KEYWORD_LOOP},
253 {"map", KEYWORD_MAP},
254 {"mod", KEYWORD_MOD},
255 {"nand", KEYWORD_NAND},
256 {"new", KEYWORD_NEW},
257 {"next", KEYWORD_NEXT},
258 {"nor", KEYWORD_NOR},
259 {"not", KEYWORD_NOT},
260 {"null", KEYWORD_NULL},
261 {"of", KEYWORD_OF},
262 {"on", KEYWORD_ON},
263 {"open", KEYWORD_OPEN},
264 {"or", KEYWORD_OR},
265 {"others", KEYWORD_OTHERS},
266 {"out", KEYWORD_OUT},
267 {"package", KEYWORD_PACKAGE},
268 {"port", KEYWORD_PORT},
269 {"postponed", KEYWORD_POSTPONED},
270 {"procedure", KEYWORD_PROCEDURE},
271 {"process", KEYWORD_PROCESS},
272 {"pure", KEYWORD_PURE},
273 {"range", KEYWORD_RANGE},
274 {"record", KEYWORD_RECORD},
275 {"register", KEYWORD_REGISTER},
276 {"reject", KEYWORD_REJECT},
277 {"return", KEYWORD_RETURN},
278 {"rol", KEYWORD_ROL},
279 {"ror", KEYWORD_ROR},
280 {"select", KEYWORD_SELECT},
281 {"severity", KEYWORD_SEVERITY},
282 {"signal", KEYWORD_SIGNAL},
283 {"shared", KEYWORD_SHARED},
284 {"sla", KEYWORD_SLA},
285 {"sli", KEYWORD_SLI},
286 {"sra", KEYWORD_SRA},
287 {"srl", KEYWORD_SRL},
288 {"subtype", KEYWORD_SUBTYPE},
289 {"then", KEYWORD_THEN},
290 {"to", KEYWORD_TO},
291 {"transport", KEYWORD_TRANSPORT},
292 {"type", KEYWORD_TYPE},
293 {"unaffected", KEYWORD_UNAFFECTED},
294 {"units", KEYWORD_UNITS},
295 {"until", KEYWORD_UNTIL},
296 {"use", KEYWORD_USE},
297 {"variable", KEYWORD_VARIABLE},
298 {"wait", KEYWORD_WAIT},
299 {"when", KEYWORD_WHEN},
300 {"while", KEYWORD_WHILE},
301 {"with", KEYWORD_WITH},
302 {"xnor", KEYWORD_XNOR},
303 {"xor", KEYWORD_XOR}
307 * FUNCTION DECLARATIONS
309 static void parseKeywords (tokenInfo * const token, boolean local);
312 * FUNCTION DEFINITIONS
315 static boolean isIdentChar1 (const int c)
317 return (boolean) (isalpha (c) || c == '_');
320 static boolean isIdentChar (const int c)
322 return (boolean) (isalpha (c) || isdigit (c) || c == '_');
325 static boolean isIdentifierMatch (const tokenInfo * const token,
326 const vString * const name)
328 return (boolean) (isType (token, TOKEN_IDENTIFIER) &&
329 strcasecmp (vStringValue (token->string), vStringValue (name)) == 0);
330 /* XXX this is copy/paste from eiffel.c and slightly modified */
331 /* shouldn't we use strNcasecmp ? */
334 static boolean isKeywordOrIdent (const tokenInfo * const token,
335 const keywordId keyword, const vString * const name)
337 return (boolean) (isKeyword (token, keyword) ||
338 isIdentifierMatch (token, name));
341 static tokenInfo *newToken (void)
343 tokenInfo *const token = xMalloc (1, tokenInfo);
344 token->type = TOKEN_NONE;
345 token->keyword = KEYWORD_NONE;
346 token->string = vStringNew ();
347 token->scope = vStringNew ();
348 token->lineNumber = getSourceLineNumber ();
349 token->filePosition = getInputFilePosition ();
350 return token;
353 static void deleteToken (tokenInfo * const token)
355 if (token != NULL)
357 vStringDelete (token->string);
358 vStringDelete (token->scope);
359 eFree (token);
364 * Parsing functions
367 static void parseString (vString * const string, const int delimiter)
369 boolean end = FALSE;
370 while (!end)
372 int c = fileGetc ();
373 if (c == EOF)
374 end = TRUE;
375 else if (c == '\\')
377 c = fileGetc (); /* This maybe a ' or ". */
378 vStringPut (string, c);
380 else if (c == delimiter)
381 end = TRUE;
382 else
383 vStringPut (string, c);
385 vStringTerminate (string);
388 /* Read a VHDL identifier beginning with "firstChar" and place it into "name".
390 static void parseIdentifier (vString * const string, const int firstChar)
392 int c = firstChar;
393 Assert (isIdentChar1 (c));
396 vStringPut (string, c);
397 c = fileGetc ();
398 } while (isIdentChar (c));
399 vStringTerminate (string);
400 if (!isspace (c))
401 fileUngetc (c); /* unget non-identifier character */
404 static void readToken (tokenInfo * const token)
406 int c;
408 token->type = TOKEN_NONE;
409 token->keyword = KEYWORD_NONE;
410 vStringClear (token->string);
412 getNextChar:
415 c = fileGetc ();
416 token->lineNumber = getSourceLineNumber ();
417 token->filePosition = getInputFilePosition ();
419 while (c == '\t' || c == ' ' || c == '\n');
421 switch (c)
423 case EOF:
424 longjmp (Exception, (int) ExceptionEOF);
425 break;
426 case '(':
427 token->type = TOKEN_OPEN_PAREN;
428 break;
429 case ')':
430 token->type = TOKEN_CLOSE_PAREN;
431 break;
432 case ';':
433 token->type = TOKEN_SEMICOLON;
434 break;
435 case '.':
436 token->type = TOKEN_PERIOD;
437 break;
438 case ',':
439 token->type = TOKEN_COMMA;
440 break;
441 case '\'': /* only single char are inside simple quotes */
442 break; /* or it is for attributes so we don't care */
443 case '"':
444 token->type = TOKEN_STRING;
445 parseString (token->string, c);
446 token->lineNumber = getSourceLineNumber ();
447 token->filePosition = getInputFilePosition ();
448 break;
449 case '-':
450 c = fileGetc ();
451 if (c == '-') /* start of a comment */
453 fileSkipToCharacter ('\n');
454 goto getNextChar;
456 else
458 if (!isspace (c))
459 fileUngetc (c);
460 token->type = TOKEN_OPERATOR;
462 break;
463 default:
464 if (!isIdentChar1 (c))
465 token->type = TOKEN_NONE;
466 else
468 parseIdentifier (token->string, c);
469 token->lineNumber = getSourceLineNumber ();
470 token->filePosition = getInputFilePosition ();
471 token->keyword = analyzeToken (token->string, Lang_vhdl);
472 if (isKeyword (token, KEYWORD_NONE))
473 token->type = TOKEN_IDENTIFIER;
474 else
475 token->type = TOKEN_KEYWORD;
477 break;
481 static void skipToKeyword (const keywordId keyword)
483 tokenInfo *const token = newToken ();
486 readToken (token);
488 while (!isKeyword (token, keyword));
489 deleteToken (token);
492 static void skipToMatched (tokenInfo * const token)
494 int nest_level = 0;
495 tokenType open_token;
496 tokenType close_token;
498 switch (token->type)
500 case TOKEN_OPEN_PAREN:
501 open_token = TOKEN_OPEN_PAREN;
502 close_token = TOKEN_CLOSE_PAREN;
503 break;
504 default:
505 return;
509 * This routine will skip to a matching closing token.
510 * It will also handle nested tokens like the (, ) below.
511 * ( name varchar(30), text binary(10) )
513 if (isType (token, open_token))
515 nest_level++;
516 while (!(isType (token, close_token) && (nest_level == 0)))
518 readToken (token);
519 if (isType (token, open_token))
521 nest_level++;
523 if (isType (token, close_token))
525 if (nest_level > 0)
527 nest_level--;
531 readToken (token);
535 static void makeConstTag (tokenInfo * const token, const vhdlKind kind)
537 if (VhdlKinds[kind].enabled)
539 const char *const name = vStringValue (token->string);
540 tagEntryInfo e;
541 initTagEntry (&e, name);
542 e.lineNumber = token->lineNumber;
543 e.filePosition = token->filePosition;
544 e.kindName = VhdlKinds[kind].name;
545 e.kind = VhdlKinds[kind].letter;
546 makeTagEntry (&e);
550 static void makeVhdlTag (tokenInfo * const token, const vhdlKind kind)
552 if (VhdlKinds[kind].enabled)
555 * If a scope has been added to the token, change the token
556 * string to include the scope when making the tag.
558 if (vStringLength (token->scope) > 0)
560 vString *fulltag = vStringNew ();
561 vStringCopy (fulltag, token->scope);
562 vStringCatS (fulltag, ".");
563 vStringCatS (fulltag, vStringValue (token->string));
564 vStringTerminate (fulltag);
565 vStringCopy (token->string, fulltag);
566 vStringDelete (fulltag);
568 makeConstTag (token, kind);
572 static void initialize (const langType language)
574 size_t i;
575 const size_t count =
576 sizeof (VhdlKeywordTable) / sizeof (VhdlKeywordTable[0]);
577 Lang_vhdl = language;
578 for (i = 0; i < count; ++i)
580 const keywordDesc *const p = &VhdlKeywordTable[i];
581 addKeyword (p->name, language, (int) p->id);
585 static void parsePackage (tokenInfo * const token)
587 tokenInfo *const name = newToken ();
588 Assert (isKeyword (token, KEYWORD_PACKAGE));
589 readToken (token);
590 if (isKeyword (token, KEYWORD_BODY))
592 readToken (name);
593 makeVhdlTag (name, VHDLTAG_PACKAGE);
595 else if (isType (token, TOKEN_IDENTIFIER))
597 makeVhdlTag (token, VHDLTAG_PACKAGE);
599 deleteToken (name);
602 static void parseModule (tokenInfo * const token)
604 tokenInfo *const name = newToken ();
605 const vhdlKind kind = isKeyword (token, KEYWORD_ENTITY) ?
606 VHDLTAG_ENTITY : VHDLTAG_COMPONENT;
607 Assert (isKeyword (token, KEYWORD_ENTITY) ||
608 isKeyword (token, KEYWORD_COMPONENT));
609 readToken (name);
610 if (kind == VHDLTAG_COMPONENT)
612 makeVhdlTag (name, VHDLTAG_COMPONENT);
613 skipToKeyword (KEYWORD_END);
614 fileSkipToCharacter (';');
616 else
618 readToken (token);
619 if (isKeyword (token, KEYWORD_IS))
621 makeVhdlTag (name, VHDLTAG_ENTITY);
622 skipToKeyword (KEYWORD_END);
623 fileSkipToCharacter (';');
626 deleteToken (name);
629 static void parseRecord (tokenInfo * const token)
631 tokenInfo *const name = newToken ();
632 Assert (isKeyword (token, KEYWORD_RECORD));
633 readToken (name);
636 readToken (token); /* should be a colon */
637 fileSkipToCharacter (';');
638 makeVhdlTag (name, VHDLTAG_RECORD);
639 readToken (name);
641 while (!isKeyword (name, KEYWORD_END));
642 fileSkipToCharacter (';');
643 deleteToken (name);
646 static void parseTypes (tokenInfo * const token)
648 tokenInfo *const name = newToken ();
649 const vhdlKind kind = isKeyword (token, KEYWORD_TYPE) ?
650 VHDLTAG_TYPE : VHDLTAG_SUBTYPE;
651 Assert (isKeyword (token, KEYWORD_TYPE) ||
652 isKeyword (token, KEYWORD_SUBTYPE));
653 readToken (name);
654 readToken (token);
655 if (isKeyword (token, KEYWORD_IS))
657 readToken (token); /* type */
658 if (isKeyword (token, KEYWORD_RECORD))
660 makeVhdlTag (name, kind);
661 /*TODO: make tags of the record's names */
662 parseRecord (token);
664 else
666 makeVhdlTag (name, kind);
669 deleteToken (name);
672 static void parseConstant (boolean local)
674 tokenInfo *const name = newToken ();
675 readToken (name);
676 if (local)
678 makeVhdlTag (name, VHDLTAG_LOCAL);
680 else
682 makeVhdlTag (name, VHDLTAG_CONSTANT);
684 fileSkipToCharacter (';');
685 deleteToken (name);
688 static void parseSubProgram (tokenInfo * const token)
690 tokenInfo *const name = newToken ();
691 boolean endSubProgram = FALSE;
692 const vhdlKind kind = isKeyword (token, KEYWORD_FUNCTION) ?
693 VHDLTAG_FUNCTION : VHDLTAG_PROCEDURE;
694 Assert (isKeyword (token, KEYWORD_FUNCTION) ||
695 isKeyword (token, KEYWORD_PROCEDURE));
696 readToken (name); /* the name of the function or procedure */
697 readToken (token);
698 if (isType (token, TOKEN_OPEN_PAREN))
700 skipToMatched (token);
703 if (kind == VHDLTAG_FUNCTION)
705 if (isKeyword (token, KEYWORD_RETURN))
707 /* Read datatype */
708 readToken (token);
709 while (! isKeyword (token, KEYWORD_IS) &&
710 ! isType (token, TOKEN_SEMICOLON))
712 readToken (token);
717 if (isType (token, TOKEN_SEMICOLON))
719 makeVhdlTag (name, VHDLTAG_PROTOTYPE);
721 else if (isKeyword (token, KEYWORD_IS))
723 if (kind == VHDLTAG_FUNCTION)
725 makeVhdlTag (name, VHDLTAG_FUNCTION);
728 readToken (token);
729 if (isKeyword (token, KEYWORD_END))
731 readToken (token);
732 endSubProgram = isKeywordOrIdent (token,
733 KEYWORD_FUNCTION, name->string);
734 fileSkipToCharacter (';');
736 else
738 parseKeywords (token, TRUE);
740 } while (!endSubProgram);
742 else
744 makeVhdlTag (name, VHDLTAG_PROCEDURE);
747 readToken (token);
748 if (isKeyword (token, KEYWORD_END))
750 readToken (token);
751 endSubProgram = isKeywordOrIdent (token,
752 KEYWORD_PROCEDURE, name->string);
753 fileSkipToCharacter (';');
755 else
757 parseKeywords (token, TRUE);
759 } while (!endSubProgram);
762 deleteToken (name);
765 /* TODO */
766 /* records */
767 static void parseKeywords (tokenInfo * const token, boolean local)
769 switch (token->keyword)
771 case KEYWORD_END:
772 fileSkipToCharacter (';');
773 break;
774 case KEYWORD_CONSTANT:
775 parseConstant (local);
776 break;
777 case KEYWORD_TYPE:
778 parseTypes (token);
779 break;
780 case KEYWORD_SUBTYPE:
781 parseTypes (token);
782 break;
783 case KEYWORD_ENTITY:
784 parseModule (token);
785 break;
786 case KEYWORD_COMPONENT:
787 parseModule (token);
788 break;
789 case KEYWORD_FUNCTION:
790 parseSubProgram (token);
791 break;
792 case KEYWORD_PROCEDURE:
793 parseSubProgram (token);
794 break;
795 case KEYWORD_PACKAGE:
796 parsePackage (token);
797 break;
798 default:
799 break;
803 static void parseVhdlFile (tokenInfo * const token)
807 readToken (token);
808 parseKeywords (token, FALSE);
809 } while (!isKeyword (token, KEYWORD_END));
812 static void findVhdlTags (void)
814 tokenInfo *const token = newToken ();
815 exception_t exception = (exception_t) (setjmp (Exception));
817 while (exception == ExceptionNone)
818 parseVhdlFile (token);
820 deleteToken (token);
823 extern parserDefinition *VhdlParser (void)
825 static const char *const extensions[] = { "vhdl", "vhd", NULL };
826 parserDefinition *def = parserNew ("VHDL");
827 def->kinds = VhdlKinds;
828 def->kindCount = KIND_COUNT (VhdlKinds);
829 def->extensions = extensions;
830 def->parser = findVhdlTags;
831 def->initialize = initialize;
832 return def;
835 /* vi:set tabstop=4 shiftwidth=4 noet: */