2 * Copyright (c) 2008, Nicolas Vincent
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * This module contains functions for generating tags for VHDL files.
10 * https://rti.etf.bg.ac.rs/rti/ri5rvl/tutorial/TUTORIAL/IEEE/HTML/1076_TOC.HTM
11 * https://tams.informatik.uni-hamburg.de/vhdl/tools/grammar/vhdl93-bnf.html
12 * http://www.vhdl.renerta.com/mobile/index.html
13 * https://www.hdlworks.com/hdl_corner/vhdl_ref/
14 * https://www.ics.uci.edu/~jmoorkan/vhdlref/Synario%20VHDL%20Manual.pdf
15 * http://atlas.physics.arizona.edu/~kjohns/downloads/vhdl/VHDL-xilinx-help.pdf
16 * http://www.csit-sun.pub.ro/resources/xilinx/synvhdl.pdf
17 * https://edg.uchicago.edu/~tang/VHDLref.pdf
23 #include "general.h" /* must always come first */
25 #include <ctype.h> /* to define isalpha () */
40 #define isType(token,t) (bool) ((token)->type == (t))
41 #define isKeyword(token,k) (bool) ((token)->keyword == (k))
42 #define isIdentChar1(c) (isalpha (c) || (c) == '_')
43 #define isIdentChar(c) (isalpha (c) || isdigit (c) || (c) == '_')
50 * Used to specify type of keyword.
70 KEYWORD_CONFIGURATION
,
149 typedef int keywordId
; /* to allow KEYWORD_NONE */
151 typedef enum eTokenType
{
152 TOKEN_NONE
, /* none */
153 TOKEN_EOF
, /* end-of-file */
154 TOKEN_OPEN_PAREN
, /* ( */
155 TOKEN_CLOSE_PAREN
, /* ) */
156 TOKEN_COMMA
, /* the comma character */
159 TOKEN_PERIOD
, /* . */
161 TOKEN_SEMICOLON
, /* the semicolon character */
166 typedef struct sTokenInfo
{
169 vString
*string
; /* the name of the token */
170 unsigned long lineNumber
; /* line number of tag */
171 MIOPos filePosition
; /* file position of line containing name */
177 static int Lang_vhdl
;
180 VHDL_ENTITY_DESIGNED
,
183 static roleDefinition VhdlEntityRoles
[] = {
185 "designed by an architecture" },
188 /* Used to index into the VhdlKinds table. */
190 VHDLTAG_UNDEFINED
= -1,
202 VHDLTAG_ARCHITECTURE
,
211 static kindDefinition VhdlKinds
[] = {
212 {true, 'c', "constant", "constant declarations"},
213 {true, 't', "type", "type definitions"},
214 {true, 'T', "subtype", "subtype definitions"},
215 {true, 'r', "record", "record names"},
216 {true, 'e', "entity", "entity declarations",
217 .referenceOnly
= false, ATTACH_ROLES(VhdlEntityRoles
)},
218 {false, 'C', "component", "component declarations"},
219 {false, 'd', "prototype", "prototypes"},
220 {true, 'f', "function", "function prototypes and declarations"},
221 {true, 'p', "procedure", "procedure prototypes and declarations"},
222 {true, 'P', "package", "package definitions"},
223 {false, 'l', "local", "local definitions"},
224 {true, 'a', "architecture", "architectures"},
225 {true, 'q', "port", "port declarations"},
226 {true, 'g', "generic", "generic declarations"},
227 {true , 's', "signal", "signal declarations"},
228 {true, 'Q', "process", "processes"},
229 {true, 'v', "variable", "variables"},
230 {true, 'A', "alias", "aliases"},
233 static const keywordTable VhdlKeywordTable
[] = {
234 {"abs", KEYWORD_ABS
},
235 {"access", KEYWORD_ACCESS
},
236 {"after", KEYWORD_AFTER
},
237 {"alias", KEYWORD_ALIAS
},
238 {"all", KEYWORD_ALL
},
239 {"and", KEYWORD_AND
},
240 {"architecture", KEYWORD_ARCHITECTURE
},
241 {"array", KEYWORD_ARRAY
},
242 {"assert", KEYWORD_ASSERT
},
243 {"attribute", KEYWORD_ATTRIBUTE
},
244 {"begin", KEYWORD_BEGIN
},
245 {"block", KEYWORD_BLOCK
},
246 {"body", KEYWORD_BODY
},
247 {"buffer", KEYWORD_BUFFER
},
248 {"bus", KEYWORD_BUS
},
249 {"case", KEYWORD_CASE
},
250 {"component", KEYWORD_COMPONENT
},
251 {"configuration", KEYWORD_CONFIGURATION
},
252 {"constant", KEYWORD_CONSTANT
},
253 {"disconnect", KEYWORD_DISCONNECT
},
254 {"downto", KEYWORD_DOWNTO
},
255 {"else", KEYWORD_ELSE
},
256 {"elsif", KEYWORD_ELSIF
},
257 {"end", KEYWORD_END
},
258 {"entity", KEYWORD_ENTITY
},
259 {"exit", KEYWORD_EXIT
},
260 {"file", KEYWORD_FILE
},
261 {"for", KEYWORD_FOR
},
262 {"function", KEYWORD_FUNCTION
},
263 {"generate", KEYWORD_GENERATE
},
264 {"generic", KEYWORD_GENERIC
},
265 {"group", KEYWORD_GROUP
},
266 {"guarded", KEYWORD_GUARDED
},
268 {"impure", KEYWORD_IMPURE
},
270 {"inertial", KEYWORD_INERTIAL
},
271 {"inout", KEYWORD_INOUT
},
273 {"label", KEYWORD_LABEL
},
274 {"library", KEYWORD_LIBRARY
},
275 {"linkage", KEYWORD_LINKAGE
},
276 {"literal", KEYWORD_LITERAL
},
277 {"loop", KEYWORD_LOOP
},
278 {"map", KEYWORD_MAP
},
279 {"mod", KEYWORD_MOD
},
280 {"nand", KEYWORD_NAND
},
281 {"new", KEYWORD_NEW
},
282 {"next", KEYWORD_NEXT
},
283 {"nor", KEYWORD_NOR
},
284 {"not", KEYWORD_NOT
},
285 {"null", KEYWORD_NULL
},
288 {"open", KEYWORD_OPEN
},
290 {"others", KEYWORD_OTHERS
},
291 {"out", KEYWORD_OUT
},
292 {"package", KEYWORD_PACKAGE
},
293 {"port", KEYWORD_PORT
},
294 {"postponed", KEYWORD_POSTPONED
},
295 {"procedure", KEYWORD_PROCEDURE
},
296 {"process", KEYWORD_PROCESS
},
297 {"pure", KEYWORD_PURE
},
298 {"range", KEYWORD_RANGE
},
299 {"record", KEYWORD_RECORD
},
300 {"register", KEYWORD_REGISTER
},
301 {"reject", KEYWORD_REJECT
},
302 {"return", KEYWORD_RETURN
},
303 {"rol", KEYWORD_ROL
},
304 {"ror", KEYWORD_ROR
},
305 {"select", KEYWORD_SELECT
},
306 {"severity", KEYWORD_SEVERITY
},
307 {"signal", KEYWORD_SIGNAL
},
308 {"shared", KEYWORD_SHARED
},
309 {"sla", KEYWORD_SLA
},
310 {"sli", KEYWORD_SLI
},
311 {"sra", KEYWORD_SRA
},
312 {"srl", KEYWORD_SRL
},
313 {"subtype", KEYWORD_SUBTYPE
},
314 {"then", KEYWORD_THEN
},
316 {"transport", KEYWORD_TRANSPORT
},
317 {"type", KEYWORD_TYPE
},
318 {"unaffected", KEYWORD_UNAFFECTED
},
319 {"units", KEYWORD_UNITS
},
320 {"until", KEYWORD_UNTIL
},
321 {"use", KEYWORD_USE
},
322 {"variable", KEYWORD_VARIABLE
},
323 {"wait", KEYWORD_WAIT
},
324 {"when", KEYWORD_WHEN
},
325 {"while", KEYWORD_WHILE
},
326 {"with", KEYWORD_WITH
},
327 {"xnor", KEYWORD_XNOR
},
335 static fieldDefinition VhdlFields
[] = {
336 { .name
= "architecture",
337 .description
= "architecture designing the entity",
342 * FUNCTION DECLARATIONS
344 static void parseKeywords (tokenInfo
* const token
, tokenInfo
* const label
, int parent
);
347 * FUNCTION DEFINITIONS
349 static bool isIdentifierMatch (const tokenInfo
* const token
,
352 return (bool) (isType (token
, TOKEN_IDENTIFIER
) &&
353 strncasecmp (vStringValue (token
->string
), name
,
354 vStringLength (token
->string
)) == 0);
357 static bool isSemicolonOrKeywordOrIdent (const tokenInfo
* const token
,
358 const keywordId keyword
, const char *name
)
360 return (bool) (isType (token
, TOKEN_SEMICOLON
)
361 || isKeyword (token
, keyword
)
362 || isIdentifierMatch (token
, name
));
365 static tokenInfo
*newToken (void)
367 tokenInfo
*const token
= xMalloc (1, tokenInfo
);
368 token
->type
= TOKEN_NONE
;
369 token
->keyword
= KEYWORD_NONE
;
370 token
->string
= vStringNew ();
371 token
->lineNumber
= getInputLineNumber ();
372 token
->filePosition
= getInputFilePosition ();
376 static tokenInfo
*copyToken (tokenInfo
* const src
)
378 tokenInfo
*dst
= newToken ();
379 vStringCopy (dst
->string
, src
->string
);
383 static void deleteToken (tokenInfo
* const token
)
387 vStringDelete (token
->string
);
396 static void parseString (vString
* const string
, const int delimiter
)
401 int c
= getcFromInputFile ();
406 c
= getcFromInputFile (); /* This maybe a ' or ". */
407 vStringPut (string
, c
);
409 else if (c
== delimiter
)
412 vStringPut (string
, c
);
416 /* Read a VHDL identifier beginning with "firstChar" and place it into "name".
418 static void parseIdentifier (vString
* const string
, const int firstChar
)
421 Assert (isIdentChar1 (c
));
424 vStringPut (string
, c
);
425 c
= getcFromInputFile ();
426 } while (isIdentChar (c
));
428 ungetcToInputFile (c
); /* unget non-identifier character */
431 static void readToken (tokenInfo
* const token
)
435 token
->type
= TOKEN_NONE
;
436 token
->keyword
= KEYWORD_NONE
;
437 vStringClear (token
->string
);
442 c
= getcFromInputFile ();
443 token
->lineNumber
= getInputLineNumber ();
444 token
->filePosition
= getInputFilePosition ();
446 while (c
== '\t' || c
== ' ' || c
== '\n');
451 token
->type
= TOKEN_EOF
;
454 token
->type
= TOKEN_OPEN_PAREN
;
457 token
->type
= TOKEN_CLOSE_PAREN
;
460 token
->type
= TOKEN_SEMICOLON
;
463 token
->type
= TOKEN_COLON
;
466 token
->type
= TOKEN_PERIOD
;
469 token
->type
= TOKEN_COMMA
;
471 case '\'': /* only single char are inside simple quotes */
472 break; /* or it is for attributes so we don't care */
474 token
->type
= TOKEN_STRING
;
475 parseString (token
->string
, c
);
476 token
->lineNumber
= getInputLineNumber ();
477 token
->filePosition
= getInputFilePosition ();
480 c
= getcFromInputFile ();
481 if (c
== '-') /* start of a comment */
483 skipToCharacterInInputFile ('\n');
489 ungetcToInputFile (c
);
490 token
->type
= TOKEN_OPERATOR
;
494 if (!isIdentChar1 (c
))
495 token
->type
= TOKEN_NONE
;
498 parseIdentifier (token
->string
, c
);
499 token
->lineNumber
= getInputLineNumber ();
500 token
->filePosition
= getInputFilePosition ();
501 token
->keyword
= lookupCaseKeyword (vStringValue (token
->string
), Lang_vhdl
);
502 if (isKeyword (token
, KEYWORD_NONE
))
503 token
->type
= TOKEN_IDENTIFIER
;
505 token
->type
= TOKEN_KEYWORD
;
511 static bool skipToKeyword (const keywordId keyword
)
513 tokenInfo
*const token
= newToken ();
518 while (!isType (token
, TOKEN_EOF
) && !isKeyword (token
, keyword
));
520 bool r
= isKeyword (token
, keyword
);
525 static void skipToMatched (tokenInfo
* const token
)
528 tokenType open_token
;
529 tokenType close_token
;
533 case TOKEN_OPEN_PAREN
:
534 open_token
= TOKEN_OPEN_PAREN
;
535 close_token
= TOKEN_CLOSE_PAREN
;
542 * This routine will skip to a matching closing token.
543 * It will also handle nested tokens like the (, ) below.
544 * ( name varchar(30), text binary(10) )
546 if (isType (token
, open_token
))
549 while (!(isType (token
, close_token
) && (nest_level
== 0)) && !isType (token
, TOKEN_EOF
))
552 if (isType (token
, open_token
))
556 if (isType (token
, close_token
))
568 static int makeVhdlTagWithScope (tokenInfo
* const token
, const vhdlKind kind
, int parent
)
570 const char *const name
= vStringValue (token
->string
);
572 initTagEntry (&e
, name
, kind
);
573 updateTagLine (&e
, token
->lineNumber
, token
->filePosition
);
574 e
.extensionFields
.scopeIndex
= parent
;
575 return makeTagEntry (&e
);
578 static int makeVhdlTag (tokenInfo
* const token
, const vhdlKind kind
)
580 return makeVhdlTagWithScope (token
, kind
, CORK_NIL
);
583 static void initialize (const langType language
)
585 Lang_vhdl
= language
;
588 static void parseTillEnd (tokenInfo
* const token
, int parent
, const int end_keyword
)
591 tagEntryInfo
*e
= getEntryInCorkQueue (parent
);
592 /* If e is NULL, the input may be broken as VHDL code
593 * or unsupported syntax in this parser. */
598 if (isKeyword (token
, KEYWORD_END
))
602 ended
= isSemicolonOrKeywordOrIdent (token
,
603 end_keyword
, e
->name
);
604 if (!isType (token
, TOKEN_SEMICOLON
))
605 skipToCharacterInInputFile (';');
607 setTagEndLine (e
, getInputLineNumber ());
611 if (isType (token
, TOKEN_EOF
))
617 parseKeywords (token
, NULL
, parent
);
623 static void parseTillBegin (tokenInfo
* const token
, int parent
)
629 if (isKeyword (token
, KEYWORD_BEGIN
)
630 || isType (token
, TOKEN_EOF
))
633 parseKeywords (token
, NULL
, parent
);
637 static void parsePackage (tokenInfo
* const token
)
639 tokenInfo
*const name
= newToken ();
640 tokenInfo
*token_for_tagging
= NULL
;
641 Assert (isKeyword (token
, KEYWORD_PACKAGE
));
643 if (isKeyword (token
, KEYWORD_BODY
))
646 token_for_tagging
= name
;
648 else if (isType (token
, TOKEN_IDENTIFIER
))
649 token_for_tagging
= token
;
651 if (token_for_tagging
)
653 int index
= makeVhdlTag (token_for_tagging
, VHDLTAG_PACKAGE
);
654 parseTillEnd (token
, index
, KEYWORD_PACKAGE
);
661 static void parseDeclElement (tokenInfo
* const token
,
662 vhdlKind kind
, int parent
,
663 bool ended_with_semicolon
)
666 while (! (isType (token
, TOKEN_EOF
)
667 || isType (token
, TOKEN_CLOSE_PAREN
)
668 || (ended_with_semicolon
&& isType (token
, TOKEN_SEMICOLON
))))
670 if (isType (token
, TOKEN_IDENTIFIER
))
672 makeVhdlTagWithScope (token
, kind
, parent
);
675 else if (isType (token
, TOKEN_COMMA
))
677 else if (isType (token
, TOKEN_COLON
))
682 skipToMatched (token
);
683 if (isType (token
, TOKEN_CLOSE_PAREN
)
684 || isType (token
, TOKEN_SEMICOLON
))
687 while (!isType (token
, TOKEN_EOF
));
698 static void parseModuleDecl (tokenInfo
* const token
, int parent
)
701 while (! (isKeyword (token
, KEYWORD_END
)
702 || isType (token
, TOKEN_EOF
)))
704 vhdlKind kind
= VHDLTAG_UNDEFINED
;
705 if (isKeyword (token
, KEYWORD_PORT
))
707 else if (isKeyword (token
, KEYWORD_GENERIC
))
708 kind
= VHDLTAG_GENERIC
;
710 if (kind
!= VHDLTAG_UNDEFINED
)
713 if (isType (token
, TOKEN_OPEN_PAREN
))
716 parseDeclElement (token
, kind
, parent
, false);
725 static void parseModule (tokenInfo
* const token
, int parent
)
727 tokenInfo
*const name
= newToken ();
728 const vhdlKind kind
= isKeyword (token
, KEYWORD_ENTITY
) ?
729 VHDLTAG_ENTITY
: VHDLTAG_COMPONENT
;
730 Assert (isKeyword (token
, KEYWORD_ENTITY
) ||
731 isKeyword (token
, KEYWORD_COMPONENT
));
734 if (kind
== VHDLTAG_COMPONENT
|| isKeyword (token
, KEYWORD_IS
))
736 int index
= makeVhdlTagWithScope (name
, kind
, parent
);
737 if (isKeyword (token
, KEYWORD_IS
))
739 parseModuleDecl (token
, index
);
741 bool ended
= isKeyword (token
, KEYWORD_END
);
743 ended
= skipToKeyword (KEYWORD_END
);
744 skipToCharacterInInputFile (';');
748 tagEntryInfo
*e
= getEntryInCorkQueue (index
);
750 setTagEndLine (e
, getInputLineNumber ());
753 if (kind
== VHDLTAG_ENTITY
)
754 registerEntry (index
);
759 static void parseRecord (tokenInfo
* const token
, int parent
)
761 tokenInfo
*const name
= newToken ();
762 Assert (isKeyword (token
, KEYWORD_RECORD
));
766 readToken (token
); /* should be a colon */
767 skipToCharacterInInputFile (';');
768 makeVhdlTagWithScope (name
, VHDLTAG_RECORD
, parent
);
771 while (!isKeyword (name
, KEYWORD_END
) && !isType (name
, TOKEN_EOF
));
772 skipToCharacterInInputFile (';');
774 if (isKeyword (name
, KEYWORD_END
))
776 tagEntryInfo
*e
= getEntryInCorkQueue (parent
);
778 setTagEndLine (e
, getInputLineNumber ());
784 static void parseTypes (tokenInfo
* const token
, int parent
)
786 tokenInfo
*const name
= newToken ();
787 const vhdlKind kind
= isKeyword (token
, KEYWORD_TYPE
) ?
788 VHDLTAG_TYPE
: VHDLTAG_SUBTYPE
;
789 Assert (isKeyword (token
, KEYWORD_TYPE
) ||
790 isKeyword (token
, KEYWORD_SUBTYPE
));
793 if (isKeyword (token
, KEYWORD_IS
))
795 readToken (token
); /* type */
796 if (isKeyword (token
, KEYWORD_RECORD
))
798 int index
= makeVhdlTagWithScope (name
, kind
, parent
);
799 /*TODO: make tags of the record's names */
800 parseRecord (token
, index
);
804 makeVhdlTagWithScope (name
, kind
, parent
);
810 static void parseConstant (int parent
)
812 vhdlKind parent_kind
= VHDLTAG_UNDEFINED
;
813 tagEntryInfo
*e
= getEntryInCorkQueue (parent
);
815 parent_kind
= e
->kindIndex
;
820 case VHDLTAG_FUNCTION
:
821 case VHDLTAG_PROCEDURE
:
822 kind
= VHDLTAG_LOCAL
;
825 kind
= VHDLTAG_CONSTANT
;
829 tokenInfo
*const name
= newToken ();
831 makeVhdlTagWithScope (name
, kind
, parent
);
832 skipToCharacterInInputFile (';');
836 static void parseSubProgram (tokenInfo
* const token
, int parent
)
838 tokenInfo
*const name
= newToken ();
839 const vhdlKind kind
= isKeyword (token
, KEYWORD_FUNCTION
) ?
840 VHDLTAG_FUNCTION
: VHDLTAG_PROCEDURE
;
841 const int end_keyword
= token
->keyword
;
842 Assert (isKeyword (token
, KEYWORD_FUNCTION
) ||
843 isKeyword (token
, KEYWORD_PROCEDURE
));
844 readToken (name
); /* the name of the function or procedure */
846 if (isType (token
, TOKEN_OPEN_PAREN
))
848 skipToMatched (token
);
851 if (kind
== VHDLTAG_FUNCTION
)
853 if (isKeyword (token
, KEYWORD_RETURN
))
857 while (! isKeyword (token
, KEYWORD_IS
) &&
858 ! isType (token
, TOKEN_SEMICOLON
) &&
859 ! isType (token
, TOKEN_EOF
))
866 if (isType (token
, TOKEN_SEMICOLON
))
868 makeVhdlTagWithScope (name
, VHDLTAG_PROTOTYPE
, parent
);
870 else if (isKeyword (token
, KEYWORD_IS
))
872 int index
= makeVhdlTagWithScope (name
, kind
, parent
);
873 parseTillEnd (token
, index
, end_keyword
);
878 /* architecture behavioral of ent is*/
879 static void parseArchitecture (tokenInfo
* const token
)
881 tokenInfo
*const name
= newToken ();
884 if (!isType (name
, TOKEN_IDENTIFIER
))
886 skipToKeyword (KEYWORD_END
);
887 skipToCharacterInInputFile (';');
892 int index
= makeVhdlTag (name
, VHDLTAG_ARCHITECTURE
);
894 if (isKeyword (token
, KEYWORD_OF
))
897 if (isType (token
, TOKEN_IDENTIFIER
))
899 /* Filling scope field of this architecture.
900 If the definition for the entity can be found in the symbol table,
901 use its cork as the scope. If not, use the reference tag for the
902 entity as fallback. */
903 int role_index
= makeSimpleRefTag (token
->string
,
904 VHDLTAG_ENTITY
, VHDL_ENTITY_DESIGNED
);
905 int entity_index
= anyKindEntryInScope (CORK_NIL
,
906 vStringValue (token
->string
),
909 tagEntryInfo
*e
= getEntryInCorkQueue (index
);
912 e
->extensionFields
.scopeIndex
= (
913 entity_index
== CORK_NIL
917 /* TODO: append thes architecture name to
918 * architecture: field of *e*. */
921 attachParserFieldToCorkEntry (role_index
,
922 VhdlFields
[F_ARCHITECTURE
].ftype
,
923 vStringValue (name
->string
));
926 if (isKeyword (token
, KEYWORD_IS
))
928 parseTillBegin (token
, index
);
929 parseTillEnd (token
, index
, KEYWORD_ARCHITECTURE
);
936 static void parseSignal (tokenInfo
* const token
, int parent
)
939 parseDeclElement (token
, VHDLTAG_SIGNAL
, parent
, true);
942 static void parseLabel (tokenInfo
* const name
, int parent
)
944 tokenInfo
*const token
= newToken ();
947 if (isType (token
, TOKEN_COLON
))
950 if (isType (token
, TOKEN_KEYWORD
))
951 parseKeywords (token
, name
, parent
);
956 static void parseProcess (tokenInfo
* const token
, tokenInfo
* const label
, int parent
)
958 tokenInfo
*process
= label
? label
: copyToken (token
);
962 process
->type
= TOKEN_IDENTIFIER
;
963 vStringClear (process
->string
);
964 anonGenerate (process
->string
, "anonProcess", VHDLTAG_PROCESS
);
967 int index
= makeVhdlTagWithScope (process
, VHDLTAG_PROCESS
, parent
);
971 tagEntryInfo
*e
= getEntryInCorkQueue (index
);
973 markTagExtraBit (e
, XTAG_ANONYMOUS
);
974 deleteToken (process
);
977 skipToMatched (token
);
978 parseTillBegin (token
, index
);
979 parseTillEnd (token
, index
, KEYWORD_PROCESS
);
982 static void parseVariable (tokenInfo
* const token
, int parent
)
985 parseDeclElement (token
, VHDLTAG_VARIABLE
, parent
, true);
988 static void parseAlias (tokenInfo
* const token
, int parent
)
991 parseDeclElement (token
, VHDLTAG_ALIAS
, parent
, true);
996 static void parseKeywords (tokenInfo
* const token
, tokenInfo
* const label
, int index
)
998 switch (token
->keyword
)
1001 skipToCharacterInInputFile (';');
1003 case KEYWORD_CONSTANT
:
1004 parseConstant (index
);
1007 parseTypes (token
, index
);
1009 case KEYWORD_SUBTYPE
:
1010 parseTypes (token
, index
);
1012 case KEYWORD_ENTITY
:
1013 parseModule (token
, index
);
1015 case KEYWORD_COMPONENT
:
1016 parseModule (token
, index
);
1018 case KEYWORD_FUNCTION
:
1019 parseSubProgram (token
, index
);
1021 case KEYWORD_PROCEDURE
:
1022 parseSubProgram (token
, index
);
1024 case KEYWORD_PACKAGE
:
1025 parsePackage (token
);
1027 case KEYWORD_ARCHITECTURE
:
1028 parseArchitecture (token
);
1030 case KEYWORD_SIGNAL
:
1031 parseSignal (token
, index
);
1033 case KEYWORD_PROCESS
:
1034 parseProcess (token
, label
, index
);
1036 case KEYWORD_VARIABLE
:
1037 parseVariable (token
, index
);
1040 parseAlias (token
, index
);
1043 if (isType (token
, TOKEN_IDENTIFIER
))
1044 parseLabel (token
, index
);
1049 static tokenType
parseVhdlFile (tokenInfo
* const token
)
1054 parseKeywords (token
, NULL
, CORK_NIL
);
1055 } while (!isKeyword (token
, KEYWORD_END
) && !isType (token
, TOKEN_EOF
));
1059 static void findVhdlTags (void)
1061 tokenInfo
*const token
= newToken ();
1063 while (parseVhdlFile (token
) != TOKEN_EOF
);
1065 deleteToken (token
);
1068 extern parserDefinition
*VhdlParser (void)
1070 static const char *const extensions
[] = { "vhdl", "vhd", NULL
};
1071 parserDefinition
*def
= parserNew ("VHDL");
1072 def
->kindTable
= VhdlKinds
;
1073 def
->kindCount
= ARRAY_SIZE (VhdlKinds
);
1074 def
->extensions
= extensions
;
1075 def
->parser
= findVhdlTags
;
1076 def
->initialize
= initialize
;
1077 def
->keywordTable
= VhdlKeywordTable
;
1078 def
->keywordCount
= ARRAY_SIZE (VhdlKeywordTable
);
1079 def
->fieldTable
= VhdlFields
;
1080 def
->fieldCount
= ARRAY_SIZE (VhdlFields
);
1081 def
->useCork
= CORK_QUEUE
|CORK_SYMTAB
;