xref: /Universal-ctags/parsers/verilog.c (revision 46313f460f7c57588df5217354db1556fe155f26)
13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO  *   Copyright (c) 2003, Darren Hiebert
3d2ca41cdSHiroo HAYASHI  *   Copyright (c) 2017, Vitor Antunes
4d2ca41cdSHiroo HAYASHI  *   Copyright (c) 2020, Hiroo Hayashi
53ae02089SMasatake YAMATO  *
63ae02089SMasatake YAMATO  *   This source code is released for free distribution under the terms of the
70ce38835Sviccuad  *   GNU General Public License version 2 or (at your option) any later version.
83ae02089SMasatake YAMATO  *
9d2ca41cdSHiroo HAYASHI  *   This module contains functions for generating tags for the Verilog or
10d2ca41cdSHiroo HAYASHI  *   SystemVerilog HDL (Hardware Description Language).
113ae02089SMasatake YAMATO  *
125a2b57ecSHiroo HAYASHI  *   References:
13d2ca41cdSHiroo HAYASHI  *       IEEE Std 1800-2017, SystemVerilog Language Reference Manual
14d2ca41cdSHiroo HAYASHI  *          https://ieeexplore.ieee.org/document/8299595
15d2ca41cdSHiroo HAYASHI  *       SystemVerilog IEEE Std 1800-2012 Grammer
16d2ca41cdSHiroo HAYASHI  *          https://insights.sigasi.com/tech/systemverilog.ebnf/
17d2ca41cdSHiroo HAYASHI  *       Verilog Formal Syntax Specification
183ae02089SMasatake YAMATO  *          http://www.verilog.com/VerilogBNF.html
193ae02089SMasatake YAMATO  */
203ae02089SMasatake YAMATO 
213ae02089SMasatake YAMATO /*
223ae02089SMasatake YAMATO  *   INCLUDE FILES
233ae02089SMasatake YAMATO  */
243ae02089SMasatake YAMATO #include "general.h"  /* must always come first */
253ae02089SMasatake YAMATO 
263ae02089SMasatake YAMATO #include <string.h>
273ae02089SMasatake YAMATO 
283ae02089SMasatake YAMATO #include "debug.h"
2914781660SMasatake YAMATO #include "entry.h"
303ae02089SMasatake YAMATO #include "keyword.h"
313ae02089SMasatake YAMATO #include "options.h"
323ae02089SMasatake YAMATO #include "parse.h"
333ae02089SMasatake YAMATO #include "read.h"
343ae02089SMasatake YAMATO #include "routines.h"
3535c59e96SMasatake YAMATO #include "xtag.h"
36462ef99aSMasatake YAMATO #include "ptrarray.h"
373ae02089SMasatake YAMATO 
383ae02089SMasatake YAMATO /*
393ae02089SMasatake YAMATO  *   MACROS
403ae02089SMasatake YAMATO  */
413ae02089SMasatake YAMATO #define NUMBER_LANGUAGES    2   /* Indicates number of defined indexes */
423ae02089SMasatake YAMATO #define IDX_SYSTEMVERILOG   0
433ae02089SMasatake YAMATO #define IDX_VERILOG         1
443ae02089SMasatake YAMATO 
453ae02089SMasatake YAMATO /*
463ae02089SMasatake YAMATO  *   DATA DECLARATIONS
473ae02089SMasatake YAMATO  */
4823297f61SMasatake YAMATO 
4923297f61SMasatake YAMATO /* A callback function searching a symbol from the cork symbol table assumes
5023297f61SMasatake YAMATO  * this kind definitions are shared in Verilog and SystemVerilog parsers.
5123297f61SMasatake YAMATO  * If you will separate the definitions for the parsers, you must revise the
5223297f61SMasatake YAMATO  * code related to the symbol table. */
533ae02089SMasatake YAMATO typedef enum {
547bcee217SHiroo HAYASHI 	/* parser private items */
55612ee934SHiroo HAYASHI 	K_IGNORE = -16,	/* Verilog/SystemVerilog keywords to be ignored */
567bcee217SHiroo HAYASHI 	K_DEFINE,
57d6b72e60SHiroo HAYASHI 	K_DIRECTIVE,
58286499bbSHiroo HAYASHI 	K_END,
5923bc0b7aSHiroo HAYASHI 	K_END_DE,	/* End of Design Elements */
608ccc1123SHiroo HAYASHI 	K_IDENTIFIER,
612e2a1af9SHiroo HAYASHI 	K_LOCALPARAM,
622e2a1af9SHiroo HAYASHI 	K_PARAMETER,
638e46c07bSHiroo HAYASHI 	K_IMPORT,
64977cdf27SHiroo HAYASHI 	K_WITH,
657bcee217SHiroo HAYASHI 
667bcee217SHiroo HAYASHI 	K_UNDEFINED = KEYWORD_NONE,
677bcee217SHiroo HAYASHI 	/* the followings items are also used as indices for VerilogKinds[] and SystemVerilogKinds[] */
687bcee217SHiroo HAYASHI 	K_CONSTANT= 0,
693ae02089SMasatake YAMATO 	K_EVENT,
703ae02089SMasatake YAMATO 	K_FUNCTION,
713ae02089SMasatake YAMATO 	K_MODULE,
723ae02089SMasatake YAMATO 	K_NET,
733ae02089SMasatake YAMATO 	K_PORT,
743ae02089SMasatake YAMATO 	K_REGISTER,
753ae02089SMasatake YAMATO 	K_TASK,
763ae02089SMasatake YAMATO 	K_BLOCK,
7705f57079Sheyun 	K_INSTANCE,
783ae02089SMasatake YAMATO 	K_ASSERTION,
793ae02089SMasatake YAMATO 	K_CLASS,
803ae02089SMasatake YAMATO 	K_COVERGROUP,
819a433176SVitor Antunes 	K_ENUM,
823ae02089SMasatake YAMATO 	K_INTERFACE,
833ae02089SMasatake YAMATO 	K_MODPORT,
843ae02089SMasatake YAMATO 	K_PACKAGE,
853ae02089SMasatake YAMATO 	K_PROGRAM,
8696047d1aSVitor Antunes 	K_PROTOTYPE,
873ae02089SMasatake YAMATO 	K_PROPERTY,
889a433176SVitor Antunes 	K_STRUCT,
892c5421aaSHiroo HAYASHI 	K_TYPEDEF,
902c5421aaSHiroo HAYASHI 	K_CHECKER,
912c5421aaSHiroo HAYASHI 	K_CLOCKING,
9231730736SHiroo HAYASHI 	K_SEQUENCE,
93b762e2b6SHiroo HAYASHI 	K_MEMBER,
94d6db2d3cSHiroo HAYASHI 	K_IFCLASS,	/* interface class */
95d6db2d3cSHiroo HAYASHI 	K_CONSTRAINT,
96d8576f6dSHiroo HAYASHI 	K_NETTYPE,
973ae02089SMasatake YAMATO } verilogKind;
983ae02089SMasatake YAMATO 
993ae02089SMasatake YAMATO typedef struct {
1003ae02089SMasatake YAMATO 	const char *keyword;
1013ae02089SMasatake YAMATO 	verilogKind kind;
1023ae02089SMasatake YAMATO 	short isValid [NUMBER_LANGUAGES];
1033ae02089SMasatake YAMATO } keywordAssoc;
1043ae02089SMasatake YAMATO 
1053ae02089SMasatake YAMATO typedef struct sTokenInfo {
1063ae02089SMasatake YAMATO 	verilogKind         kind;
1073ae02089SMasatake YAMATO 	vString*            name;          /* the name of the token */
1083ae02089SMasatake YAMATO 	unsigned long       lineNumber;    /* line number where token was found */
109509a47dbSJiří Techet 	MIOPos              filePosition;  /* file position where token was found */
1103ae02089SMasatake YAMATO 	struct sTokenInfo*  scope;         /* context of keyword */
1113ae02089SMasatake YAMATO 	int                 nestLevel;     /* Current nest level */
1123ae02089SMasatake YAMATO 	verilogKind         lastKind;      /* Kind of last found tag */
1133ae02089SMasatake YAMATO 	vString*            blockName;     /* Current block name */
1143ae02089SMasatake YAMATO 	vString*            inheritance;   /* Class inheritance */
115ce990805SThomas Braun 	bool                prototype;     /* Is only a prototype */
116ce990805SThomas Braun 	bool                classScope;    /* Context is local to the current sub-context */
1172e2a1af9SHiroo HAYASHI 	bool				parameter;	   /* parameter which can be overridden */
118af35bd7cSHiroo HAYASHI 	bool				hasParamList;  /* module definition has a parameter port list */
1193ae02089SMasatake YAMATO } tokenInfo;
1203ae02089SMasatake YAMATO 
1212e2a1af9SHiroo HAYASHI typedef enum {
122af35bd7cSHiroo HAYASHI 	F_PARAMETER,
1232e2a1af9SHiroo HAYASHI } verilogField;
1242e2a1af9SHiroo HAYASHI 
1253ae02089SMasatake YAMATO /*
1263ae02089SMasatake YAMATO  *   DATA DEFINITIONS
1273ae02089SMasatake YAMATO  */
1283ae02089SMasatake YAMATO static int Ungetc;
1293ae02089SMasatake YAMATO static int Lang_verilog;
1303ae02089SMasatake YAMATO static int Lang_systemverilog;
1313ae02089SMasatake YAMATO 
132e112e8abSMasatake YAMATO static kindDefinition VerilogKinds [] = {
133ce990805SThomas Braun  { true, 'c', "constant",  "constants (define, parameter, specparam)" },
134ce990805SThomas Braun  { true, 'e', "event",     "events" },
135ce990805SThomas Braun  { true, 'f', "function",  "functions" },
136ce990805SThomas Braun  { true, 'm', "module",    "modules" },
137ce990805SThomas Braun  { true, 'n', "net",       "net data types" },
138ce990805SThomas Braun  { true, 'p', "port",      "ports" },
1392c5421aaSHiroo HAYASHI  { true, 'r', "register",  "variable data types" },
140ce990805SThomas Braun  { true, 't', "task",      "tasks" },
14105f57079Sheyun  { true, 'b', "block",     "blocks (begin, fork)" },
14283214f95SHiroo HAYASHI  { true, 'i', "instance",  "instances of module" },
1433ae02089SMasatake YAMATO };
1443ae02089SMasatake YAMATO 
145e112e8abSMasatake YAMATO static kindDefinition SystemVerilogKinds [] = {
1469a433176SVitor Antunes  { true, 'c', "constant",  "constants (define, parameter, specparam, enum values)" },
147ce990805SThomas Braun  { true, 'e', "event",     "events" },
148ce990805SThomas Braun  { true, 'f', "function",  "functions" },
149ce990805SThomas Braun  { true, 'm', "module",    "modules" },
150ce990805SThomas Braun  { true, 'n', "net",       "net data types" },
151ce990805SThomas Braun  { true, 'p', "port",      "ports" },
1522c5421aaSHiroo HAYASHI  { true, 'r', "register",  "variable data types" },
153ce990805SThomas Braun  { true, 't', "task",      "tasks" },
1544aaf731aSHiroo HAYASHI  { true, 'b', "block",     "blocks (begin, fork)" },
15558caa39dSHiroo HAYASHI  { true, 'i', "instance",  "instances of module or interface" },
1564aaf731aSHiroo HAYASHI  { true, 'A', "assert",    "assertions (assert, assume, cover, restrict)" },
157ce990805SThomas Braun  { true, 'C', "class",     "classes" },
158ce990805SThomas Braun  { true, 'V', "covergroup","covergroups" },
1599a433176SVitor Antunes  { true, 'E', "enum",      "enumerators" },
160ce990805SThomas Braun  { true, 'I', "interface", "interfaces" },
161ce990805SThomas Braun  { true, 'M', "modport",   "modports" },
162ce990805SThomas Braun  { true, 'K', "package",   "packages" },
163ce990805SThomas Braun  { true, 'P', "program",   "programs" },
1644aaf731aSHiroo HAYASHI  { false,'Q', "prototype", "prototypes (extern, pure)" },
165ce990805SThomas Braun  { true, 'R', "property",  "properties" },
1669a433176SVitor Antunes  { true, 'S', "struct",    "structs and unions" },
1672c5421aaSHiroo HAYASHI  { true, 'T', "typedef",   "type declarations" },
1682c5421aaSHiroo HAYASHI  { true, 'H', "checker",   "checkers" },
1692c5421aaSHiroo HAYASHI  { true, 'L', "clocking",  "clocking" },
17031730736SHiroo HAYASHI  { true, 'q', "sequence",  "sequences" },
171b762e2b6SHiroo HAYASHI  { true, 'w', "member",    "struct and union members" },
17283214f95SHiroo HAYASHI  { true, 'l', "ifclass",   "interface class" },
173d6db2d3cSHiroo HAYASHI  { true, 'O', "constraint","constraints" },
174d8576f6dSHiroo HAYASHI  { true, 'N', "nettype",   "nettype declarations" },
1753ae02089SMasatake YAMATO };
1763ae02089SMasatake YAMATO 
1773ae02089SMasatake YAMATO static const keywordAssoc KeywordTable [] = {
1783ae02089SMasatake YAMATO 	/*                 	             	  SystemVerilog */
1793ae02089SMasatake YAMATO 	/*                 	             	  |  Verilog    */
1803ae02089SMasatake YAMATO 	/* keyword         	keyword ID   	  |  |          */
1817bcee217SHiroo HAYASHI 	{ "`define",       	K_DEFINE,   	{ 1, 1 } },
1824aaf731aSHiroo HAYASHI 	{ "begin",         	K_BLOCK,     	{ 1, 1 } },
183286499bbSHiroo HAYASHI 	{ "end",           	K_END,       	{ 1, 1 } },
18423bc0b7aSHiroo HAYASHI 	{ "endfunction",   	K_END_DE,    	{ 1, 1 } },
18523bc0b7aSHiroo HAYASHI 	{ "endmodule",     	K_END_DE,    	{ 1, 1 } },
18623bc0b7aSHiroo HAYASHI 	{ "endtask",       	K_END_DE,    	{ 1, 1 } },
1870b0f1255SHiroo HAYASHI 	{ "event",         	K_EVENT,     	{ 1, 1 } },
1884aaf731aSHiroo HAYASHI 	{ "fork",          	K_BLOCK,     	{ 1, 1 } },
1890b0f1255SHiroo HAYASHI 	{ "function",      	K_FUNCTION,  	{ 1, 1 } },
1900b0f1255SHiroo HAYASHI 	{ "genvar",        	K_REGISTER,  	{ 1, 1 } },
1910b0f1255SHiroo HAYASHI 	{ "inout",         	K_PORT,      	{ 1, 1 } },
1920b0f1255SHiroo HAYASHI 	{ "input",         	K_PORT,      	{ 1, 1 } },
1930b0f1255SHiroo HAYASHI 	{ "integer",       	K_REGISTER,  	{ 1, 1 } },
1940b0f1255SHiroo HAYASHI 	{ "join",          	K_END,       	{ 1, 1 } },
1952e2a1af9SHiroo HAYASHI 	{ "localparam",    	K_LOCALPARAM,  	{ 1, 1 } },
1960b0f1255SHiroo HAYASHI 	{ "module",        	K_MODULE,    	{ 1, 1 } },
1970b0f1255SHiroo HAYASHI 	{ "output",        	K_PORT,      	{ 1, 1 } },
1982e2a1af9SHiroo HAYASHI 	{ "parameter",     	K_PARAMETER,  	{ 1, 1 } },
1990b0f1255SHiroo HAYASHI 	{ "real",          	K_REGISTER,  	{ 1, 1 } },
2000b0f1255SHiroo HAYASHI 	{ "realtime",      	K_REGISTER,  	{ 1, 1 } },
2010b0f1255SHiroo HAYASHI 	{ "reg",           	K_REGISTER,  	{ 1, 1 } },
2023ae02089SMasatake YAMATO 	{ "signed",        	K_IGNORE,    	{ 1, 1 } },
2030b0f1255SHiroo HAYASHI 	{ "specparam",     	K_CONSTANT,  	{ 1, 1 } },
2040b0f1255SHiroo HAYASHI 	{ "supply0",       	K_NET,       	{ 1, 1 } },
2050b0f1255SHiroo HAYASHI 	{ "supply1",       	K_NET,       	{ 1, 1 } },
2060b0f1255SHiroo HAYASHI 	{ "task",          	K_TASK,      	{ 1, 1 } },
2070b0f1255SHiroo HAYASHI 	{ "time",          	K_REGISTER,  	{ 1, 1 } },
2080b0f1255SHiroo HAYASHI 	{ "tri",           	K_NET,       	{ 1, 1 } },
2090b0f1255SHiroo HAYASHI 	{ "triand",        	K_NET,       	{ 1, 1 } },
2100b0f1255SHiroo HAYASHI 	{ "trior",         	K_NET,       	{ 1, 1 } },
2110b0f1255SHiroo HAYASHI 	{ "trireg",        	K_NET,       	{ 1, 1 } },
2120b0f1255SHiroo HAYASHI 	{ "tri0",          	K_NET,       	{ 1, 1 } },
2130b0f1255SHiroo HAYASHI 	{ "tri1",          	K_NET,       	{ 1, 1 } },
2140b0f1255SHiroo HAYASHI 	{ "uwire",         	K_NET,       	{ 1, 1 } },
2150b0f1255SHiroo HAYASHI 	{ "wand",          	K_NET,       	{ 1, 1 } },
2160b0f1255SHiroo HAYASHI 	{ "wire",          	K_NET,       	{ 1, 1 } },
2170b0f1255SHiroo HAYASHI 	{ "wor",           	K_NET,       	{ 1, 1 } },
2183ae02089SMasatake YAMATO 	{ "assert",        	K_ASSERTION, 	{ 1, 0 } },
2193ae02089SMasatake YAMATO 	{ "assume",        	K_ASSERTION, 	{ 1, 0 } },
2203ae02089SMasatake YAMATO 	{ "bit",           	K_REGISTER,  	{ 1, 0 } },
2213ae02089SMasatake YAMATO 	{ "byte",          	K_REGISTER,  	{ 1, 0 } },
222c635353dSHiroo HAYASHI 	{ "chandle",       	K_REGISTER,  	{ 1, 0 } },
2232c5421aaSHiroo HAYASHI 	{ "checker",       	K_CHECKER,  	{ 1, 0 } },
2243ae02089SMasatake YAMATO 	{ "class",         	K_CLASS,     	{ 1, 0 } },
225d6db2d3cSHiroo HAYASHI 	{ "constraint",   	K_CONSTRAINT, 	{ 1, 0 } },
2263ae02089SMasatake YAMATO 	{ "cover",         	K_ASSERTION, 	{ 1, 0 } },
2272c5421aaSHiroo HAYASHI 	{ "clocking",       K_CLOCKING,     { 1, 0 } },
2283ae02089SMasatake YAMATO 	{ "covergroup",    	K_COVERGROUP,	{ 1, 0 } },
2292c5421aaSHiroo HAYASHI 	{ "endchecker",    	K_END_DE,    	{ 1, 0 } },
23023bc0b7aSHiroo HAYASHI 	{ "endclass",      	K_END_DE,    	{ 1, 0 } },
2312c5421aaSHiroo HAYASHI 	{ "endclocking",    K_END_DE,     	{ 1, 0 } },
23223bc0b7aSHiroo HAYASHI 	{ "endgroup",      	K_END_DE,    	{ 1, 0 } },
23323bc0b7aSHiroo HAYASHI 	{ "endinterface",  	K_END_DE,    	{ 1, 0 } },
23423bc0b7aSHiroo HAYASHI 	{ "endpackage",    	K_END_DE,    	{ 1, 0 } },
23523bc0b7aSHiroo HAYASHI 	{ "endprogram",    	K_END_DE,    	{ 1, 0 } },
23623bc0b7aSHiroo HAYASHI 	{ "endproperty",   	K_END_DE,    	{ 1, 0 } },
2372c5421aaSHiroo HAYASHI 	{ "endsequence",   	K_END_DE,    	{ 1, 0 } },
2389a433176SVitor Antunes 	{ "enum",          	K_ENUM,      	{ 1, 0 } },
23969e311feSHiroo HAYASHI 	{ "extern",        	K_PROTOTYPE, 	{ 1, 0 } },
2408e46c07bSHiroo HAYASHI 	{ "import",        	K_IMPORT,	  	{ 1, 0 } },
2413ae02089SMasatake YAMATO 	{ "int",           	K_REGISTER,  	{ 1, 0 } },
2420b0f1255SHiroo HAYASHI 	{ "interconnect",  	K_NET,       	{ 1, 0 } },
2433ae02089SMasatake YAMATO 	{ "interface",     	K_INTERFACE, 	{ 1, 0 } },
2441e1b1e95SHiroo HAYASHI 	{ "join_any",      	K_END,       	{ 1, 0 } },
2451e1b1e95SHiroo HAYASHI 	{ "join_none",     	K_END,       	{ 1, 0 } },
2463ae02089SMasatake YAMATO 	{ "logic",         	K_REGISTER,  	{ 1, 0 } },
2473ae02089SMasatake YAMATO 	{ "longint",       	K_REGISTER,  	{ 1, 0 } },
2483ae02089SMasatake YAMATO 	{ "modport",       	K_MODPORT,   	{ 1, 0 } },
2493ae02089SMasatake YAMATO 	{ "package",       	K_PACKAGE,   	{ 1, 0 } },
2503ae02089SMasatake YAMATO 	{ "program",       	K_PROGRAM,   	{ 1, 0 } },
2513ae02089SMasatake YAMATO 	{ "property",      	K_PROPERTY,  	{ 1, 0 } },
25269e311feSHiroo HAYASHI 	{ "pure",          	K_PROTOTYPE, 	{ 1, 0 } },
253279330eeSVitor Antunes 	{ "ref",           	K_PORT,      	{ 1, 0 } },
2542c5421aaSHiroo HAYASHI 	{ "restrict",      	K_ASSERTION, 	{ 1, 0 } },
2552c5421aaSHiroo HAYASHI 	{ "sequence",      	K_SEQUENCE,  	{ 1, 0 } },
2563ae02089SMasatake YAMATO 	{ "shortint",      	K_REGISTER,  	{ 1, 0 } },
2573ae02089SMasatake YAMATO 	{ "shortreal",     	K_REGISTER,  	{ 1, 0 } },
2583ae02089SMasatake YAMATO 	{ "string",        	K_REGISTER,  	{ 1, 0 } },
2599a433176SVitor Antunes 	{ "struct",        	K_STRUCT,    	{ 1, 0 } },
2600b0f1255SHiroo HAYASHI 	{ "type",          	K_REGISTER,  	{ 1, 0 } },
2613ae02089SMasatake YAMATO 	{ "typedef",       	K_TYPEDEF,   	{ 1, 0 } },
2629a433176SVitor Antunes 	{ "union",         	K_STRUCT,    	{ 1, 0 } },
263c635353dSHiroo HAYASHI 	{ "var",           	K_REGISTER,  	{ 1, 0 } },
264977cdf27SHiroo HAYASHI 	{ "void",          	K_REGISTER,  	{ 1, 0 } },
26583214f95SHiroo HAYASHI 	{ "with",          	K_WITH,			{ 1, 0 } },
266d8576f6dSHiroo HAYASHI 	{ "nettype",       	K_NETTYPE,		{ 1, 0 } },
267e1d64241SHiroo HAYASHI //	{ "virtual",       	K_PROTOTYPE,	{ 1, 0 } },		// do not add for now
2683ae02089SMasatake YAMATO };
2693ae02089SMasatake YAMATO 
2703ae02089SMasatake YAMATO static tokenInfo *currentContext = NULL;
271462ef99aSMasatake YAMATO static ptrArray *tagContents;
272af35bd7cSHiroo HAYASHI static fieldDefinition *fieldTable = NULL;
2733ae02089SMasatake YAMATO 
274612ee934SHiroo HAYASHI // IEEE Std 1364-2005 LRM, Appendix B "List of Keywords"
27548e38ee2SMasatake YAMATO const static struct keywordGroup verilogKeywords = {
27648e38ee2SMasatake YAMATO 	.value = K_IGNORE,
27748e38ee2SMasatake YAMATO 	.addingUnlessExisting = true,
27848e38ee2SMasatake YAMATO 	.keywords = {
279612ee934SHiroo HAYASHI 		"always", "and", "assign", "automatic", "begin", "buf", "bufif0",
280612ee934SHiroo HAYASHI 		"bufif1", "case", "casex", "casez", "cell", "cmos", "config",
281612ee934SHiroo HAYASHI 		"deassign", "default", "defparam", "design", "disable", "edge",
282612ee934SHiroo HAYASHI 		"else", "end", "endcase", "endconfig", "endfunction", "endgenerate",
283612ee934SHiroo HAYASHI 		"endmodule", "endprimitive", "endspecify", "endtable", "endtask",
284612ee934SHiroo HAYASHI 		"event", "for", "force", "forever", "fork", "function", "generate",
285612ee934SHiroo HAYASHI 		"genvar", "highz0", "highz1", "if", "ifnone", "incdir", "include",
286612ee934SHiroo HAYASHI 		"initial", "inout", "input", "instance", "integer", "join", "large",
287612ee934SHiroo HAYASHI 		"liblist", "library", "localparam", "macromodule", "medium", "module",
288612ee934SHiroo HAYASHI 		"nand", "negedge", "nmos", "nor", "noshowcancelled", "not", "notif0",
289612ee934SHiroo HAYASHI 		"notif1", "or", "output", "parameter", "pmos", "posedge", "primitive",
290612ee934SHiroo HAYASHI 		"pull0", "pull1", "pulldown", "pullup", "pulsestyle_onevent",
291612ee934SHiroo HAYASHI 		"pulsestyle_ondetect", "rcmos", "real", "realtime", "reg", "release",
292612ee934SHiroo HAYASHI 		"repeat", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1",
293612ee934SHiroo HAYASHI 		"scalared", "showcancelled", "signed", "small", "specify",
294612ee934SHiroo HAYASHI 		"specparam", "strong0", "strong1", "supply0", "supply1", "table",
295612ee934SHiroo HAYASHI 		"task", "time", "tran", "tranif0", "tranif1", "tri", "tri0", "tri1",
296612ee934SHiroo HAYASHI 		"triand", "trior", "trireg", "unsigned1", "use", "uwire", "vectored",
29748e38ee2SMasatake YAMATO 		"wait", "wand", "weak0", "weak1", "while", "wire", "wor", "xnor", "xor",
29848e38ee2SMasatake YAMATO 		NULL
29948e38ee2SMasatake YAMATO 	},
300612ee934SHiroo HAYASHI };
301612ee934SHiroo HAYASHI // IEEE Std 1800-2017 LRM, Annex B "Keywords"
30248e38ee2SMasatake YAMATO const static struct keywordGroup systemVerilogKeywords = {
30348e38ee2SMasatake YAMATO 	.value = K_IGNORE,
30448e38ee2SMasatake YAMATO 	.addingUnlessExisting = true,
30548e38ee2SMasatake YAMATO 	.keywords = {
306612ee934SHiroo HAYASHI 		"accept_on", "alias", "always", "always_comb", "always_ff",
307612ee934SHiroo HAYASHI 		"always_latch", "and", "assert", "assign", "assume", "automatic",
308612ee934SHiroo HAYASHI 		"before", "begin", "bind", "bins", "binsof", "bit", "break", "buf",
309612ee934SHiroo HAYASHI 		"bufif0", "bufif1", "byte", "case", "casex", "casez", "cell",
310612ee934SHiroo HAYASHI 		"chandle", "checker", "class", "clocking", "cmos", "config", "const",
311612ee934SHiroo HAYASHI 		"constraint", "context", "continue", "cover", "covergroup",
312612ee934SHiroo HAYASHI 		"coverpoint", "cross", "deassign", "default", "defparam", "design",
313612ee934SHiroo HAYASHI 		"disable", "dist", "do", "edge", "else", "end", "endcase",
314612ee934SHiroo HAYASHI 		"endchecker", "endclass", "endclocking", "endconfig", "endfunction",
315612ee934SHiroo HAYASHI 		"endgenerate", "endgroup", "endinterface", "endmodule", "endpackage",
316612ee934SHiroo HAYASHI 		"endprimitive", "endprogram", "endproperty", "endspecify",
317612ee934SHiroo HAYASHI 		"endsequence", "endtable", "endtask", "enum", "event", "eventually",
318612ee934SHiroo HAYASHI 		"expect", "export", "extends", "extern", "final", "first_match",
319612ee934SHiroo HAYASHI 		"for", "force", "foreach", "forever", "fork", "forkjoin", "function",
320612ee934SHiroo HAYASHI 		"generate", "genvar", "global", "highz0", "highz1", "if", "iff",
321612ee934SHiroo HAYASHI 		"ifnone", "ignore_bins", "illegal_bins", "implements", "implies",
322612ee934SHiroo HAYASHI 		"import", "incdir", "include", "initial", "inout", "input", "inside",
323612ee934SHiroo HAYASHI 		"instance", "int", "integer", "interconnect", "interface",
324612ee934SHiroo HAYASHI 		"intersect", "join", "join_any", "join_none", "large", "let",
325612ee934SHiroo HAYASHI 		"liblist", "library", "local", "localparam", "logic", "longint",
326612ee934SHiroo HAYASHI 		"macromodule", "matches", "medium", "modport", "module", "nand",
327612ee934SHiroo HAYASHI 		"negedge", "nettype", "new", "nexttime", "nmos", "nor",
328612ee934SHiroo HAYASHI 		"noshowcancelled", "not", "notif0", "notif1", "null", "or", "output",
329612ee934SHiroo HAYASHI 		"package", "packed", "parameter", "pmos", "posedge", "primitive",
330612ee934SHiroo HAYASHI 		"priority", "program", "property", "protected", "pull0", "pull1",
331612ee934SHiroo HAYASHI 		"pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent",
332612ee934SHiroo HAYASHI 		"pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real",
333612ee934SHiroo HAYASHI 		"realtime", "ref", "reg", "reject_on", "release", "repeat",
334612ee934SHiroo HAYASHI 		"restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0",
335612ee934SHiroo HAYASHI 		"rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until",
336612ee934SHiroo HAYASHI 		"s_until_with", "scalared", "sequence", "shortint", "shortreal",
337612ee934SHiroo HAYASHI 		"showcancelled", "signed", "small", "soft", "solve", "specify",
338612ee934SHiroo HAYASHI 		"specparam", "static", "string", "strong", "strong0", "strong1",
339612ee934SHiroo HAYASHI 		"struct", "super", "supply0", "supply1", "sync_accept_on",
340612ee934SHiroo HAYASHI 		"sync_reject_on", "table", "tagged", "task", "this", "throughout",
341612ee934SHiroo HAYASHI 		"time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1",
342612ee934SHiroo HAYASHI 		"tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef",
343612ee934SHiroo HAYASHI 		"union", "unique", "unique0", "unsigned", "until", "until_with",
344612ee934SHiroo HAYASHI 		"untyped", "use", "uwire", "var", "vectored", "virtual", "void",
345612ee934SHiroo HAYASHI 		"wait", "wait_order", "wand", "weak", "weak0", "weak1", "while",
34648e38ee2SMasatake YAMATO 		"wildcard", "wire", "with", "within", "wor", "xnor", "xor",
34748e38ee2SMasatake YAMATO 		NULL
34848e38ee2SMasatake YAMATO 	},
349612ee934SHiroo HAYASHI };
350612ee934SHiroo HAYASHI 
351d6b72e60SHiroo HAYASHI // IEEE Std 1364-2005 LRM, "19. Compiler directives"
352d6b72e60SHiroo HAYASHI const static struct keywordGroup verilogDirectives = {
353d6b72e60SHiroo HAYASHI 	.value = K_DIRECTIVE,
354d6b72e60SHiroo HAYASHI 	.addingUnlessExisting = true,
355d6b72e60SHiroo HAYASHI 	.keywords = {
356d6b72e60SHiroo HAYASHI 		"`begin_keywords", "`celldefine", "`default_nettype", "`define",
357d6b72e60SHiroo HAYASHI 		"`else", "`elsif", "`end_keywords", "`endcelldefine", "`endif",
358d6b72e60SHiroo HAYASHI 		"`ifdef", "`ifndef", "`include", "`line", "`nounconnected_drive",
359d6b72e60SHiroo HAYASHI 		"`pragma", "`resetall", "`timescale", "`unconnected_drive", "`undef",
360d6b72e60SHiroo HAYASHI 		NULL
361d6b72e60SHiroo HAYASHI 	},
362d6b72e60SHiroo HAYASHI };
363d6b72e60SHiroo HAYASHI 
364d6b72e60SHiroo HAYASHI // IEEE Std 1800-2017 LRM, "22. Compiler directives"
365d6b72e60SHiroo HAYASHI const static struct keywordGroup systemVerilogDirectives = {
366d6b72e60SHiroo HAYASHI 	.value = K_DIRECTIVE,
367d6b72e60SHiroo HAYASHI 	.addingUnlessExisting = true,
368d6b72e60SHiroo HAYASHI 	.keywords = {
369d6b72e60SHiroo HAYASHI 		"`__LINE__", "`begin_keywords", "`celldefine", "`default_nettype",
370d6b72e60SHiroo HAYASHI 		"`define", "`else", "`elsif", "`end_keywords", "`endcelldefine",
371d6b72e60SHiroo HAYASHI 		"`endif", "`ifdef", "`ifndef", "`include", "`line",
372d6b72e60SHiroo HAYASHI 		"`nounconnected_drive", "`pragma", "`resetall", "`timescale",
373d6b72e60SHiroo HAYASHI 		"`unconnected_drive", "`undef", "`undefineall",
374d6b72e60SHiroo HAYASHI 		NULL
375d6b72e60SHiroo HAYASHI 	},
376d6b72e60SHiroo HAYASHI };
377d6b72e60SHiroo HAYASHI 
378af35bd7cSHiroo HAYASHI // .enabled field cannot be shared by two languages
3792e2a1af9SHiroo HAYASHI static fieldDefinition VerilogFields[] = {
380af35bd7cSHiroo HAYASHI 	{ .name = "parameter",
381af35bd7cSHiroo HAYASHI 	  .description = "parameter whose value can be overridden.",
382af35bd7cSHiroo HAYASHI 	  .enabled = false,
383af35bd7cSHiroo HAYASHI 	  .dataType = FIELDTYPE_BOOL },
384af35bd7cSHiroo HAYASHI };
385af35bd7cSHiroo HAYASHI 
386af35bd7cSHiroo HAYASHI static fieldDefinition SystemVerilogFields[] = {
387af35bd7cSHiroo HAYASHI 	{ .name = "parameter",
388af35bd7cSHiroo HAYASHI 	  .description = "parameter whose value can be overridden.",
389af35bd7cSHiroo HAYASHI 	  .enabled = false,
390af35bd7cSHiroo HAYASHI 	  .dataType = FIELDTYPE_BOOL },
3912e2a1af9SHiroo HAYASHI };
3922e2a1af9SHiroo HAYASHI 
3933ae02089SMasatake YAMATO /*
3947bbbffbcSHiroo HAYASHI  *   PROTOTYPE DEFINITIONS
3957bbbffbcSHiroo HAYASHI  */
3967bbbffbcSHiroo HAYASHI 
397b67a1035SHiroo HAYASHI static bool isIdentifier (tokenInfo* token);
398336b0d0dSHiroo HAYASHI static int processDefine (tokenInfo *const token, int c);
399a6f873e6SHiroo HAYASHI static int processType (tokenInfo* token, int c, verilogKind* kind, bool* with);
400de5b45a8SHiroo HAYASHI static int pushEnumNames (tokenInfo* token, int c);
40131730736SHiroo HAYASHI static int pushMembers (tokenInfo* token, int c);
402bd7f3072SHiroo HAYASHI static int readWordToken (tokenInfo *const token, int c);
403419aa5d0SHiroo HAYASHI static int readWordTokenNoSkip (tokenInfo *const token, int c);
40491b5c3fcSHiroo HAYASHI static int skipBlockName (tokenInfo *const token, int c);
4055b1c62e9SHiroo HAYASHI static int skipClockEvent (tokenInfo* token, int c);
4063087f342SHiroo HAYASHI static int skipDelay (tokenInfo* token, int c);
407622e7342SHiroo HAYASHI static int tagIdentifierList (tokenInfo *const token, int c, verilogKind kind, bool mayPortDecl);
408b449e8a0SHiroo HAYASHI static int tagNameList (tokenInfo* token, int c, verilogKind kind);
4097bbbffbcSHiroo HAYASHI 
4107bbbffbcSHiroo HAYASHI /*
4113ae02089SMasatake YAMATO  *   FUNCTION DEFINITIONS
4123ae02089SMasatake YAMATO  */
4133ae02089SMasatake YAMATO 
isContainer(verilogKind kind)414220345f7SHiroo HAYASHI static short isContainer (verilogKind kind)
4153ae02089SMasatake YAMATO {
416220345f7SHiroo HAYASHI 	switch (kind)
4173ae02089SMasatake YAMATO 	{
4183ae02089SMasatake YAMATO 		case K_MODULE:
4193ae02089SMasatake YAMATO 		case K_TASK:
4203ae02089SMasatake YAMATO 		case K_FUNCTION:
4213ae02089SMasatake YAMATO 		case K_BLOCK:
4222c5421aaSHiroo HAYASHI 		case K_CHECKER:
4233ae02089SMasatake YAMATO 		case K_CLASS:
424cd0963d9SHiroo HAYASHI 		case K_CLOCKING:
4253ae02089SMasatake YAMATO 		case K_COVERGROUP:
426b762e2b6SHiroo HAYASHI 		case K_IFCLASS:
4273ae02089SMasatake YAMATO 		case K_INTERFACE:
4283ae02089SMasatake YAMATO 		case K_PACKAGE:
4293ae02089SMasatake YAMATO 		case K_PROGRAM:
4303ae02089SMasatake YAMATO 		case K_PROPERTY:
4312c5421aaSHiroo HAYASHI 		case K_SEQUENCE:
4329a433176SVitor Antunes 		case K_TYPEDEF:
433d8576f6dSHiroo HAYASHI 		case K_NETTYPE:
4349a433176SVitor Antunes 		case K_ENUM:
43531730736SHiroo HAYASHI 		case K_STRUCT:
4369a433176SVitor Antunes 			return true;
4379a433176SVitor Antunes 		default:
4389a433176SVitor Antunes 			return false;
4399a433176SVitor Antunes 	}
4409a433176SVitor Antunes }
4419a433176SVitor Antunes 
isTempContext(tokenInfo const * token)4429a433176SVitor Antunes static short isTempContext (tokenInfo const* token)
4439a433176SVitor Antunes {
4449a433176SVitor Antunes 	switch (token->kind)
4459a433176SVitor Antunes 	{
4469a433176SVitor Antunes 		case K_TYPEDEF:
447d8576f6dSHiroo HAYASHI 		case K_NETTYPE:
4489a433176SVitor Antunes 		case K_ENUM:
44931730736SHiroo HAYASHI 		case K_STRUCT:
450ce990805SThomas Braun 			return true;
4513ae02089SMasatake YAMATO 		default:
452ce990805SThomas Braun 			return false;
4533ae02089SMasatake YAMATO 	}
4543ae02089SMasatake YAMATO }
4553ae02089SMasatake YAMATO 
clearToken(tokenInfo * token)45669de9ae1SHiroo HAYASHI static void clearToken (tokenInfo *token)
4573ae02089SMasatake YAMATO {
45869de9ae1SHiroo HAYASHI 	token->kind = K_UNDEFINED;	// to be set by updateKind()
45969de9ae1SHiroo HAYASHI 	vStringClear (token->name);
460a31b37dcSMasatake YAMATO 	token->lineNumber = getInputLineNumber ();
4613ae02089SMasatake YAMATO 	token->filePosition = getInputFilePosition ();
4623ae02089SMasatake YAMATO 	token->scope = NULL;
4633ae02089SMasatake YAMATO 	token->nestLevel = 0;
4643ae02089SMasatake YAMATO 	token->lastKind = K_UNDEFINED;
46569de9ae1SHiroo HAYASHI 	vStringClear (token->blockName);
46669de9ae1SHiroo HAYASHI 	vStringClear (token->inheritance);
467ce990805SThomas Braun 	token->prototype = false;
468ce990805SThomas Braun 	token->classScope = false;
4692e2a1af9SHiroo HAYASHI 	token->parameter = false;
470af35bd7cSHiroo HAYASHI 	token->hasParamList = false;
47169de9ae1SHiroo HAYASHI }
47269de9ae1SHiroo HAYASHI 
newToken(void)47369de9ae1SHiroo HAYASHI static tokenInfo *newToken (void)
47469de9ae1SHiroo HAYASHI {
47569de9ae1SHiroo HAYASHI 	tokenInfo *const token = xMalloc (1, tokenInfo);
47669de9ae1SHiroo HAYASHI 	token->name = vStringNew ();
47769de9ae1SHiroo HAYASHI 	token->blockName = vStringNew ();
47869de9ae1SHiroo HAYASHI 	token->inheritance = vStringNew ();
47969de9ae1SHiroo HAYASHI 	clearToken (token);
4803ae02089SMasatake YAMATO 	return token;
4813ae02089SMasatake YAMATO }
4823ae02089SMasatake YAMATO 
dupToken(tokenInfo * token)48369de9ae1SHiroo HAYASHI static tokenInfo *dupToken (tokenInfo *token)
48469de9ae1SHiroo HAYASHI {
48569de9ae1SHiroo HAYASHI 	tokenInfo *dup = newToken ();
48669de9ae1SHiroo HAYASHI 	tokenInfo tmp = *dup;	// save vStrings, name, blockName, and inheritance
48769de9ae1SHiroo HAYASHI 	*dup = *token;
48869de9ae1SHiroo HAYASHI 	// revert vStrings allocated for dup
48969de9ae1SHiroo HAYASHI 	dup->name = tmp.name;
49069de9ae1SHiroo HAYASHI 	dup->blockName = tmp.blockName;
49169de9ae1SHiroo HAYASHI 	dup->inheritance = tmp.inheritance;
49269de9ae1SHiroo HAYASHI 	// copy contents of vStrings
49369de9ae1SHiroo HAYASHI 	vStringCopy (dup->name, token->name);
49469de9ae1SHiroo HAYASHI 	vStringCopy (dup->blockName, token->blockName);
49569de9ae1SHiroo HAYASHI 	vStringCopy (dup->inheritance, token->inheritance);
49669de9ae1SHiroo HAYASHI 	return dup;
49769de9ae1SHiroo HAYASHI }
49869de9ae1SHiroo HAYASHI 
deleteToken(tokenInfo * const token)4993ae02089SMasatake YAMATO static void deleteToken (tokenInfo * const token)
5003ae02089SMasatake YAMATO {
5013ae02089SMasatake YAMATO 	if (token != NULL)
5023ae02089SMasatake YAMATO 	{
5033ae02089SMasatake YAMATO 		vStringDelete (token->name);
5043ae02089SMasatake YAMATO 		vStringDelete (token->blockName);
5053ae02089SMasatake YAMATO 		vStringDelete (token->inheritance);
5063ae02089SMasatake YAMATO 		eFree (token);
5073ae02089SMasatake YAMATO 	}
5083ae02089SMasatake YAMATO }
5093ae02089SMasatake YAMATO 
pushToken(tokenInfo * const token,tokenInfo * const tokenPush)5103ae02089SMasatake YAMATO static tokenInfo *pushToken (tokenInfo * const token, tokenInfo * const tokenPush)
5113ae02089SMasatake YAMATO {
5123ae02089SMasatake YAMATO 	tokenPush->scope = token;
5133ae02089SMasatake YAMATO 	return tokenPush;
5143ae02089SMasatake YAMATO }
5153ae02089SMasatake YAMATO 
popToken(tokenInfo * const token)5163ae02089SMasatake YAMATO static tokenInfo *popToken (tokenInfo * const token)
5173ae02089SMasatake YAMATO {
5183ae02089SMasatake YAMATO 	tokenInfo *localToken;
5193ae02089SMasatake YAMATO 	if (token != NULL)
5203ae02089SMasatake YAMATO 	{
5213ae02089SMasatake YAMATO 		localToken = token->scope;
5223ae02089SMasatake YAMATO 		deleteToken (token);
5233ae02089SMasatake YAMATO 		return localToken;
5243ae02089SMasatake YAMATO 	}
5253ae02089SMasatake YAMATO 	return NULL;
5263ae02089SMasatake YAMATO }
5273ae02089SMasatake YAMATO 
pruneTokens(tokenInfo * token)5283ae02089SMasatake YAMATO static void pruneTokens (tokenInfo * token)
5293ae02089SMasatake YAMATO {
530b0793354SHiroo HAYASHI 	while ((token = popToken (token)))
531b0793354SHiroo HAYASHI 		;
5323ae02089SMasatake YAMATO }
5333ae02089SMasatake YAMATO 
swapToken(tokenInfo * t0,tokenInfo * t1)5349a7cd5c2SHiroo HAYASHI static void swapToken (tokenInfo *t0, tokenInfo *t1)
5359a7cd5c2SHiroo HAYASHI {
5369a7cd5c2SHiroo HAYASHI 	tokenInfo tmp = *t0;
5379a7cd5c2SHiroo HAYASHI 	*t0 = *t1;
5389a7cd5c2SHiroo HAYASHI 	*t1 = tmp;
5399a7cd5c2SHiroo HAYASHI }
5409a7cd5c2SHiroo HAYASHI 
getNameForKind(const verilogKind kind)541f92e6bf2SMasatake YAMATO static const char *getNameForKind (const verilogKind kind)
5423ae02089SMasatake YAMATO {
5437d90c743SMasatake YAMATO 	if (isInputLanguage (Lang_systemverilog))
544f92e6bf2SMasatake YAMATO 		return (SystemVerilogKinds[kind]).name;
5457d90c743SMasatake YAMATO 	else /* isInputLanguage (Lang_verilog) */
546f92e6bf2SMasatake YAMATO 		return (VerilogKinds[kind]).name;
5473ae02089SMasatake YAMATO }
5483ae02089SMasatake YAMATO 
kindEnabled(const verilogKind kind)5494a95e4a5SColomban Wendling static char kindEnabled (const verilogKind kind)
5504a95e4a5SColomban Wendling {
5517d90c743SMasatake YAMATO 	if (isInputLanguage (Lang_systemverilog))
5524a95e4a5SColomban Wendling 		return SystemVerilogKinds[kind].enabled;
5537d90c743SMasatake YAMATO 	else /* isInputLanguage (Lang_verilog) */
5544a95e4a5SColomban Wendling 		return VerilogKinds[kind].enabled;
5554a95e4a5SColomban Wendling }
5564a95e4a5SColomban Wendling 
buildKeywordHash(const langType language,unsigned int idx)55748e38ee2SMasatake YAMATO static void buildKeywordHash (const langType language, unsigned int idx)
5583ae02089SMasatake YAMATO {
5593ae02089SMasatake YAMATO 	size_t i;
560158a3387SMasatake YAMATO 	const size_t count = ARRAY_SIZE (KeywordTable);
5613ae02089SMasatake YAMATO 	for (i = 0  ;  i < count  ;  ++i)
5623ae02089SMasatake YAMATO 	{
5633ae02089SMasatake YAMATO 		const keywordAssoc *p = &KeywordTable [i];
5643ae02089SMasatake YAMATO 		if (p->isValid [idx])
5653ae02089SMasatake YAMATO 			addKeyword (p->keyword, language, (int) p->kind);
5663ae02089SMasatake YAMATO 	}
567612ee934SHiroo HAYASHI }
56848e38ee2SMasatake YAMATO 
initializeVerilog(const langType language)5693ae02089SMasatake YAMATO static void initializeVerilog (const langType language)
5703ae02089SMasatake YAMATO {
5713ae02089SMasatake YAMATO 	Lang_verilog = language;
57248e38ee2SMasatake YAMATO 	buildKeywordHash (language, IDX_VERILOG);
573d6b72e60SHiroo HAYASHI 	addKeywordGroup (&verilogKeywords, language);
574d6b72e60SHiroo HAYASHI 	addKeywordGroup (&verilogDirectives, language);
575462ef99aSMasatake YAMATO 	if (tagContents == NULL)
576462ef99aSMasatake YAMATO 		tagContents = ptrArrayNew ((ptrArrayDeleteFunc)deleteToken);
577462ef99aSMasatake YAMATO 
5783ae02089SMasatake YAMATO }
5793ae02089SMasatake YAMATO 
initializeSystemVerilog(const langType language)5803ae02089SMasatake YAMATO static void initializeSystemVerilog (const langType language)
5813ae02089SMasatake YAMATO {
5823ae02089SMasatake YAMATO 	Lang_systemverilog = language;
58348e38ee2SMasatake YAMATO 	buildKeywordHash (language, IDX_SYSTEMVERILOG);
584d6b72e60SHiroo HAYASHI 	addKeywordGroup (&systemVerilogKeywords, language);
585d6b72e60SHiroo HAYASHI 	addKeywordGroup (&systemVerilogDirectives, language);
586462ef99aSMasatake YAMATO 	if (tagContents == NULL)
587462ef99aSMasatake YAMATO 		tagContents = ptrArrayNew ((ptrArrayDeleteFunc)deleteToken);
5883ae02089SMasatake YAMATO }
5893ae02089SMasatake YAMATO 
vUngetc(int c)5903ae02089SMasatake YAMATO static void vUngetc (int c)
5913ae02089SMasatake YAMATO {
5923ae02089SMasatake YAMATO 	Assert (Ungetc == '\0');
5933ae02089SMasatake YAMATO 	Ungetc = c;
5943ae02089SMasatake YAMATO }
5953ae02089SMasatake YAMATO 
596ebdbd8e2SK.Takata /* Mostly copied from cppSkipOverCComment() in cpreprocessor.c.
597557ece60SMasatake YAMATO  *
598557ece60SMasatake YAMATO  * cppSkipOverCComment() uses the internal ungetc buffer of
599557ece60SMasatake YAMATO  * CPreProcessor.  On the other hand, the Verilog parser uses
600557ece60SMasatake YAMATO  * getcFromInputFile() directly. getcFromInputFile() uses just
601557ece60SMasatake YAMATO  * another internal ungetc buffer. Using them mixed way will
602557ece60SMasatake YAMATO  * cause a trouble. */
verilogSkipOverCComment(void)603557ece60SMasatake YAMATO static int verilogSkipOverCComment (void)
604557ece60SMasatake YAMATO {
605557ece60SMasatake YAMATO 	int c =  getcFromInputFile ();
606557ece60SMasatake YAMATO 
607557ece60SMasatake YAMATO 	while (c != EOF)
608557ece60SMasatake YAMATO 	{
609557ece60SMasatake YAMATO 		if (c != '*')
610557ece60SMasatake YAMATO 			c = getcFromInputFile ();
611557ece60SMasatake YAMATO 		else
612557ece60SMasatake YAMATO 		{
613557ece60SMasatake YAMATO 			const int next = getcFromInputFile ();
614557ece60SMasatake YAMATO 
615557ece60SMasatake YAMATO 			if (next != '/')
616557ece60SMasatake YAMATO 				c = next;
617557ece60SMasatake YAMATO 			else
618557ece60SMasatake YAMATO 			{
619557ece60SMasatake YAMATO 				c = SPACE;  /* replace comment with space */
620557ece60SMasatake YAMATO 				break;
621557ece60SMasatake YAMATO 			}
622557ece60SMasatake YAMATO 		}
623557ece60SMasatake YAMATO 	}
624557ece60SMasatake YAMATO 	return c;
625557ece60SMasatake YAMATO }
626557ece60SMasatake YAMATO 
_vGetc(bool inSkipPastMatch)627bd01a12eSHiroo HAYASHI static int _vGetc (bool inSkipPastMatch)
6283ae02089SMasatake YAMATO {
6293ae02089SMasatake YAMATO 	int c;
6303ae02089SMasatake YAMATO 	if (Ungetc == '\0')
631018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
6323ae02089SMasatake YAMATO 	else
6333ae02089SMasatake YAMATO 	{
6343ae02089SMasatake YAMATO 		c = Ungetc;
6353ae02089SMasatake YAMATO 		Ungetc = '\0';
6363ae02089SMasatake YAMATO 	}
6373ae02089SMasatake YAMATO 	if (c == '/')
6383ae02089SMasatake YAMATO 	{
639018bce0bSMasatake YAMATO 		int c2 = getcFromInputFile ();
6403ae02089SMasatake YAMATO 		if (c2 == EOF)
6413ae02089SMasatake YAMATO 			return EOF;
6423ae02089SMasatake YAMATO 		else if (c2 == '/')  /* strip comment until end-of-line */
6433ae02089SMasatake YAMATO 		{
6443ae02089SMasatake YAMATO 			do
645018bce0bSMasatake YAMATO 				c = getcFromInputFile ();
6463ae02089SMasatake YAMATO 			while (c != '\n'  &&  c != EOF);
6473ae02089SMasatake YAMATO 		}
6483ae02089SMasatake YAMATO 		else if (c2 == '*')  /* strip block comment */
649557ece60SMasatake YAMATO 			c = verilogSkipOverCComment ();
6503ae02089SMasatake YAMATO 		else
65161f14fa5SMasatake YAMATO 			ungetcToInputFile (c2);
6523ae02089SMasatake YAMATO 	}
653decc8799SHiroo HAYASHI 	// replace a string with "@" only in skipPastMatch()
654decc8799SHiroo HAYASHI 	// because the string may contain parens, etc.
655decc8799SHiroo HAYASHI 	else if (inSkipPastMatch && c == '"')
6563ae02089SMasatake YAMATO 	{
6573ae02089SMasatake YAMATO 		int c2;
6583ae02089SMasatake YAMATO 		do
659018bce0bSMasatake YAMATO 			c2 = getcFromInputFile ();
6603ae02089SMasatake YAMATO 		while (c2 != '"'  &&  c2 != EOF);
6613ae02089SMasatake YAMATO 		c = '@';
6623ae02089SMasatake YAMATO 	}
6633ae02089SMasatake YAMATO 	return c;
6643ae02089SMasatake YAMATO }
6653ae02089SMasatake YAMATO 
vGetc(void)666bd01a12eSHiroo HAYASHI static int vGetc (void)
667bd01a12eSHiroo HAYASHI {
668bd01a12eSHiroo HAYASHI 	return _vGetc (false);
669bd01a12eSHiroo HAYASHI }
670bd01a12eSHiroo HAYASHI 
671314ae427SHiroo HAYASHI // Is the first charactor in an identifier? [a-zA-Z_`]
isWordToken(const int c)672314ae427SHiroo HAYASHI static bool isWordToken (const int c)
673aaee1c58SHiroo HAYASHI {
674aaee1c58SHiroo HAYASHI 	return (isalpha (c) || c == '_' || c == '`');
675aaee1c58SHiroo HAYASHI }
676aaee1c58SHiroo HAYASHI 
677314ae427SHiroo HAYASHI // Is a charactor in an identifier? [a-zA-Z0-9_`$]
isIdentifierCharacter(const int c)678ce990805SThomas Braun static bool isIdentifierCharacter (const int c)
6793ae02089SMasatake YAMATO {
680aaee1c58SHiroo HAYASHI 	return (isalnum (c) || c == '_' || c == '`' || c == '$');
6813ae02089SMasatake YAMATO }
6823ae02089SMasatake YAMATO 
skipWhite(int c)6833ae02089SMasatake YAMATO static int skipWhite (int c)
6843ae02089SMasatake YAMATO {
6853ae02089SMasatake YAMATO 	while (isspace (c))
6863ae02089SMasatake YAMATO 		c = vGetc ();
6873ae02089SMasatake YAMATO 	return c;
6883ae02089SMasatake YAMATO }
6893ae02089SMasatake YAMATO 
skipPastMatch(const char * const pair)6903ae02089SMasatake YAMATO static int skipPastMatch (const char *const pair)
6913ae02089SMasatake YAMATO {
6923ae02089SMasatake YAMATO 	const int begin = pair [0], end = pair [1];
6933ae02089SMasatake YAMATO 	int matchLevel = 1;
6943ae02089SMasatake YAMATO 	int c;
6953ae02089SMasatake YAMATO 	do
6963ae02089SMasatake YAMATO 	{
697bd01a12eSHiroo HAYASHI 		c = _vGetc (true);
6983ae02089SMasatake YAMATO 		if (c == begin)
6993ae02089SMasatake YAMATO 			++matchLevel;
7003ae02089SMasatake YAMATO 		else if (c == end)
7013ae02089SMasatake YAMATO 			--matchLevel;
7023ae02089SMasatake YAMATO 	}
70383214f95SHiroo HAYASHI 	while (matchLevel > 0 && c != EOF);
70496eaa201SHiroo HAYASHI 	return skipWhite (vGetc ());
7053ae02089SMasatake YAMATO }
7063ae02089SMasatake YAMATO 
skipDimension(int c)707acdf1816SHiroo HAYASHI static int skipDimension (int c)
708acdf1816SHiroo HAYASHI {
709b0793354SHiroo HAYASHI 	while (c == '[' && c != EOF)
71096eaa201SHiroo HAYASHI 		c = skipPastMatch ("[]");
711acdf1816SHiroo HAYASHI 	return c;
712acdf1816SHiroo HAYASHI }
713acdf1816SHiroo HAYASHI 
skipToSemiColon(int c)7144257cd2eSHiroo HAYASHI static int skipToSemiColon (int c)
7153ae02089SMasatake YAMATO {
71683214f95SHiroo HAYASHI 	while (c != ';' && c != EOF)
7173ae02089SMasatake YAMATO 		c = vGetc ();
7185b45dd48SHiroo HAYASHI 	return c;	// ';' or EOF
7193ae02089SMasatake YAMATO }
7203ae02089SMasatake YAMATO 
skipString(int c)721decc8799SHiroo HAYASHI static int skipString (int c)
722decc8799SHiroo HAYASHI {
723decc8799SHiroo HAYASHI 	if (c == '"')
724decc8799SHiroo HAYASHI 	{
725decc8799SHiroo HAYASHI 		do
726decc8799SHiroo HAYASHI 			c = vGetc ();
727decc8799SHiroo HAYASHI 		while (c != '"' && c != EOF);
728decc8799SHiroo HAYASHI 	}
729decc8799SHiroo HAYASHI 	c = skipWhite (vGetc ());
730decc8799SHiroo HAYASHI 	return c;
731decc8799SHiroo HAYASHI }
732decc8799SHiroo HAYASHI 
skipExpression(int c)733702c8227SHiroo HAYASHI static int skipExpression (int c)
734702c8227SHiroo HAYASHI {
73583214f95SHiroo HAYASHI 	while (c != ','  &&  c != ';' && c != ')' && c != '}' && c != ']' && c != EOF)
736702c8227SHiroo HAYASHI 	{
737702c8227SHiroo HAYASHI 		if (c == '(')
738702c8227SHiroo HAYASHI 			c = skipPastMatch ("()");
739702c8227SHiroo HAYASHI 		else if (c == '{')
740702c8227SHiroo HAYASHI 			c = skipPastMatch ("{}");
741702c8227SHiroo HAYASHI 		else if (c == '[')
742702c8227SHiroo HAYASHI 			c = skipPastMatch ("[]");
743decc8799SHiroo HAYASHI 		else if (c == '"')
744decc8799SHiroo HAYASHI 			c = skipString (c);
745702c8227SHiroo HAYASHI 		else
746702c8227SHiroo HAYASHI 			c = skipWhite (vGetc ());
747702c8227SHiroo HAYASHI 	}
748702c8227SHiroo HAYASHI 	return c;
749702c8227SHiroo HAYASHI }
750702c8227SHiroo HAYASHI 
751d6b72e60SHiroo HAYASHI // Skip to newline. The newline preceded by a backslash ( \ ) is ignored.
752419aa5d0SHiroo HAYASHI // Should be used after readWordTokenNoSkip() for compiler directives
skipToNewLine(int c)753419aa5d0SHiroo HAYASHI static int skipToNewLine (int c)
7545517e213SHiroo HAYASHI {
755d6b72e60SHiroo HAYASHI 	bool escape = false;
756419aa5d0SHiroo HAYASHI 	for ( ; (c != '\n' || escape) &&  c != EOF; c = vGetc ())
757d6b72e60SHiroo HAYASHI 		escape = (c == '\\');
758419aa5d0SHiroo HAYASHI 
759336b0d0dSHiroo HAYASHI 	return c;	// '\n' or EOF
7605517e213SHiroo HAYASHI }
7615517e213SHiroo HAYASHI 
skipMacro(int c,tokenInfo * token)762453a3983SHiroo HAYASHI static int skipMacro (int c, tokenInfo *token)
7635517e213SHiroo HAYASHI {
764453a3983SHiroo HAYASHI 	tokenInfo *localToken = newToken ();	// don't update token outside
7658a07c37aSHiroo HAYASHI 	while (c == '`')	// to support back-to-back compiler directives
7668a07c37aSHiroo HAYASHI 	{
767453a3983SHiroo HAYASHI 		c = readWordTokenNoSkip (localToken, c);
768d6b72e60SHiroo HAYASHI 		/* Skip compiler directive other than `define */
769453a3983SHiroo HAYASHI 		if (localToken->kind == K_DIRECTIVE)
7705517e213SHiroo HAYASHI 		{
771419aa5d0SHiroo HAYASHI 			c = skipToNewLine (c);
772336b0d0dSHiroo HAYASHI 			c = skipWhite (c);
7735517e213SHiroo HAYASHI 		}
774d6b72e60SHiroo HAYASHI 		/* Skip `define */
775453a3983SHiroo HAYASHI 		else if (localToken->kind == K_DEFINE)
776d6b72e60SHiroo HAYASHI 		{
777419aa5d0SHiroo HAYASHI 			c = skipWhite (c);
778453a3983SHiroo HAYASHI 			c = processDefine (localToken, c);
779d6b72e60SHiroo HAYASHI 		}
780453a3983SHiroo HAYASHI 		/* return macro expansion */
781453a3983SHiroo HAYASHI 		else
782453a3983SHiroo HAYASHI 		{
783453a3983SHiroo HAYASHI 			swapToken (token, localToken);
784453a3983SHiroo HAYASHI 			c = skipWhite (c);
785453a3983SHiroo HAYASHI 			if (c == '(')
786453a3983SHiroo HAYASHI 				c = skipPastMatch ("()");
7878a07c37aSHiroo HAYASHI 			break;
7888a07c37aSHiroo HAYASHI 		}
789453a3983SHiroo HAYASHI 	}
790453a3983SHiroo HAYASHI 	deleteToken (localToken);
7915517e213SHiroo HAYASHI 	return c;
7925517e213SHiroo HAYASHI }
7935517e213SHiroo HAYASHI 
_updateKind(tokenInfo * const token)79488f8b13bSHiroo HAYASHI static void _updateKind (tokenInfo *const token)
79588f8b13bSHiroo HAYASHI {
79688f8b13bSHiroo HAYASHI 	verilogKind kind = (verilogKind) lookupKeyword (vStringValue (token->name), getInputLanguage () );
79788f8b13bSHiroo HAYASHI 	token->kind = ((kind == K_UNDEFINED) && isIdentifier (token)) ? K_IDENTIFIER : kind;
79888f8b13bSHiroo HAYASHI }
79988f8b13bSHiroo HAYASHI 
800139e7cedSHiroo HAYASHI /* read an identifier, keyword, number, compiler directive, or macro identifier */
_readWordToken(tokenInfo * const token,int c,bool skip)801bd7f3072SHiroo HAYASHI static int _readWordToken (tokenInfo *const token, int c, bool skip)
8023ae02089SMasatake YAMATO {
803bd7f3072SHiroo HAYASHI 	Assert (isWordToken (c));
804bd7f3072SHiroo HAYASHI 
80569de9ae1SHiroo HAYASHI 	clearToken (token);
806aaee1c58SHiroo HAYASHI 	do
8073ae02089SMasatake YAMATO 	{
8083ae02089SMasatake YAMATO 		vStringPut (token->name, c);
8093ae02089SMasatake YAMATO 		c = vGetc ();
810aaee1c58SHiroo HAYASHI 	} while (isIdentifierCharacter (c));
81188f8b13bSHiroo HAYASHI 	_updateKind (token);
812bd7f3072SHiroo HAYASHI 
813bd7f3072SHiroo HAYASHI 	if (skip)
814bd7f3072SHiroo HAYASHI 		return skipWhite (c);
815bd7f3072SHiroo HAYASHI 	else
816419aa5d0SHiroo HAYASHI 		return c;
817bd7f3072SHiroo HAYASHI }
818bd7f3072SHiroo HAYASHI 
819419aa5d0SHiroo HAYASHI // read a word token starting with "c".
820419aa5d0SHiroo HAYASHI // returns the first charactor of the next token.
readWordToken(tokenInfo * const token,int c)821bd7f3072SHiroo HAYASHI static int readWordToken (tokenInfo *const token, int c)
822bd7f3072SHiroo HAYASHI {
823bd7f3072SHiroo HAYASHI 	return _readWordToken (token, c, true);
824bd7f3072SHiroo HAYASHI }
825bd7f3072SHiroo HAYASHI 
826419aa5d0SHiroo HAYASHI // read a word token starting with "c".
827419aa5d0SHiroo HAYASHI // returns the next charactor of the token read.
828bd7f3072SHiroo HAYASHI // for compiler directives.  Since they are line-based, skipWhite() cannot be used.
readWordTokenNoSkip(tokenInfo * const token,int c)829419aa5d0SHiroo HAYASHI static int readWordTokenNoSkip (tokenInfo *const token, int c)
830bd7f3072SHiroo HAYASHI {
831419aa5d0SHiroo HAYASHI 	return _readWordToken (token, c, false);
8323ae02089SMasatake YAMATO }
8333ae02089SMasatake YAMATO 
8348ccc1123SHiroo HAYASHI /* check if an identifier:
835139e7cedSHiroo HAYASHI  *   simple_identifier ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_$ ] } */
isIdentifier(tokenInfo * token)836139e7cedSHiroo HAYASHI static bool isIdentifier (tokenInfo* token)
837139e7cedSHiroo HAYASHI {
838139e7cedSHiroo HAYASHI 	if (token->kind == K_UNDEFINED)
839139e7cedSHiroo HAYASHI 	{
840139e7cedSHiroo HAYASHI 		for (int i = 0; i < vStringLength (token->name); i++)
841139e7cedSHiroo HAYASHI 		{
842139e7cedSHiroo HAYASHI 			int c = vStringChar (token->name, i);
843139e7cedSHiroo HAYASHI 			if (i == 0)
844139e7cedSHiroo HAYASHI 			{
845314ae427SHiroo HAYASHI 				if (c == '`' || !isWordToken (c))
846139e7cedSHiroo HAYASHI 					return false;
847139e7cedSHiroo HAYASHI 			}
848139e7cedSHiroo HAYASHI 			else
849139e7cedSHiroo HAYASHI 			{
850aaee1c58SHiroo HAYASHI 				if (!isIdentifierCharacter (c))
851139e7cedSHiroo HAYASHI 					return false;
852139e7cedSHiroo HAYASHI 			}
853139e7cedSHiroo HAYASHI 		}
854139e7cedSHiroo HAYASHI 		return true;
855139e7cedSHiroo HAYASHI 	}
856139e7cedSHiroo HAYASHI 	else
857139e7cedSHiroo HAYASHI 		return false;
858139e7cedSHiroo HAYASHI }
859139e7cedSHiroo HAYASHI 
createContext(verilogKind kind,vString * const name)860abb1a0abSHiroo HAYASHI static void createContext (verilogKind kind, vString* const name)
8613ae02089SMasatake YAMATO {
862abb1a0abSHiroo HAYASHI 	tokenInfo *const scope = newToken ();
863abb1a0abSHiroo HAYASHI 	vStringCopy (scope->name, name);
864abb1a0abSHiroo HAYASHI 	scope->kind = kind;
865abb1a0abSHiroo HAYASHI 
8663ae02089SMasatake YAMATO 	if (scope)
8673ae02089SMasatake YAMATO 	{
8683ae02089SMasatake YAMATO 		vString *contextName = vStringNew ();
8693ae02089SMasatake YAMATO 
8703ae02089SMasatake YAMATO 		/* Determine full context name */
8713ae02089SMasatake YAMATO 		if (currentContext->kind != K_UNDEFINED)
8723ae02089SMasatake YAMATO 		{
8733ae02089SMasatake YAMATO 			vStringCopy (contextName, currentContext->name);
8741da6e7e4SMasatake YAMATO 			vStringPut (contextName, '.');
8753ae02089SMasatake YAMATO 		}
8763ae02089SMasatake YAMATO 		vStringCat (contextName, scope->name);
8773ae02089SMasatake YAMATO 		/* Create context */
8783ae02089SMasatake YAMATO 		currentContext = pushToken (currentContext, scope);
8793ae02089SMasatake YAMATO 		vStringCopy (currentContext->name, contextName);
8803ae02089SMasatake YAMATO 		vStringDelete (contextName);
881b304ce8dSVitor Antunes 		verbose ("Created new context %s (kind %d)\n", vStringValue (currentContext->name), currentContext->kind);
8823ae02089SMasatake YAMATO 	}
8833ae02089SMasatake YAMATO }
8843ae02089SMasatake YAMATO 
dropContext()88553ae1d47SHiroo HAYASHI static void dropContext ()
88653ae1d47SHiroo HAYASHI {
88753ae1d47SHiroo HAYASHI 	verbose ("Dropping context %s\n", vStringValue (currentContext->name));
88853ae1d47SHiroo HAYASHI 	currentContext = popToken (currentContext);
88953ae1d47SHiroo HAYASHI }
89053ae1d47SHiroo HAYASHI 
891b56d22dcSHiroo HAYASHI /* Drop context, but only if an end token is found */
dropEndContext(tokenInfo * const token,int c)892336b0d0dSHiroo HAYASHI static int dropEndContext (tokenInfo *const token, int c)
8933ae02089SMasatake YAMATO {
8943ae02089SMasatake YAMATO 	verbose ("current context %s; context kind %0d; nest level %0d\n", vStringValue (currentContext->name), currentContext->kind, currentContext->nestLevel);
895b762e2b6SHiroo HAYASHI 	if ((currentContext->kind == K_COVERGROUP && strcmp (vStringValue (token->name), "endgroup") == 0)
896b762e2b6SHiroo HAYASHI 	    || (currentContext->kind == K_IFCLASS && strcmp (vStringValue (token->name), "endclass") == 0))
8973ae02089SMasatake YAMATO 	{
89853ae1d47SHiroo HAYASHI 		dropContext ();
89991b5c3fcSHiroo HAYASHI 		c = skipBlockName (token ,c);
9003ae02089SMasatake YAMATO 	}
901b56d22dcSHiroo HAYASHI 	else if (currentContext->kind != K_UNDEFINED)
9023ae02089SMasatake YAMATO 	{
903286499bbSHiroo HAYASHI 		vString *endTokenName = vStringNewInit ("end");
904f92e6bf2SMasatake YAMATO 		vStringCatS (endTokenName, getNameForKind (currentContext->kind));
9053ae02089SMasatake YAMATO 		if (strcmp (vStringValue (token->name), vStringValue (endTokenName)) == 0)
9063ae02089SMasatake YAMATO 		{
90753ae1d47SHiroo HAYASHI 			dropContext ();
90891b5c3fcSHiroo HAYASHI 			c = skipBlockName (token ,c);
909b304ce8dSVitor Antunes 			if (currentContext->classScope)
910b304ce8dSVitor Antunes 			{
911b304ce8dSVitor Antunes 				verbose ("Dropping local context %s\n", vStringValue (currentContext->name));
912b304ce8dSVitor Antunes 				currentContext = popToken (currentContext);
913b304ce8dSVitor Antunes 			}
9143ae02089SMasatake YAMATO 		}
9153ae02089SMasatake YAMATO 		vStringDelete (endTokenName);
9163ae02089SMasatake YAMATO 	}
917b56d22dcSHiroo HAYASHI 	else
918b56d22dcSHiroo HAYASHI 		verbose ("Unexpected current context %s\n", vStringValue (currentContext->name));
919336b0d0dSHiroo HAYASHI 	return c;
920286499bbSHiroo HAYASHI }
9213ae02089SMasatake YAMATO 
9223ae02089SMasatake YAMATO 
createTag(tokenInfo * const token,verilogKind kind)923220345f7SHiroo HAYASHI static void createTag (tokenInfo *const token, verilogKind kind)
9243ae02089SMasatake YAMATO {
9253ae02089SMasatake YAMATO 	tagEntryInfo tag;
926220345f7SHiroo HAYASHI 
9272e2a1af9SHiroo HAYASHI 	if (kind == K_LOCALPARAM)
9282e2a1af9SHiroo HAYASHI 		kind = K_CONSTANT;
9292e2a1af9SHiroo HAYASHI 	else if (kind == K_PARAMETER)
9302e2a1af9SHiroo HAYASHI 	{
9312e2a1af9SHiroo HAYASHI 		kind = K_CONSTANT;
932af35bd7cSHiroo HAYASHI 		// See LRM 2017 6.20.1 Parameter declaration syntax
933af35bd7cSHiroo HAYASHI 		if (currentContext->kind != K_CLASS && currentContext->kind != K_PACKAGE && !currentContext->hasParamList)
9342e2a1af9SHiroo HAYASHI 			token->parameter = true;
9352e2a1af9SHiroo HAYASHI 	}
936d6fa3c08SHiroo HAYASHI 	Assert (kind >= 0 && kind != K_UNDEFINED && kind != K_IDENTIFIER);
937b449e8a0SHiroo HAYASHI 	Assert (vStringLength (token->name) > 0);
9382e2a1af9SHiroo HAYASHI 
939220345f7SHiroo HAYASHI 	/* check if a container before kind is modified by prototype */
940220345f7SHiroo HAYASHI 	/* BTW should we create a context for a prototype? */
941220345f7SHiroo HAYASHI 	bool container = isContainer (kind);
94296047d1aSVitor Antunes 
94396047d1aSVitor Antunes 	/* Determine if kind is prototype */
94496047d1aSVitor Antunes 	if (currentContext->prototype)
94596047d1aSVitor Antunes 		kind = K_PROTOTYPE;
9463ae02089SMasatake YAMATO 
947b449e8a0SHiroo HAYASHI 	/* Do nothing if tag kind is disabled */
94894d34aa7SHiroo HAYASHI 	if (! kindEnabled (kind))
94994d34aa7SHiroo HAYASHI 	{
95094d34aa7SHiroo HAYASHI 		verbose ("kind disabled\n");
9513ae02089SMasatake YAMATO 		return;
9523ae02089SMasatake YAMATO 	}
9533ae02089SMasatake YAMATO 
9543ae02089SMasatake YAMATO 	/* Create tag */
9555a2b57ecSHiroo HAYASHI 	initTagEntry (&tag, vStringValue (token->name), kind);
956ca63abd1SMasatake YAMATO 	tag.lineNumber = token->lineNumber;
957ca63abd1SMasatake YAMATO 	tag.filePosition = token->filePosition;
958ca63abd1SMasatake YAMATO 
95996047d1aSVitor Antunes 	verbose ("Adding tag %s (kind %d)", vStringValue (token->name), kind);
9603ae02089SMasatake YAMATO 	if (currentContext->kind != K_UNDEFINED)
9613ae02089SMasatake YAMATO 	{
9623ae02089SMasatake YAMATO 		verbose (" to context %s\n", vStringValue (currentContext->name));
96396047d1aSVitor Antunes 		currentContext->lastKind = kind;
964f92e6bf2SMasatake YAMATO 		tag.extensionFields.scopeKindIndex = currentContext->kind;
965015ab54cSMasatake YAMATO 		tag.extensionFields.scopeName = vStringValue (currentContext->name);
9663ae02089SMasatake YAMATO 	}
9673ae02089SMasatake YAMATO 	verbose ("\n");
9683ae02089SMasatake YAMATO 	if (vStringLength (token->inheritance) > 0)
9693ae02089SMasatake YAMATO 	{
9703ae02089SMasatake YAMATO 		tag.extensionFields.inheritance = vStringValue (token->inheritance);
9713ae02089SMasatake YAMATO 		verbose ("Class %s extends %s\n", vStringValue (token->name), tag.extensionFields.inheritance);
9723ae02089SMasatake YAMATO 	}
97323297f61SMasatake YAMATO 
9742e2a1af9SHiroo HAYASHI 	if (token->parameter)
9755a2b57ecSHiroo HAYASHI 		attachParserField (&tag, false, fieldTable [F_PARAMETER].ftype, "");
9762e2a1af9SHiroo HAYASHI 
97718ef4c99SMasatake YAMATO 	makeTagEntry (&tag);
97823297f61SMasatake YAMATO 
97935c59e96SMasatake YAMATO 	if (isXtagEnabled (XTAG_QUALIFIED_TAGS) && currentContext->kind != K_UNDEFINED)
9803ae02089SMasatake YAMATO 	{
9813ae02089SMasatake YAMATO 		vString *const scopedName = vStringNew ();
9823ae02089SMasatake YAMATO 
9833ae02089SMasatake YAMATO 		vStringCopy (scopedName, currentContext->name);
9841da6e7e4SMasatake YAMATO 		vStringPut (scopedName, '.');
9854e6bcb7bSColomban Wendling 		vStringCat (scopedName, token->name);
9863ae02089SMasatake YAMATO 		tag.name = vStringValue (scopedName);
9873ae02089SMasatake YAMATO 
9885022e63aSMasatake YAMATO 		markTagExtraBit (&tag, XTAG_QUALIFIED_TAGS);
9893ae02089SMasatake YAMATO 		makeTagEntry (&tag);
9903ae02089SMasatake YAMATO 
9913ae02089SMasatake YAMATO 		vStringDelete (scopedName);
9923ae02089SMasatake YAMATO 	}
9933ae02089SMasatake YAMATO 
9943ae02089SMasatake YAMATO 	/* Push token as context if it is a container */
995220345f7SHiroo HAYASHI 	if (container)
9963ae02089SMasatake YAMATO 	{
997abb1a0abSHiroo HAYASHI 		createContext (kind, token->name);
9989a433176SVitor Antunes 
999c16b8e7aSHiroo HAYASHI 		/* Put found contents in context */
1000c16b8e7aSHiroo HAYASHI 		verbose ("Putting tagContents: %d element(s)\n",
1001462ef99aSMasatake YAMATO 				 ptrArrayCount (tagContents));
100254c9eceaSHiroo HAYASHI 		for (unsigned int i = 0; i < ptrArrayCount (tagContents); i++)
10039a433176SVitor Antunes 		{
100454c9eceaSHiroo HAYASHI 			tokenInfo *content = ptrArrayItem (tagContents, i);
1005220345f7SHiroo HAYASHI 			createTag (content, content->kind);
10069a433176SVitor Antunes 		}
10079a433176SVitor Antunes 
10089a433176SVitor Antunes 		/* Drop temporary contexts */
10099a433176SVitor Antunes 		if (isTempContext (currentContext))
101053ae1d47SHiroo HAYASHI 			dropContext ();
10119a433176SVitor Antunes 	}
10123ae02089SMasatake YAMATO 
10133ae02089SMasatake YAMATO 	/* Clear no longer required inheritance information */
10143ae02089SMasatake YAMATO 	vStringClear (token->inheritance);
10153ae02089SMasatake YAMATO }
10163ae02089SMasatake YAMATO 
skipBlockName(tokenInfo * const token,int c)101791b5c3fcSHiroo HAYASHI static int skipBlockName (tokenInfo *const token, int c)
10183ae02089SMasatake YAMATO {
10193ae02089SMasatake YAMATO 	if (c == ':')
10203ae02089SMasatake YAMATO 	{
10213ae02089SMasatake YAMATO 		c = skipWhite (vGetc ());
1022b67a1035SHiroo HAYASHI 		if (isWordToken (c))
1023bd7f3072SHiroo HAYASHI 			c = readWordToken (token, c);
1024b67a1035SHiroo HAYASHI 	}
102591b5c3fcSHiroo HAYASHI 	return c;
10263ae02089SMasatake YAMATO }
10273ae02089SMasatake YAMATO 
10284aaf731aSHiroo HAYASHI // begin, fork
processBlock(tokenInfo * const token,int c)1029336b0d0dSHiroo HAYASHI static int processBlock (tokenInfo *const token, int c)
10303ae02089SMasatake YAMATO {
103191b5c3fcSHiroo HAYASHI 	if (c == ':')	// tag an optional block identifier
103291b5c3fcSHiroo HAYASHI 	{
103391b5c3fcSHiroo HAYASHI 		c = skipWhite (vGetc ());
1034b67a1035SHiroo HAYASHI 		if (isWordToken (c))
10353ae02089SMasatake YAMATO 		{
1036bd7f3072SHiroo HAYASHI 			c = readWordToken (token, c);
10373ae02089SMasatake YAMATO 			verbose ("Found block: %s\n", vStringValue (token->name));
1038220345f7SHiroo HAYASHI 			createTag (token, K_BLOCK);
10393ae02089SMasatake YAMATO 			verbose ("Current context %s\n", vStringValue (currentContext->name));
10403ae02089SMasatake YAMATO 		}
104191b5c3fcSHiroo HAYASHI 	}
10424aaf731aSHiroo HAYASHI 	currentContext->nestLevel++;	// increment after creating a context
1043336b0d0dSHiroo HAYASHI 	return c;
10443ae02089SMasatake YAMATO }
104589026706SHiroo HAYASHI 
10464aaf731aSHiroo HAYASHI // end, join, join_any, join_none
processEnd(tokenInfo * const token,int c)1047336b0d0dSHiroo HAYASHI static int processEnd (tokenInfo *const token, int c)
104889026706SHiroo HAYASHI {
10494aaf731aSHiroo HAYASHI 	if (currentContext->nestLevel > 0)	// for sanity check
105089026706SHiroo HAYASHI 		currentContext->nestLevel--;
10514aaf731aSHiroo HAYASHI 	if (currentContext->kind == K_BLOCK && currentContext->nestLevel == 0)
10524aaf731aSHiroo HAYASHI 		dropContext ();
10534aaf731aSHiroo HAYASHI 
105491b5c3fcSHiroo HAYASHI 	c = skipBlockName (token, c);
1055336b0d0dSHiroo HAYASHI 	return c;
10563ae02089SMasatake YAMATO }
10573ae02089SMasatake YAMATO 
processPortList(tokenInfo * token,int c,bool mayPortDecl)10580c733c6aSHiroo HAYASHI static int processPortList (tokenInfo *token, int c, bool mayPortDecl)
10593ae02089SMasatake YAMATO {
1060acdf1816SHiroo HAYASHI 	if (c == '(')
10613ae02089SMasatake YAMATO 	{
10620c733c6aSHiroo HAYASHI 		c = skipWhite (vGetc ());	// skip '('
10630c733c6aSHiroo HAYASHI 		c = tagIdentifierList (token, c, K_PORT, mayPortDecl);
1064336b0d0dSHiroo HAYASHI 		if (c == ')')	// sanity check
1065336b0d0dSHiroo HAYASHI 			c = skipWhite (vGetc ());
1066336b0d0dSHiroo HAYASHI 		else
1067336b0d0dSHiroo HAYASHI 			verbose ("Unexpected input: %c\n", c);
10683ae02089SMasatake YAMATO 	}
10693c80bb1eSHiroo HAYASHI 	return c;
1070d59ce112SVitor Antunes }
10713ae02089SMasatake YAMATO 
skipParameterAssignment(int c)10729eac6db5SHiroo HAYASHI static int skipParameterAssignment (int c)
10739eac6db5SHiroo HAYASHI {
10749eac6db5SHiroo HAYASHI 	if (c == '#')
10759eac6db5SHiroo HAYASHI 	{
10769eac6db5SHiroo HAYASHI 		c = skipWhite (vGetc ());
10779eac6db5SHiroo HAYASHI 		if (c == '(')
107896eaa201SHiroo HAYASHI 			c = skipPastMatch ("()");
10799eac6db5SHiroo HAYASHI 	}
10809eac6db5SHiroo HAYASHI 	return c;
10819eac6db5SHiroo HAYASHI }
10829eac6db5SHiroo HAYASHI 
1083a022b740SHiroo HAYASHI // Functions are treated differently because they may also include the type of the return value.
1084a022b740SHiroo HAYASHI // Tasks are treated in the same way, although not having a return value.
1085a022b740SHiroo HAYASHI //
1086a022b740SHiroo HAYASHI // function [ lifetime ] function_data_type_or_implicit [ interface_identifier . | class_scope ] function_identifier [ ( [ tf_port_list ] ) ] ;
1087a022b740SHiroo HAYASHI // task     [ lifetime ] task_body_declaration          [ interface_identifier . | class_scope ] task_identifier     [ ( [ tf_port_list ] ) ] ;
processFunction(tokenInfo * const token,int c)1088336b0d0dSHiroo HAYASHI static int processFunction (tokenInfo *const token, int c)
10893ae02089SMasatake YAMATO {
1090220345f7SHiroo HAYASHI 	verilogKind kind = token->kind;	// K_FUNCTION or K_TASK
10913ae02089SMasatake YAMATO 
10923ae02089SMasatake YAMATO 	/* Search for function name
10933ae02089SMasatake YAMATO 	 * Last identifier found before a '(' or a ';' is the function name */
109483214f95SHiroo HAYASHI 	while (c != '(' && c != ';' && c != EOF)
10953ae02089SMasatake YAMATO 	{
1096b67a1035SHiroo HAYASHI 		if (isWordToken (c))
1097bd7f3072SHiroo HAYASHI 			c = readWordToken (token, c);
1098bd7f3072SHiroo HAYASHI 		else
10993ae02089SMasatake YAMATO 			c = skipWhite (vGetc ());
11009eac6db5SHiroo HAYASHI 		/* skip parameter assignment of a class type
11019eac6db5SHiroo HAYASHI 		 *    ex. function uvm_port_base #(IF) get_if(int index=0); */
11029eac6db5SHiroo HAYASHI 		c = skipParameterAssignment (c);
11039eac6db5SHiroo HAYASHI 
1104b304ce8dSVitor Antunes 		/* Identify class type prefixes and create respective context*/
11057d90c743SMasatake YAMATO 		if (isInputLanguage (Lang_systemverilog) && c == ':')
1106b304ce8dSVitor Antunes 		{
1107b304ce8dSVitor Antunes 			c = vGetc ();
1108b304ce8dSVitor Antunes 			if (c == ':')
1109b304ce8dSVitor Antunes 			{
1110b304ce8dSVitor Antunes 				verbose ("Found function declaration with class type %s\n", vStringValue (token->name));
1111abb1a0abSHiroo HAYASHI 				createContext (K_CLASS, token->name);
1112ce990805SThomas Braun 				currentContext->classScope = true;
1113b304ce8dSVitor Antunes 			}
1114b304ce8dSVitor Antunes 			else
1115b304ce8dSVitor Antunes 				vUngetc (c);
1116b304ce8dSVitor Antunes 		}
111783214f95SHiroo HAYASHI 	}
11183ae02089SMasatake YAMATO 	verbose ("Found function: %s\n", vStringValue (token->name));
1119220345f7SHiroo HAYASHI 	createTag (token, kind);
11203ae02089SMasatake YAMATO 
11213ae02089SMasatake YAMATO 	/* Get port list from function */
11223c80bb1eSHiroo HAYASHI 	c = skipWhite (c);
11230c733c6aSHiroo HAYASHI 	c = processPortList (token, c, false);
1124336b0d0dSHiroo HAYASHI 	return c;
11253ae02089SMasatake YAMATO }
11263ae02089SMasatake YAMATO 
11272d0d3dcbSK.Takata // ( enum | union ) [ enum_base_type ] { < enum_name_declaration > }  { [ ... ] }
processEnum(tokenInfo * const token,int c)1128336b0d0dSHiroo HAYASHI static int processEnum (tokenInfo *const token, int c)
11299a433176SVitor Antunes {
1130b7a8e855SHiroo HAYASHI 	tokenInfo* enumToken = dupToken (token);	// save enum token
11319a433176SVitor Antunes 
1132b7a8e855SHiroo HAYASHI 	/* skip enum_base_type */
113383214f95SHiroo HAYASHI 	while (isWordToken (c))
1134bd7f3072SHiroo HAYASHI 		c = readWordToken (token, c);
1135acdf1816SHiroo HAYASHI 	c = skipDimension (c);
11369a433176SVitor Antunes 
11379a433176SVitor Antunes 	/* Search enum elements */
1138de5b45a8SHiroo HAYASHI 	c = pushEnumNames (token, c);
11399a433176SVitor Antunes 
1140b7a8e855SHiroo HAYASHI 	/* Skip bus width definition */
1141b7a8e855SHiroo HAYASHI 	c = skipDimension (c);
1142b7a8e855SHiroo HAYASHI 
11439a433176SVitor Antunes 	/* Following identifiers are tag names */
11443db0d4c2SHiroo HAYASHI 	verbose ("Find enum tags. Token %s kind %d\n", vStringValue (enumToken->name), enumToken->kind);
1145b449e8a0SHiroo HAYASHI 	c = tagNameList (enumToken, c, enumToken->kind);
11463db0d4c2SHiroo HAYASHI 	deleteToken (enumToken);
114791c75da9SHiroo HAYASHI 
1148b7a8e855SHiroo HAYASHI 	// Clean up the tag content list at the end of the declaration to support multiple variables
114991c75da9SHiroo HAYASHI 	//   enum { ... } foo, bar;
1150462ef99aSMasatake YAMATO 	ptrArrayClear (tagContents);
1151336b0d0dSHiroo HAYASHI 	return c;
11529a433176SVitor Antunes }
11539a433176SVitor Antunes 
11542d0d3dcbSK.Takata // [ struct | union [ tagged ] ] [ packed [ signed | unsigned ] ] { struct_union_member { struct_union_member } } { [ ... ] }
processStruct(tokenInfo * const token,int c)1155336b0d0dSHiroo HAYASHI static int processStruct (tokenInfo *const token, int c)
11562db6ef34SHiroo HAYASHI {
1157d8576f6dSHiroo HAYASHI 	verilogKind kind = token->kind;	// K_STRUCT, K_TYPEDEF, or K_NETTYPE
11582db6ef34SHiroo HAYASHI 
11592db6ef34SHiroo HAYASHI 	/* Skip packed, signed, and unsigned */
116083214f95SHiroo HAYASHI 	while (isWordToken (c))
1161bd7f3072SHiroo HAYASHI 		c = readWordToken (token, c);
11622db6ef34SHiroo HAYASHI 
116331730736SHiroo HAYASHI 	/* create a list of members */
116431730736SHiroo HAYASHI 	c = pushMembers (token, c);
11652db6ef34SHiroo HAYASHI 
11662db6ef34SHiroo HAYASHI 	/* Skip packed_dimension */
1167acdf1816SHiroo HAYASHI 	c = skipDimension (c);
11682db6ef34SHiroo HAYASHI 
11692db6ef34SHiroo HAYASHI 	/* Following identifiers are tag names */
11702db6ef34SHiroo HAYASHI 	verbose ("Find struct|union tags. Token %s kind %d\n", vStringValue (token->name), token->kind);
1171b449e8a0SHiroo HAYASHI 	c = tagNameList (token, c, kind);
117231730736SHiroo HAYASHI 	ptrArrayClear (tagContents);
1173336b0d0dSHiroo HAYASHI 	return c;
11742db6ef34SHiroo HAYASHI }
11752db6ef34SHiroo HAYASHI 
1176a022b740SHiroo HAYASHI // data_declaration ::=
1177a022b740SHiroo HAYASHI //       [ const ] [ var ] [ static | automatic ] data_type_or_implicit list_of_variable_decl_assignments ;
11782d0d3dcbSK.Takata //     | typedef data_type type_identifier { [ ... ] } ;
1179fdca20b9SHiroo HAYASHI //     | typedef interface_instance_identifier [ ... ] . type_identifier type_identifier ; // interface based typedef
1180a022b740SHiroo HAYASHI //     | typedef [ enum | struct | union | class | interface class ] type_identifier ;
1181a022b740SHiroo HAYASHI //     | import < package_import_item > ;
1182a022b740SHiroo HAYASHI //     | nettype data_type net_type_identifier [ with [ class_type :: | package_identifier :: | $unit :: ] tf_identifier ] ;
1183a022b740SHiroo HAYASHI //     | nettype [ class_type :: | package_identifier :: | $unit :: ] net_type_identifier net_type_identifier ;
processTypedef(tokenInfo * const token,int c)1184336b0d0dSHiroo HAYASHI static int processTypedef (tokenInfo *const token, int c)
11853ae02089SMasatake YAMATO {
1186d8576f6dSHiroo HAYASHI 	verilogKind kindSave = token->kind;	// K_TYPEDEF or K_NETTYPE
11873087f342SHiroo HAYASHI 	verilogKind kind = K_UNDEFINED;
1188a6f873e6SHiroo HAYASHI 	bool not_used;
1189b67a1035SHiroo HAYASHI 	if (isWordToken (c))
119096047d1aSVitor Antunes 	{
1191bd7f3072SHiroo HAYASHI 		c = readWordToken (token, c);
11923087f342SHiroo HAYASHI 		kind = token->kind;
11933087f342SHiroo HAYASHI 	}
1194c8fe183bSHiroo HAYASHI 	// forward typedef (LRM 6.18) is tagged as prototype
11953087f342SHiroo HAYASHI 	//   (I don't know why...)
11963087f342SHiroo HAYASHI 	switch (kind)
11973087f342SHiroo HAYASHI 	{
11989a433176SVitor Antunes 		case K_CLASS:
11993087f342SHiroo HAYASHI 		case K_INTERFACE:
1200ce990805SThomas Braun 			currentContext->prototype = true;
12019a433176SVitor Antunes 			break;
12029a433176SVitor Antunes 		case K_ENUM:
1203b4ff3167SHiroo HAYASHI 		case K_STRUCT:
1204b67a1035SHiroo HAYASHI 			if (isWordToken (c))
120596047d1aSVitor Antunes 			{
1206bd7f3072SHiroo HAYASHI 				c = readWordToken (token, c);
12073087f342SHiroo HAYASHI 				if (token->kind == K_IDENTIFIER && c == ';')
12089a433176SVitor Antunes 					currentContext->prototype = true;
120996047d1aSVitor Antunes 			}
12103087f342SHiroo HAYASHI 			break;
12113087f342SHiroo HAYASHI 		case K_IDENTIFIER:
1212fdca20b9SHiroo HAYASHI 			// interface based typedef
1213fdca20b9SHiroo HAYASHI 			c = skipDimension (c);
1214fdca20b9SHiroo HAYASHI 			if (c == '.')
1215fdca20b9SHiroo HAYASHI 			{
1216fdca20b9SHiroo HAYASHI 				c = skipWhite (vGetc ());
1217fdca20b9SHiroo HAYASHI 				if (isWordToken (c))
1218fdca20b9SHiroo HAYASHI 					c = readWordToken (token, c);
1219fdca20b9SHiroo HAYASHI 			}
12203087f342SHiroo HAYASHI 			if (c == ';')
12213087f342SHiroo HAYASHI 				currentContext->prototype = true;
12223087f342SHiroo HAYASHI 			break;
12233087f342SHiroo HAYASHI 		default:
12243087f342SHiroo HAYASHI 			; // do nothing
12259a433176SVitor Antunes 	}
1226a6f873e6SHiroo HAYASHI 	c = processType (token, c, &kind, &not_used);
12279a433176SVitor Antunes 
1228d8576f6dSHiroo HAYASHI 	createTag (token, kindSave);
1229de5b45a8SHiroo HAYASHI 
1230462ef99aSMasatake YAMATO 	ptrArrayClear (tagContents);
1231336b0d0dSHiroo HAYASHI 	return c;
12323ae02089SMasatake YAMATO }
12333ae02089SMasatake YAMATO 
processParameterList(tokenInfo * token,int c)1234f3d60108SHiroo HAYASHI static int processParameterList (tokenInfo *token, int c)
1235628374a2SHiroo HAYASHI {
12362e2a1af9SHiroo HAYASHI 	bool parameter = true;	// default "parameter"
123783214f95SHiroo HAYASHI 
123883214f95SHiroo HAYASHI 	if (c != '#')
123983214f95SHiroo HAYASHI 		return c;
1240628374a2SHiroo HAYASHI 	c = skipWhite (vGetc ());
124183214f95SHiroo HAYASHI 
124283214f95SHiroo HAYASHI 	if (c != '(')
124383214f95SHiroo HAYASHI 		return c;
1244628374a2SHiroo HAYASHI 	c = skipWhite (vGetc ());
124583214f95SHiroo HAYASHI 
124654b431e2SHiroo HAYASHI 	while (c != ')' && c != EOF)
1247c66a896dSHiroo HAYASHI 	{
1248b67a1035SHiroo HAYASHI 		if (isWordToken (c))
1249628374a2SHiroo HAYASHI 		{
1250c66a896dSHiroo HAYASHI 			c = readWordToken (token, c);
1251628374a2SHiroo HAYASHI 			verbose ("Found parameter %s\n", vStringValue (token->name));
12528ccc1123SHiroo HAYASHI 			if (token->kind == K_IDENTIFIER)
1253628374a2SHiroo HAYASHI 			{
1254628374a2SHiroo HAYASHI 				if (c == ',' || c == ')' || c == '=')	// ignore user defined type
1255628374a2SHiroo HAYASHI 				{
125673701136SHiroo HAYASHI 					tokenInfo *param = dupToken (token);
125773701136SHiroo HAYASHI 					param->kind = K_CONSTANT;
125873701136SHiroo HAYASHI 					param->parameter = parameter;
1259c16b8e7aSHiroo HAYASHI 					ptrArrayAdd (tagContents, param);
1260c66a896dSHiroo HAYASHI 					if (c == '=')
1261c66a896dSHiroo HAYASHI 						c = skipExpression (vGetc ());
1262c66a896dSHiroo HAYASHI 					else if (c == ',')
1263c66a896dSHiroo HAYASHI 						c = skipWhite (vGetc ());
1264c66a896dSHiroo HAYASHI 					else	// ')'
1265c66a896dSHiroo HAYASHI 						break;
1266628374a2SHiroo HAYASHI 				}
1267628374a2SHiroo HAYASHI 			}
12682e2a1af9SHiroo HAYASHI 			else if (token->kind == K_PARAMETER)
12692e2a1af9SHiroo HAYASHI 				parameter = true;
12702e2a1af9SHiroo HAYASHI 			else if (token->kind == K_LOCALPARAM)
12712e2a1af9SHiroo HAYASHI 				parameter = false;
1272628374a2SHiroo HAYASHI 		}
1273c66a896dSHiroo HAYASHI 		else
1274c66a896dSHiroo HAYASHI 			c = skipWhite (vGetc ());
1275d6fa3c08SHiroo HAYASHI 		// unpacked array is not allowed for a parameter
1276c66a896dSHiroo HAYASHI 	}
127783214f95SHiroo HAYASHI 	c = skipWhite (vGetc ());	// skip ')'
1278f3d60108SHiroo HAYASHI 	return c;
1279628374a2SHiroo HAYASHI }
1280628374a2SHiroo HAYASHI 
1281a022b740SHiroo HAYASHI // [ virtual ] class [ static | automatic ] class_identifier [ parameter_port_list ]
1282a022b740SHiroo HAYASHI //     [ extends class_type [ ( list_of_arguments ) ] ] [ implements < interface_class_type > ] ;
1283a022b740SHiroo HAYASHI // interface class class_identifier [ parameter_port_list ] [ extends < interface_class_type > ] ;
processClass(tokenInfo * const token,int c,verilogKind kind)1284b762e2b6SHiroo HAYASHI static int processClass (tokenInfo *const token, int c, verilogKind kind)
12853ae02089SMasatake YAMATO {
1286abe7de79SHiroo HAYASHI 	tokenInfo *classToken;
12873ae02089SMasatake YAMATO 
12883ae02089SMasatake YAMATO 	/* Get identifiers */
1289aa0057abSHiroo HAYASHI 	while (isWordToken (c))
1290aa0057abSHiroo HAYASHI 	{
1291bd7f3072SHiroo HAYASHI 		c = readWordToken (token, c);
1292aa0057abSHiroo HAYASHI 		// skip static or automatic
1293aa0057abSHiroo HAYASHI 		if (token->kind != K_IGNORE)
1294aa0057abSHiroo HAYASHI 			break;
1295aa0057abSHiroo HAYASHI 	}
1296aa0057abSHiroo HAYASHI 
1297aa0057abSHiroo HAYASHI 	if (token->kind != K_IDENTIFIER)
1298abe7de79SHiroo HAYASHI 	{
1299abe7de79SHiroo HAYASHI 		verbose ("Unexpected input: class name is expected.\n");
1300336b0d0dSHiroo HAYASHI 		return c;
1301abe7de79SHiroo HAYASHI 	}
1302abe7de79SHiroo HAYASHI 
1303abe7de79SHiroo HAYASHI 	/* save token */
1304abe7de79SHiroo HAYASHI 	classToken = dupToken (token);
13053ae02089SMasatake YAMATO 
13063ae02089SMasatake YAMATO 	/* Find class parameters list */
1307f3d60108SHiroo HAYASHI 	c = processParameterList (token, c);
13083ae02089SMasatake YAMATO 
13093ae02089SMasatake YAMATO 	/* Search for inheritance information */
1310b67a1035SHiroo HAYASHI 	if (isWordToken (c))
13113ae02089SMasatake YAMATO 	{
1312bd7f3072SHiroo HAYASHI 		c = readWordToken (token, c);
1313abe7de79SHiroo HAYASHI 		if (strcmp (vStringValue (token->name), "extends") == 0)
1314abe7de79SHiroo HAYASHI 		{
1315b67a1035SHiroo HAYASHI 			if (isWordToken (c))
1316bd7f3072SHiroo HAYASHI 				c = readWordToken (token, c);
1317abe7de79SHiroo HAYASHI 			vStringCopy (classToken->inheritance, token->name);
1318abe7de79SHiroo HAYASHI 			verbose ("Inheritance %s\n", vStringValue (classToken->inheritance));
13193ae02089SMasatake YAMATO 		}
13203ae02089SMasatake YAMATO 	}
1321a022b740SHiroo HAYASHI 	// process implements: FIXME
1322a022b740SHiroo HAYASHI 
1323b762e2b6SHiroo HAYASHI 	createTag (classToken, kind);
1324abe7de79SHiroo HAYASHI 	deleteToken (classToken);
1325c16b8e7aSHiroo HAYASHI 	ptrArrayClear (tagContents);
1326336b0d0dSHiroo HAYASHI 	return c;
13273ae02089SMasatake YAMATO }
13283ae02089SMasatake YAMATO 
1329d6db2d3cSHiroo HAYASHI // constraint_declaration ::= [ static ] constraint constraint_identifier '{' { constraint_block_item } '}'
1330d6db2d3cSHiroo HAYASHI // constraint_prototype ::= [ extern | pure ] [ static ] constraint constraint_identifier ;
processConstraint(tokenInfo * const token,int c)1331d6db2d3cSHiroo HAYASHI static int processConstraint (tokenInfo *const token, int c)
1332d6db2d3cSHiroo HAYASHI {
133325085778SHiroo HAYASHI 	verilogKind kind;
1334d6db2d3cSHiroo HAYASHI 	if (isWordToken (c))
1335d6db2d3cSHiroo HAYASHI 		c = readWordToken (token, c);
1336d6db2d3cSHiroo HAYASHI 	if (c == '{')
133725085778SHiroo HAYASHI 	{
1338d6db2d3cSHiroo HAYASHI 		c = skipPastMatch ("{}");
133925085778SHiroo HAYASHI 		kind = K_CONSTRAINT;
134025085778SHiroo HAYASHI 	}
134125085778SHiroo HAYASHI 	else
134225085778SHiroo HAYASHI 		kind = K_PROTOTYPE;
134325085778SHiroo HAYASHI 	createTag (token, kind);
1344d6db2d3cSHiroo HAYASHI 	return c;
1345d6db2d3cSHiroo HAYASHI }
1346d6db2d3cSHiroo HAYASHI 
processDefine(tokenInfo * const token,int c)1347336b0d0dSHiroo HAYASHI static int processDefine (tokenInfo *const token, int c)
13487bcee217SHiroo HAYASHI {
13497bcee217SHiroo HAYASHI 	/* Bug #961001: Verilog compiler directives are line-based. */
1350b67a1035SHiroo HAYASHI 	if (isWordToken (c))
1351b67a1035SHiroo HAYASHI 	{
1352419aa5d0SHiroo HAYASHI 		c = readWordTokenNoSkip (token, c);
1353220345f7SHiroo HAYASHI 		createTag (token, K_CONSTANT);
1354b67a1035SHiroo HAYASHI 	}
1355419aa5d0SHiroo HAYASHI 	c = skipToNewLine (c);
1356336b0d0dSHiroo HAYASHI 	c = skipWhite (c);
1357336b0d0dSHiroo HAYASHI 	return c;
13587bcee217SHiroo HAYASHI }
13597bcee217SHiroo HAYASHI 
13603abc4388SHiroo HAYASHI // immediate_assertion_statement ::=
13613abc4388SHiroo HAYASHI //     ( assert | asume | cover ) [ #0 | final ] '(' expression ')' block
13623abc4388SHiroo HAYASHI // concurrent_assertion_statement ::=
13633abc4388SHiroo HAYASHI //     ( assert | assume ) property ( property_spec ) action_block
13643abc4388SHiroo HAYASHI //   | expect ( property_spec ) action_block  # ignore : processed as same as "if"
13653abc4388SHiroo HAYASHI //   | cover property ( property_spec ) statement_or_null
13663abc4388SHiroo HAYASHI //   | cover sequence ( [clocking_event ] [ disable iff ( expression_or_dist ) ] sequence_expr ) statement_or_null
13673abc4388SHiroo HAYASHI //   | restrict property ( property_spec ) ;
processAssertion(tokenInfo * const token,int c)1368336b0d0dSHiroo HAYASHI static int processAssertion (tokenInfo *const token, int c)
13690c7db870SHiroo HAYASHI {
13700c7db870SHiroo HAYASHI 	if (vStringLength (currentContext->blockName) > 0)
13710c7db870SHiroo HAYASHI 	{
13720c7db870SHiroo HAYASHI 		vStringCopy (token->name, currentContext->blockName);
13732c5421aaSHiroo HAYASHI 		vStringClear (currentContext->blockName);	// clear block name not to be reused
1374220345f7SHiroo HAYASHI 		createTag (token, K_ASSERTION);
13750c7db870SHiroo HAYASHI 	}
13763abc4388SHiroo HAYASHI 	// skip final | property | sequence
13773abc4388SHiroo HAYASHI 	if (isWordToken (c))
13783abc4388SHiroo HAYASHI 		c = readWordToken (token, c);
13793abc4388SHiroo HAYASHI 	// skip #0
13803abc4388SHiroo HAYASHI 	c = skipDelay (token, c);
13813abc4388SHiroo HAYASHI 	// skip ( ... )
13823abc4388SHiroo HAYASHI 	if (c == '(')
13833abc4388SHiroo HAYASHI 		c = skipPastMatch ("()");
1384336b0d0dSHiroo HAYASHI 	return c;
13850c7db870SHiroo HAYASHI }
13860c7db870SHiroo HAYASHI 
1387a022b740SHiroo HAYASHI // non-ANSI type
1388a022b740SHiroo HAYASHI // ( module | interface | program ) [ static | automatic ] identifier { package_import_declaration } [ parameter_port_list ] ( port { , port } ) ;
1389a022b740SHiroo HAYASHI // ANSI type
13902d0d3dcbSK.Takata // ( module | interface | program ) [ static | automatic ] identifier { package_import_declaration } [ parameter_port_list ] [ ( [ < { (* ... *) } ansi_port_declaration > ] ) ] ;
1391a022b740SHiroo HAYASHI //
1392b762e2b6SHiroo HAYASHI // interface class class_identifier [ parameter_port_list ] [ extends < interface_class_type > ] ;
processDesignElementL(tokenInfo * const token,int c)1393da035c87SHiroo HAYASHI static int processDesignElementL (tokenInfo *const token, int c)
1394da035c87SHiroo HAYASHI {
1395da035c87SHiroo HAYASHI 	verilogKind kind = token->kind;
1396da035c87SHiroo HAYASHI 
1397aeb1f25cSHiroo HAYASHI 	while (isWordToken (c))
1398aeb1f25cSHiroo HAYASHI 	{
1399da035c87SHiroo HAYASHI 		c = readWordToken (token, c);
1400b762e2b6SHiroo HAYASHI 		// interface class
1401b762e2b6SHiroo HAYASHI 		if (token->kind == K_CLASS)
1402b762e2b6SHiroo HAYASHI 			return processClass (token, c, K_IFCLASS);
1403aeb1f25cSHiroo HAYASHI 		// skip static or automatic
1404aeb1f25cSHiroo HAYASHI 		else if (token->kind != K_IGNORE)
1405aeb1f25cSHiroo HAYASHI 			break;
1406da035c87SHiroo HAYASHI 	}
1407aeb1f25cSHiroo HAYASHI 	if (token->kind == K_IDENTIFIER)
1408da035c87SHiroo HAYASHI 		createTag (token, kind);	// identifier
1409da035c87SHiroo HAYASHI 
141021bb515dSHiroo HAYASHI 	// skip package_import_declaration
1411*46313f46SHiroo HAYASHI 	while (isWordToken (c))
141221bb515dSHiroo HAYASHI 	{
141321bb515dSHiroo HAYASHI 		c = readWordToken (token, c);
141421bb515dSHiroo HAYASHI 		if (token->kind == K_IMPORT)
141521bb515dSHiroo HAYASHI 		{
141621bb515dSHiroo HAYASHI 			c = skipToSemiColon (c);
141721bb515dSHiroo HAYASHI 			c = skipWhite (vGetc ());	// skip semicolon
141821bb515dSHiroo HAYASHI 		}
141921bb515dSHiroo HAYASHI 		else
142021bb515dSHiroo HAYASHI 		{
142121bb515dSHiroo HAYASHI 			verbose ("Unexpected input\n");
142221bb515dSHiroo HAYASHI 			return c;
142321bb515dSHiroo HAYASHI 		}
142421bb515dSHiroo HAYASHI 	}
1425da035c87SHiroo HAYASHI 	if (c == '#')	// parameter_port_list
1426da035c87SHiroo HAYASHI 	{
1427da035c87SHiroo HAYASHI 		c = processParameterList (token, c);
1428da035c87SHiroo HAYASHI 
1429da035c87SHiroo HAYASHI 		/* Put found parameters in context */
1430da035c87SHiroo HAYASHI 		verbose ("Putting parameters: %d element(s)\n",
1431da035c87SHiroo HAYASHI 				ptrArrayCount (tagContents));
1432da035c87SHiroo HAYASHI 		for (unsigned int i = 0; i < ptrArrayCount (tagContents); i++)
1433da035c87SHiroo HAYASHI 		{
1434da035c87SHiroo HAYASHI 			tokenInfo *content = ptrArrayItem (tagContents, i);
1435da035c87SHiroo HAYASHI 			createTag (content, K_CONSTANT);
1436da035c87SHiroo HAYASHI 		}
1437da035c87SHiroo HAYASHI 		ptrArrayClear (tagContents);
1438da035c87SHiroo HAYASHI 		// disable parameter property on parameter declaration statement
1439da035c87SHiroo HAYASHI 		currentContext->hasParamList = true;
1440da035c87SHiroo HAYASHI 	}
14417084a858SHiroo HAYASHI 	// Process ANSI/non-ANSI port list in main loop
14420c733c6aSHiroo HAYASHI 	c = processPortList (token, c, true);
1443da035c87SHiroo HAYASHI 	return c;
1444da035c87SHiroo HAYASHI }
1445da035c87SHiroo HAYASHI 
1446a022b740SHiroo HAYASHI // ( checker | property | sequence ) identifier [ ( [ port_list ] ) ] ;
1447a022b740SHiroo HAYASHI // covergroup identifier [ ( [ port_list ] ) ] [ coverage_event ] ;
1448977cdf27SHiroo HAYASHI //   coverage_event ::= clocking_event | with function sample ( ... ) | @@( ... )
1449a022b740SHiroo HAYASHI // package identifier ;
14505b1c62e9SHiroo HAYASHI // modport < identifier ( < ports_declaration > ) > ;
1451cd0963d9SHiroo HAYASHI // [ default | global ] clocking [ identifier ] ( @ identifier | @ ( event_expression ) )
processDesignElementS(tokenInfo * const token,int c)1452da035c87SHiroo HAYASHI static int processDesignElementS (tokenInfo *const token, int c)
14530c7db870SHiroo HAYASHI {
1454220345f7SHiroo HAYASHI 	verilogKind kind = token->kind;
14550c7db870SHiroo HAYASHI 
1456b67a1035SHiroo HAYASHI 	if (isWordToken (c))
1457bd7f3072SHiroo HAYASHI 		c = readWordToken (token, c);
14585b1c62e9SHiroo HAYASHI 	else
14595b1c62e9SHiroo HAYASHI 		return c;
14605b1c62e9SHiroo HAYASHI 
1461a022b740SHiroo HAYASHI 	createTag (token, kind);	// identifier
1462a022b740SHiroo HAYASHI 
1463cd0963d9SHiroo HAYASHI 	/* Get port list if required */
1464a022b740SHiroo HAYASHI 	if (c == '(')	// port_list
14650c7db870SHiroo HAYASHI 	{
1466126aeaefSHiroo HAYASHI 		if (kind == K_MODPORT)
1467126aeaefSHiroo HAYASHI 			c = skipPastMatch ("()");	// ignore port list
14685b1c62e9SHiroo HAYASHI 		else
14690c733c6aSHiroo HAYASHI 			c = processPortList (token, c, false);
14700c7db870SHiroo HAYASHI 	}
1471977cdf27SHiroo HAYASHI 	// skip clocking_event for clocking block or coverage_event for covergroup
1472977cdf27SHiroo HAYASHI 	// "with function sample ()" is processed in the main loop
14735b1c62e9SHiroo HAYASHI 	if (c == '@')
14745b1c62e9SHiroo HAYASHI 		c = skipClockEvent (token, c);
1475336b0d0dSHiroo HAYASHI 	return c;
14760c7db870SHiroo HAYASHI }
147723297f61SMasatake YAMATO 
skipDelay(tokenInfo * token,int c)1478925a79d6SHiroo HAYASHI static int skipDelay (tokenInfo* token, int c)
1479925a79d6SHiroo HAYASHI {
1480925a79d6SHiroo HAYASHI 	if (c == '#')
1481925a79d6SHiroo HAYASHI 	{
1482925a79d6SHiroo HAYASHI 		c = skipWhite (vGetc ());
1483925a79d6SHiroo HAYASHI 		if (c == '(')
1484925a79d6SHiroo HAYASHI 			c = skipPastMatch ("()");
14855a2b57ecSHiroo HAYASHI 		else if (c == '#')
14865a2b57ecSHiroo HAYASHI 			// a dirty hack for "x ##delay1 y[*min:max];"
14875a2b57ecSHiroo HAYASHI 			c = skipToSemiColon (vGetc ());
14885b45dd48SHiroo HAYASHI 		else	// time literals
14895b45dd48SHiroo HAYASHI 		{
14905b45dd48SHiroo HAYASHI 			while (isIdentifierCharacter (c) || c == '.')
149103df6491SHiroo HAYASHI 				c = vGetc ();
1492925a79d6SHiroo HAYASHI 			c = skipWhite (c);
1493925a79d6SHiroo HAYASHI 		}
149483214f95SHiroo HAYASHI 	}
1495925a79d6SHiroo HAYASHI 	return c;
1496925a79d6SHiroo HAYASHI }
1497925a79d6SHiroo HAYASHI 
skipClockEvent(tokenInfo * token,int c)1498268986ceSHiroo HAYASHI static int skipClockEvent (tokenInfo* token, int c)
1499268986ceSHiroo HAYASHI {
1500268986ceSHiroo HAYASHI 	if (c == '@')
1501268986ceSHiroo HAYASHI 	{
1502268986ceSHiroo HAYASHI 		c = skipWhite (vGetc ());
1503977cdf27SHiroo HAYASHI 		// for @@ ( ... ) : coverage_event
1504977cdf27SHiroo HAYASHI 		if (c == '@')
1505977cdf27SHiroo HAYASHI 			c = skipWhite (vGetc ());
1506268986ceSHiroo HAYASHI 		if (c == '(')
150796eaa201SHiroo HAYASHI 			c = skipPastMatch ("()");
1508b67a1035SHiroo HAYASHI 		else if (isWordToken (c))
1509bd7f3072SHiroo HAYASHI 			c = readWordToken (token, c);
1510b67a1035SHiroo HAYASHI 	}
1511268986ceSHiroo HAYASHI 	return c;
1512268986ceSHiroo HAYASHI }
1513268986ceSHiroo HAYASHI 
pushEnumNames(tokenInfo * token,int c)1514de5b45a8SHiroo HAYASHI static int pushEnumNames (tokenInfo* token, int c)
1515de5b45a8SHiroo HAYASHI {
1516de5b45a8SHiroo HAYASHI 	if (c == '{')
1517de5b45a8SHiroo HAYASHI 	{
1518de5b45a8SHiroo HAYASHI 		c = skipWhite (vGetc ());
151983214f95SHiroo HAYASHI 		while (c != '}' && c != EOF)
1520de5b45a8SHiroo HAYASHI 		{
152183214f95SHiroo HAYASHI 			if (!isWordToken (c))
152283214f95SHiroo HAYASHI 			{
152383214f95SHiroo HAYASHI 				verbose ("Unexpected input: %c\n", c);
152483214f95SHiroo HAYASHI 				return c;
152583214f95SHiroo HAYASHI 			}
1526bd7f3072SHiroo HAYASHI 			c = readWordToken (token, c);
152783214f95SHiroo HAYASHI 
1528de5b45a8SHiroo HAYASHI 			token->kind = K_CONSTANT;
1529462ef99aSMasatake YAMATO 			ptrArrayAdd (tagContents, dupToken (token));
1530de5b45a8SHiroo HAYASHI 			verbose ("Pushed enum element \"%s\"\n", vStringValue (token->name));
1531de5b45a8SHiroo HAYASHI 
1532de5b45a8SHiroo HAYASHI 			/* Skip element ranges */
1533de5b45a8SHiroo HAYASHI 			/* TODO Implement element ranges */
1534bd7f3072SHiroo HAYASHI 			c = skipDimension (c);
1535de5b45a8SHiroo HAYASHI 
1536de5b45a8SHiroo HAYASHI 			/* Skip value assignments */
1537de5b45a8SHiroo HAYASHI 			if (c == '=')
1538de5b45a8SHiroo HAYASHI 				c = skipExpression (vGetc ());
1539de5b45a8SHiroo HAYASHI 
1540de5b45a8SHiroo HAYASHI 			/* Skip comma */
1541de5b45a8SHiroo HAYASHI 			if (c == ',')
1542de5b45a8SHiroo HAYASHI 				c = skipWhite (vGetc ());
1543de5b45a8SHiroo HAYASHI 		}
154483214f95SHiroo HAYASHI 		c = skipWhite (vGetc ());	// skip '}'
1545de5b45a8SHiroo HAYASHI 	}
1546de5b45a8SHiroo HAYASHI 	return c;
1547de5b45a8SHiroo HAYASHI }
1548de5b45a8SHiroo HAYASHI 
154931730736SHiroo HAYASHI // create a list of struct/union members
pushMembers(tokenInfo * token,int c)155031730736SHiroo HAYASHI static int pushMembers (tokenInfo* token, int c)
155131730736SHiroo HAYASHI {
155231730736SHiroo HAYASHI 	if (c == '{')
155331730736SHiroo HAYASHI 	{
155431730736SHiroo HAYASHI 		c = skipWhite (vGetc ());
155554b431e2SHiroo HAYASHI 		while (c != '}' && c != EOF)
155631730736SHiroo HAYASHI 		{
155731730736SHiroo HAYASHI 			verilogKind kind = K_UNDEFINED;	// set kind of context for processType()
1558a6f873e6SHiroo HAYASHI 			bool not_used;
15593a0c0023SHiroo HAYASHI 			if (!isWordToken (c))
15603a0c0023SHiroo HAYASHI 			{
15613a0c0023SHiroo HAYASHI 				verbose ("Unexpected input: %c\n", c);
15623a0c0023SHiroo HAYASHI 				return c;
15633a0c0023SHiroo HAYASHI 			}
1564bd7f3072SHiroo HAYASHI 			c = readWordToken (token, c);
156531730736SHiroo HAYASHI 
1566a6f873e6SHiroo HAYASHI 			c = processType (token, c, &kind, &not_used);
156754b431e2SHiroo HAYASHI 			while (true)
156831730736SHiroo HAYASHI 			{
156931730736SHiroo HAYASHI 				token->kind = K_MEMBER;
157031730736SHiroo HAYASHI 				ptrArrayAdd (tagContents, dupToken (token));
157131730736SHiroo HAYASHI 				verbose ("Pushed struct/union member \"%s\"\n", vStringValue (token->name));
157231730736SHiroo HAYASHI 
157331730736SHiroo HAYASHI 				/* Skip unpacked dimensions */
157483214f95SHiroo HAYASHI 				c = skipDimension (c);
157531730736SHiroo HAYASHI 
157631730736SHiroo HAYASHI 				/* Skip value assignments */
157731730736SHiroo HAYASHI 				if (c == '=')
157831730736SHiroo HAYASHI 					c = skipExpression (vGetc ());
157931730736SHiroo HAYASHI 
158083214f95SHiroo HAYASHI 				if (c != ',' || c == EOF)
158183214f95SHiroo HAYASHI 					break;		// should be ';'
158231730736SHiroo HAYASHI 
158383214f95SHiroo HAYASHI 				c = skipWhite (vGetc ());	// skip ','
1584b67a1035SHiroo HAYASHI 				if (isWordToken (c))
1585bd7f3072SHiroo HAYASHI 					c = readWordToken (token, c);
158631730736SHiroo HAYASHI 				else
158731730736SHiroo HAYASHI 				{
158831730736SHiroo HAYASHI 					verbose ("Unexpected input.\n");
158931730736SHiroo HAYASHI 					break;
159031730736SHiroo HAYASHI 				}
159154b431e2SHiroo HAYASHI 			}
159231730736SHiroo HAYASHI 			/* Skip semicolon */
159331730736SHiroo HAYASHI 			if (c == ';')
159431730736SHiroo HAYASHI 				c = skipWhite (vGetc ());
159531730736SHiroo HAYASHI 			/* End of enum elements list */
159654b431e2SHiroo HAYASHI 		}
159783214f95SHiroo HAYASHI 		c = skipWhite (vGetc ());	// skip '}'
159831730736SHiroo HAYASHI 	}
159931730736SHiroo HAYASHI 	return c;
160031730736SHiroo HAYASHI }
160131730736SHiroo HAYASHI 
1602dc7ffa23SHiroo HAYASHI // input
1603dc7ffa23SHiroo HAYASHI //   kind: kind of context
1604dc7ffa23SHiroo HAYASHI // output
1605dc7ffa23SHiroo HAYASHI //   kind: kind of type
1606dc7ffa23SHiroo HAYASHI //   token: identifier token (unless K_IDENTIFIER nor K_UNDEFINED)
processType(tokenInfo * token,int c,verilogKind * kind,bool * with)1607a6f873e6SHiroo HAYASHI static int processType (tokenInfo* token, int c, verilogKind* kind, bool* with)
1608dc7ffa23SHiroo HAYASHI {
1609dc7ffa23SHiroo HAYASHI 	verilogKind actualKind = K_UNDEFINED;
1610d8576f6dSHiroo HAYASHI 	tokenInfo *tokenSaved;
1611a6f873e6SHiroo HAYASHI 	*with = false;
161254b431e2SHiroo HAYASHI 	do
1613dc7ffa23SHiroo HAYASHI 	{
161483214f95SHiroo HAYASHI 		c = skipDimension (c);
1615dc7ffa23SHiroo HAYASHI 		c = skipDelay (token, c);	// class parameter #(...)
1616dc7ffa23SHiroo HAYASHI 		if (c == '{')	// skip enum, struct, or union member
1617de5b45a8SHiroo HAYASHI 		{
1618de5b45a8SHiroo HAYASHI 			if (*kind == K_ENUM)
1619de5b45a8SHiroo HAYASHI 				c = pushEnumNames (token, c);
162031730736SHiroo HAYASHI 			else if (*kind == K_STRUCT)
162131730736SHiroo HAYASHI 				c = pushMembers (token, c);
162231730736SHiroo HAYASHI 			else	// for a nested structure
162396eaa201SHiroo HAYASHI 				c = skipPastMatch ("{}");
1624de5b45a8SHiroo HAYASHI 		}
16258a619ad7SHiroo HAYASHI 		c = skipDimension (c);
1626453a3983SHiroo HAYASHI 		c = skipMacro (c, token);
1627dc7ffa23SHiroo HAYASHI 
1628d8576f6dSHiroo HAYASHI 		// break on ',', ';', ')', '}', or other unexpected charactors
1629b67a1035SHiroo HAYASHI 		if (!isWordToken (c))
1630dc7ffa23SHiroo HAYASHI 			break;
1631d8576f6dSHiroo HAYASHI 
1632d8576f6dSHiroo HAYASHI 		tokenSaved = dupToken (token);
1633bd7f3072SHiroo HAYASHI 		c = readWordToken (token, c);
1634d8576f6dSHiroo HAYASHI 		// break on "with"
1635d8576f6dSHiroo HAYASHI 		if (token->kind == K_WITH)
1636d8576f6dSHiroo HAYASHI 		{
16379a7cd5c2SHiroo HAYASHI  			swapToken (token, tokenSaved);
16389a7cd5c2SHiroo HAYASHI 			deleteToken (tokenSaved);
1639a6f873e6SHiroo HAYASHI 			*with = true;	// inform to caller
1640d8576f6dSHiroo HAYASHI 			break;
1641d8576f6dSHiroo HAYASHI 		}
1642d8576f6dSHiroo HAYASHI 		deleteToken (tokenSaved);
1643dc7ffa23SHiroo HAYASHI 
1644dc7ffa23SHiroo HAYASHI 		// fix kind of user defined type
1645dc7ffa23SHiroo HAYASHI 		if (*kind == K_IDENTIFIER)
1646dc7ffa23SHiroo HAYASHI 		{
1647dc7ffa23SHiroo HAYASHI 			if (token->kind == K_NET)
1648dc7ffa23SHiroo HAYASHI 				actualKind = K_NET;
1649dc7ffa23SHiroo HAYASHI 			else if (token->kind == K_REGISTER)
1650dc7ffa23SHiroo HAYASHI 				actualKind = K_REGISTER;
1651622e7342SHiroo HAYASHI 			else if (token->kind == K_PORT)
1652622e7342SHiroo HAYASHI 				actualKind = K_PORT;
1653dc7ffa23SHiroo HAYASHI 			else if (token->kind == K_IDENTIFIER)
1654dc7ffa23SHiroo HAYASHI 			{	// identifier of a user defined type
1655dc7ffa23SHiroo HAYASHI 				*kind = K_REGISTER;	// FIXME: consider kind of the user defined type
1656dc7ffa23SHiroo HAYASHI 				break;
1657dc7ffa23SHiroo HAYASHI 			}
1658dc7ffa23SHiroo HAYASHI 			else
1659dc7ffa23SHiroo HAYASHI 			{
1660d6db2d3cSHiroo HAYASHI 				verbose ("Unexpected input\n");	// FIXME: x dist {}, with
1661dc7ffa23SHiroo HAYASHI 				break;
1662dc7ffa23SHiroo HAYASHI 			}
1663dc7ffa23SHiroo HAYASHI 		}
166454b431e2SHiroo HAYASHI 	} while (c != '`' && c != EOF);	// break on compiler directive
1665dc7ffa23SHiroo HAYASHI 
1666dc7ffa23SHiroo HAYASHI 	// skip unpacked dimension (or packed dimension after type-words)
1667dc7ffa23SHiroo HAYASHI 	c = skipDimension (skipWhite (c));
1668dc7ffa23SHiroo HAYASHI 
16693c80bb1eSHiroo HAYASHI 	if (*kind == K_UNDEFINED && *kind != K_PORT)
1670dc7ffa23SHiroo HAYASHI 		*kind = actualKind;
1671dc7ffa23SHiroo HAYASHI 	return c;
1672dc7ffa23SHiroo HAYASHI }
1673dc7ffa23SHiroo HAYASHI 
167435d31ab3SHiroo HAYASHI // class_type ::=
1675056a5848SK.Takata //       ps_class_identifier [ # ( ... ) ] { :: class_identifier [ # ( ... ) ] }
1676326d7444SHiroo HAYASHI // "interface_identifier ." is also handled
skipClassType(tokenInfo * token,int c)167735d31ab3SHiroo HAYASHI static int skipClassType (tokenInfo* token, int c)
167835d31ab3SHiroo HAYASHI {
16795cd8612dSHiroo HAYASHI 	while (c == '#' || c == ':' || c == '.')
168035d31ab3SHiroo HAYASHI 	{
168135d31ab3SHiroo HAYASHI 		if (c == '#')
168235d31ab3SHiroo HAYASHI 		{
168335d31ab3SHiroo HAYASHI 			c = skipWhite (vGetc ());
168435d31ab3SHiroo HAYASHI 			// a dirty hack for "x ##delay1 y[*min:max];"
168535d31ab3SHiroo HAYASHI 			if (c == '#')
168635d31ab3SHiroo HAYASHI 				return skipToSemiColon (vGetc ());
168735d31ab3SHiroo HAYASHI 			c = skipPastMatch ("()");
168835d31ab3SHiroo HAYASHI 		}
16895cd8612dSHiroo HAYASHI 		else if (c == ':')
169035d31ab3SHiroo HAYASHI 		{
169135d31ab3SHiroo HAYASHI 			c = skipWhite (vGetc ());
1692fdd10e5cSHiroo HAYASHI 			if (c != ':')
169335d31ab3SHiroo HAYASHI 			{
1694fdd10e5cSHiroo HAYASHI 				verbose ("Unexpected input.\n");
169535d31ab3SHiroo HAYASHI 				vUngetc (c);
169635d31ab3SHiroo HAYASHI 				return ':';
169735d31ab3SHiroo HAYASHI 			}
169835d31ab3SHiroo HAYASHI 			c = skipWhite (vGetc ());
169935d31ab3SHiroo HAYASHI 			if (isWordToken (c))
170035d31ab3SHiroo HAYASHI 				c = readWordToken (token, c);
170135d31ab3SHiroo HAYASHI 		}
1702326d7444SHiroo HAYASHI 		else	// c == '.' : interface_identifier .
17035cd8612dSHiroo HAYASHI 		{
17045cd8612dSHiroo HAYASHI 			c = skipWhite (vGetc ());
17055cd8612dSHiroo HAYASHI 			if (isWordToken (c))
17065cd8612dSHiroo HAYASHI 				c = readWordToken (token, c);
17075cd8612dSHiroo HAYASHI 		}
170835d31ab3SHiroo HAYASHI 	}
170935d31ab3SHiroo HAYASHI 	return c;
171035d31ab3SHiroo HAYASHI }
171135d31ab3SHiroo HAYASHI 
1712622e7342SHiroo HAYASHI // Tag a list of identifiers
17135cd8612dSHiroo HAYASHI // data_type :: =
17145cd8612dSHiroo HAYASHI //   ...
17155cd8612dSHiroo HAYASHI //   | virtual [ interface ] identifier [ # ( [ ... ] ) ]  [ . identifier ]
17165cd8612dSHiroo HAYASHI //   | [ class_type :: | identifier :: | $unit :: ] identifier { [ ... ] }
1717056a5848SK.Takata //   | [ identifier :: | $unit :: ] identifier [ # ( ... ) ] { :: identifier [ # ( ... ) ] }
17185cd8612dSHiroo HAYASHI //   | ...
17195cd8612dSHiroo HAYASHI //
1720622e7342SHiroo HAYASHI //   mayPortDecl: may be a ANSI port declaration.  true for module, interface, or program.
tagIdentifierList(tokenInfo * const token,int c,verilogKind kind,bool mayPortDecl)1721622e7342SHiroo HAYASHI static int tagIdentifierList (tokenInfo *const token, int c, verilogKind kind, bool mayPortDecl)
1722622e7342SHiroo HAYASHI {
1723622e7342SHiroo HAYASHI 	bool first_port = true;
1724622e7342SHiroo HAYASHI 	bool enableTag = true;
1725622e7342SHiroo HAYASHI 	verilogKind localKind;
1726622e7342SHiroo HAYASHI 	bool not_used;
1727622e7342SHiroo HAYASHI 
17285cd8612dSHiroo HAYASHI 	while (c != ')' && c != EOF)	// skip empty port, "()"
1729622e7342SHiroo HAYASHI 	{
1730622e7342SHiroo HAYASHI 		// skip attribute_instance: (* ... *)
1731622e7342SHiroo HAYASHI 		if (c == '(')
1732622e7342SHiroo HAYASHI 			c = skipPastMatch ("()");
1733622e7342SHiroo HAYASHI 
17345cd8612dSHiroo HAYASHI 		// skip port direction, "virtual", or "interface"
17355cd8612dSHiroo HAYASHI 		while (isWordToken (c))
17365cd8612dSHiroo HAYASHI 		{
1737622e7342SHiroo HAYASHI 			c = readWordToken (token, c);
17385cd8612dSHiroo HAYASHI 			if (token->kind == K_PORT || token->kind == K_IGNORE || token->kind == K_INTERFACE)
17395cd8612dSHiroo HAYASHI 				mayPortDecl = false;	// now never be a non-ANSI port
17405cd8612dSHiroo HAYASHI 			else
17415cd8612dSHiroo HAYASHI 				break;
17425cd8612dSHiroo HAYASHI 		}
17435cd8612dSHiroo HAYASHI 		if (token->kind == K_IDENTIFIER)
17440c733c6aSHiroo HAYASHI 			c = skipClassType (token, c);
17458a07c37aSHiroo HAYASHI 		c = skipMacro (c, token);	// `ifdef, `else, `endif, etc. (between identifiers)
17460c733c6aSHiroo HAYASHI 
17475cd8612dSHiroo HAYASHI 		if (isWordToken (c))
17485cd8612dSHiroo HAYASHI 		{
17495cd8612dSHiroo HAYASHI 			c = readWordToken (token, c);
17505cd8612dSHiroo HAYASHI 			if (token->kind == K_IDENTIFIER)
17515cd8612dSHiroo HAYASHI 			{
17525cd8612dSHiroo HAYASHI 				mayPortDecl = false;
17535cd8612dSHiroo HAYASHI 				c = skipClassType (token, c);
17545cd8612dSHiroo HAYASHI 			}
17555cd8612dSHiroo HAYASHI 		}
17565cd8612dSHiroo HAYASHI 		// aoid tagging enum and struct items
17570c733c6aSHiroo HAYASHI 		localKind = token->kind == K_ENUM || token->kind == K_STRUCT ? K_PORT : token->kind;
1758622e7342SHiroo HAYASHI 		c = processType (token, c, &localKind, &not_used);
1759622e7342SHiroo HAYASHI 
1760622e7342SHiroo HAYASHI 		// LRM 23.2.2.3 Rules for determining port kind, data type, and direction
1761622e7342SHiroo HAYASHI 		// If the direction, port kind, and data type are all omitted for
1762622e7342SHiroo HAYASHI 		// the first port in the port list, ... non-ANSI style, ...
1763622e7342SHiroo HAYASHI 		if (mayPortDecl && first_port)
1764622e7342SHiroo HAYASHI 		{
1765622e7342SHiroo HAYASHI 			first_port = false;
1766622e7342SHiroo HAYASHI 			if (localKind == K_IDENTIFIER)
1767622e7342SHiroo HAYASHI 				enableTag = false;	// don't tag for non-ANSI port
1768622e7342SHiroo HAYASHI 		}
1769622e7342SHiroo HAYASHI 		if (enableTag && token->kind == K_IDENTIFIER)
1770622e7342SHiroo HAYASHI 			createTag (token, kind);
1771622e7342SHiroo HAYASHI 
1772622e7342SHiroo HAYASHI 		if (c == '=')
1773622e7342SHiroo HAYASHI 			c = skipExpression (vGetc ());
1774622e7342SHiroo HAYASHI 
1775453a3983SHiroo HAYASHI 		c = skipMacro (c, token);	// `ifdef, `else, `endif, etc. (before comma)
1776622e7342SHiroo HAYASHI 		if (c != ',' || c == EOF)
1777622e7342SHiroo HAYASHI 			break;
1778622e7342SHiroo HAYASHI 		c = skipWhite (vGetc ());	// skip ','
1779453a3983SHiroo HAYASHI 		c = skipMacro (c, token);	// `ifdef, `else, `endif, etc. (after comma)
1780622e7342SHiroo HAYASHI 	}
1781622e7342SHiroo HAYASHI 	return c;
1782622e7342SHiroo HAYASHI }
1783622e7342SHiroo HAYASHI 
tagNameList(tokenInfo * token,int c,verilogKind kind)1784b449e8a0SHiroo HAYASHI static int tagNameList (tokenInfo* token, int c, verilogKind kind)
17853ae02089SMasatake YAMATO {
178635d31ab3SHiroo HAYASHI 	c = skipClassType (token, c);
1787fdd10e5cSHiroo HAYASHI 	if (c == ':' || c == ';')	// ## (cycle delay) or unexpected input
178835d31ab3SHiroo HAYASHI 		return c;
178935d31ab3SHiroo HAYASHI 
1790dc7ffa23SHiroo HAYASHI 	// skip drive|charge strength or type_reference, dimensions, and delay for net
17913ae02089SMasatake YAMATO 	if (c == '(')
17923ae02089SMasatake YAMATO 		c = skipPastMatch ("()");
179396eaa201SHiroo HAYASHI 	c = skipDimension (c);
1794dc7ffa23SHiroo HAYASHI 	if (c == '.')
17953087f342SHiroo HAYASHI 		return c;	// foo[...].bar = ..;
1796925a79d6SHiroo HAYASHI 	c = skipDelay (token, c);
17973ae02089SMasatake YAMATO 
179854b431e2SHiroo HAYASHI 	while (c != EOF)
17993ae02089SMasatake YAMATO 	{
1800a6f873e6SHiroo HAYASHI 		bool with = false;
1801a6f873e6SHiroo HAYASHI 		c = processType (token, c, &kind, &with);	// update token and kind
18023ae02089SMasatake YAMATO 
1803a6f873e6SHiroo HAYASHI 		if (c == '=' || c == ',' || c == ';' || c == ')' || c == '`' || with)
1804dc7ffa23SHiroo HAYASHI 		{
1805b449e8a0SHiroo HAYASHI 			// ignore an empty token or procedual assignment: foo = bar;
1806b449e8a0SHiroo HAYASHI 			if (kind != K_UNDEFINED && kind != K_IDENTIFIER && token->kind != K_UNDEFINED)
1807dc7ffa23SHiroo HAYASHI 				createTag (token, kind);
1808dc7ffa23SHiroo HAYASHI 			if (c == '=')
1809dc7ffa23SHiroo HAYASHI 				c = skipExpression (c);
1810dc7ffa23SHiroo HAYASHI 		}
181105f57079Sheyun 		else if (c == '(' || c == '[')	// should be instance
181205f57079Sheyun 		{
181305f57079Sheyun 			c = skipDimension (c); // name_of_instance {unpacked_dimension}
181405f57079Sheyun 			c = skipPastMatch ("()"); // list_of_port_connections
181505f57079Sheyun 
181605f57079Sheyun 			// if without the next "if" clause, get a instance named: `add_t from the following example
181705f57079Sheyun 			// var `add_t(foo) = '0;
181805f57079Sheyun 			if (c == ';' || c == ',')
181905f57079Sheyun 			{
182005f57079Sheyun 				verbose ("find instance: %s with kind %s\n", vStringValue (token->name), getNameForKind (K_INSTANCE));
182105f57079Sheyun 				createTag (token, K_INSTANCE);
182205f57079Sheyun 			}
182305f57079Sheyun 		}
1824453a3983SHiroo HAYASHI 		c = skipMacro (c, token);	// `ifdef, `else, `endif, etc. (before comma)
1825dc7ffa23SHiroo HAYASHI 		if (c != ',' || c == EOF)
1826dc7ffa23SHiroo HAYASHI 			break;
182783214f95SHiroo HAYASHI 		c = skipWhite (vGetc ());	// skip ','
1828453a3983SHiroo HAYASHI 		c = skipMacro (c, token);	// `ifdef, `else, `endif, etc. (after comma)
182954b431e2SHiroo HAYASHI 	}
18303087f342SHiroo HAYASHI 	return c;
18313ae02089SMasatake YAMATO }
18323ae02089SMasatake YAMATO 
findTag(tokenInfo * const token,int c)183361530bb5SHiroo HAYASHI static int findTag (tokenInfo *const token, int c)
18343ae02089SMasatake YAMATO {
183596047d1aSVitor Antunes 	verbose ("Checking token %s of kind %d\n", vStringValue (token->name), token->kind);
183696047d1aSVitor Antunes 
1837f483ab2aSHiroo HAYASHI 	switch (token->kind)
18383ae02089SMasatake YAMATO 	{
1839f483ab2aSHiroo HAYASHI 		case K_CONSTANT:
1840f483ab2aSHiroo HAYASHI 		case K_EVENT:
18412e2a1af9SHiroo HAYASHI 		case K_LOCALPARAM:
1842f483ab2aSHiroo HAYASHI 		case K_NET:
18432e2a1af9SHiroo HAYASHI 		case K_PARAMETER:
1844f483ab2aSHiroo HAYASHI 		case K_PORT:
1845f483ab2aSHiroo HAYASHI 		case K_REGISTER:
1846cd0963d9SHiroo HAYASHI 			if (token->kind == K_PORT && currentContext->kind == K_CLOCKING)
18474257cd2eSHiroo HAYASHI 				c = skipToSemiColon (c); // clocking items are not port definitions
1848cd0963d9SHiroo HAYASHI 			else
1849b449e8a0SHiroo HAYASHI 				c = tagNameList (token, c, token->kind);
1850f483ab2aSHiroo HAYASHI 			break;
18518ccc1123SHiroo HAYASHI 		case K_IDENTIFIER:
1852139e7cedSHiroo HAYASHI 			{
1853fdd10e5cSHiroo HAYASHI 				if (c == '[')	// for a case label foo[x]:
1854fdd10e5cSHiroo HAYASHI 					c = skipPastMatch ("[]");
1855fdd10e5cSHiroo HAYASHI 
1856628374a2SHiroo HAYASHI 				if (c == ':')
185761530bb5SHiroo HAYASHI 					; /* label */
1858fdd10e5cSHiroo HAYASHI 				else if (c == ',' || c == '{')	// "foo, ..." or "coverpoint foo { ... }"
1859336b0d0dSHiroo HAYASHI 					c = skipWhite (vGetc ());
1860a6f873e6SHiroo HAYASHI 				else if (c == '(')	// task, function, or method call
1861a6f873e6SHiroo HAYASHI 					c = skipPastMatch ("()");
1862fdd10e5cSHiroo HAYASHI 				else if (c == '=')	// assignment
1863336b0d0dSHiroo HAYASHI 					c = skipExpression (skipWhite (vGetc ()));
1864628374a2SHiroo HAYASHI 				else
1865b449e8a0SHiroo HAYASHI 					c = tagNameList (token, c, token->kind); /* user defined type */
1866628374a2SHiroo HAYASHI 			}
1867f483ab2aSHiroo HAYASHI 			break;
1868f483ab2aSHiroo HAYASHI 		case K_CLASS:
1869b762e2b6SHiroo HAYASHI 			c = processClass (token, c, K_CLASS);
1870f483ab2aSHiroo HAYASHI 			break;
1871f483ab2aSHiroo HAYASHI 		case K_TYPEDEF:
1872d8576f6dSHiroo HAYASHI 		case K_NETTYPE:
1873336b0d0dSHiroo HAYASHI 			c = processTypedef (token, c);
1874f483ab2aSHiroo HAYASHI 			break;
1875f483ab2aSHiroo HAYASHI 		case K_ENUM:
1876336b0d0dSHiroo HAYASHI 			c = processEnum (token, c);
1877f483ab2aSHiroo HAYASHI 			break;
1878f483ab2aSHiroo HAYASHI 		case K_STRUCT:
1879336b0d0dSHiroo HAYASHI 			c = processStruct (token, c);
1880f483ab2aSHiroo HAYASHI 			break;
1881f483ab2aSHiroo HAYASHI 		case K_PROTOTYPE:
18828e46c07bSHiroo HAYASHI 		case K_IMPORT:
1883977cdf27SHiroo HAYASHI 		case K_WITH:
1884f483ab2aSHiroo HAYASHI 			currentContext->prototype = true;
1885f483ab2aSHiroo HAYASHI 			break;
1886f483ab2aSHiroo HAYASHI 
1887da035c87SHiroo HAYASHI 		case K_INTERFACE:
1888da035c87SHiroo HAYASHI 		case K_MODULE:
1889da035c87SHiroo HAYASHI 		case K_PROGRAM:
1890da035c87SHiroo HAYASHI 			c = processDesignElementL (token, c);
1891da035c87SHiroo HAYASHI 			break;
18922c5421aaSHiroo HAYASHI 		case K_CHECKER:
1893cd0963d9SHiroo HAYASHI 		case K_CLOCKING:
1894f483ab2aSHiroo HAYASHI 		case K_COVERGROUP:
1895f483ab2aSHiroo HAYASHI 		case K_MODPORT:
1896f483ab2aSHiroo HAYASHI 		case K_PACKAGE:
1897f483ab2aSHiroo HAYASHI 		case K_PROPERTY:
18982c5421aaSHiroo HAYASHI 		case K_SEQUENCE:
1899da035c87SHiroo HAYASHI 			c = processDesignElementS (token, c);
1900f483ab2aSHiroo HAYASHI 			break;
1901b56d22dcSHiroo HAYASHI 		case K_END_DE:
1902336b0d0dSHiroo HAYASHI 			c = dropEndContext (token, c);
1903b56d22dcSHiroo HAYASHI 			break;
19044aaf731aSHiroo HAYASHI 		case K_BLOCK:
1905336b0d0dSHiroo HAYASHI 			c = processBlock (token, c);
190689026706SHiroo HAYASHI 			break;
1907f483ab2aSHiroo HAYASHI 		case K_END:
1908336b0d0dSHiroo HAYASHI 			c = processEnd (token, c);
1909f483ab2aSHiroo HAYASHI 			break;
1910f483ab2aSHiroo HAYASHI 		case K_FUNCTION:
1911f483ab2aSHiroo HAYASHI 		case K_TASK:
1912336b0d0dSHiroo HAYASHI 			c = processFunction (token, c);
1913f483ab2aSHiroo HAYASHI 			break;
1914f483ab2aSHiroo HAYASHI 		case K_ASSERTION:
1915336b0d0dSHiroo HAYASHI 			c = processAssertion (token, c);
1916f483ab2aSHiroo HAYASHI 			break;
1917d6db2d3cSHiroo HAYASHI 		case K_CONSTRAINT:
1918d6db2d3cSHiroo HAYASHI 			c = processConstraint (token, c);
1919d6db2d3cSHiroo HAYASHI 			break;
1920f483ab2aSHiroo HAYASHI 
1921f483ab2aSHiroo HAYASHI 		case K_DEFINE:
1922336b0d0dSHiroo HAYASHI 			c = processDefine (token, c);
1923f483ab2aSHiroo HAYASHI 			break;
1924f483ab2aSHiroo HAYASHI 
1925f483ab2aSHiroo HAYASHI 		case K_IGNORE:
1926b56d22dcSHiroo HAYASHI 			break;
1927f483ab2aSHiroo HAYASHI 		default:
1928f483ab2aSHiroo HAYASHI 			verbose ("Unexpected kind->token %d\n", token->kind);
19293ae02089SMasatake YAMATO 	}
193061530bb5SHiroo HAYASHI 	return c;
19313ae02089SMasatake YAMATO }
19323ae02089SMasatake YAMATO 
findVerilogTags(void)19333ae02089SMasatake YAMATO static void findVerilogTags (void)
19343ae02089SMasatake YAMATO {
19353ae02089SMasatake YAMATO 	tokenInfo *const token = newToken ();
193661530bb5SHiroo HAYASHI 	int c = skipWhite (vGetc ());
19373ae02089SMasatake YAMATO 	currentContext = newToken ();
1938af35bd7cSHiroo HAYASHI 	fieldTable = isInputLanguage (Lang_verilog) ? VerilogFields : SystemVerilogFields;
1939462ef99aSMasatake YAMATO 	ptrArrayClear (tagContents);
19403ae02089SMasatake YAMATO 
19413ae02089SMasatake YAMATO 	while (c != EOF)
19423ae02089SMasatake YAMATO 	{
19433ae02089SMasatake YAMATO 		switch (c)
19443ae02089SMasatake YAMATO 		{
19453ae02089SMasatake YAMATO 			case ':':
19465a2b57ecSHiroo HAYASHI 				/* Store current block name whenever a : is found
19475a2b57ecSHiroo HAYASHI 				 * This is used later by any tag type that requires this information */
19483ae02089SMasatake YAMATO 				vStringCopy (currentContext->blockName, token->name);
194961530bb5SHiroo HAYASHI 				c = skipWhite (vGetc ());
19503ae02089SMasatake YAMATO 				break;
19513ae02089SMasatake YAMATO 			case ';':
19529a433176SVitor Antunes 				/* Drop context on prototypes because they don't have an
19539a433176SVitor Antunes 				 * end statement */
195496047d1aSVitor Antunes 				if (currentContext->scope && currentContext->scope->prototype)
195553ae1d47SHiroo HAYASHI 					dropContext ();
1956942da152SHiroo HAYASHI 
195796047d1aSVitor Antunes 				/* Prototypes end at the end of statement */
1958ce990805SThomas Braun 				currentContext->prototype = false;
195961530bb5SHiroo HAYASHI 				c = skipWhite (vGetc ());
19608ccc1123SHiroo HAYASHI 				break;
1961942da152SHiroo HAYASHI 			case '(':	// ignore locally declared variables in a for-loop (LRM 12.7.1)
1962942da152SHiroo HAYASHI 				c = skipPastMatch ("()");;
1963942da152SHiroo HAYASHI 				break;
1964942da152SHiroo HAYASHI 			case '{':
1965942da152SHiroo HAYASHI 				c = skipPastMatch ("{}");;
1966942da152SHiroo HAYASHI 				break;
19675b45dd48SHiroo HAYASHI 			case '#':
19685b45dd48SHiroo HAYASHI 				c = skipDelay (token, c);
19695b45dd48SHiroo HAYASHI 				break;
1970268986ceSHiroo HAYASHI 			case '@':
1971268986ceSHiroo HAYASHI 				c = skipClockEvent (token, c);
1972268986ceSHiroo HAYASHI 				break;
19738e46c07bSHiroo HAYASHI 			case '"':
19748e46c07bSHiroo HAYASHI 				c = skipString (c);
19758e46c07bSHiroo HAYASHI 				break;
19763ae02089SMasatake YAMATO 			default :
1977b67a1035SHiroo HAYASHI 				if (isWordToken (c))
19783ae02089SMasatake YAMATO 				{
1979419aa5d0SHiroo HAYASHI 					c = readWordTokenNoSkip (token, c);
1980edc75f8cSHiroo HAYASHI 					if (token->kind == K_DIRECTIVE)
198161530bb5SHiroo HAYASHI 					{
1982edc75f8cSHiroo HAYASHI 						// Skip compiler directives which are line-based.
1983419aa5d0SHiroo HAYASHI 						c = skipToNewLine (c);
1984419aa5d0SHiroo HAYASHI 						c = skipWhite (c);
19853ae02089SMasatake YAMATO 					}
198661530bb5SHiroo HAYASHI 					else if (token->kind != K_UNDEFINED)
1987419aa5d0SHiroo HAYASHI 						c = findTag (token, skipWhite (c));
198861530bb5SHiroo HAYASHI 				}
198961530bb5SHiroo HAYASHI 				else
199061530bb5SHiroo HAYASHI 					c = skipWhite (vGetc ());
19913ae02089SMasatake YAMATO 		}
19923ae02089SMasatake YAMATO 	}
19933ae02089SMasatake YAMATO 	deleteToken (token);
19943ae02089SMasatake YAMATO 	pruneTokens (currentContext);
19953ae02089SMasatake YAMATO 	currentContext = NULL;
19963ae02089SMasatake YAMATO }
19973ae02089SMasatake YAMATO 
VerilogParser(void)19983ae02089SMasatake YAMATO extern parserDefinition* VerilogParser (void)
19993ae02089SMasatake YAMATO {
20003ae02089SMasatake YAMATO 	static const char *const extensions [] = { "v", NULL };
20013ae02089SMasatake YAMATO 	parserDefinition* def = parserNew ("Verilog");
200209ae690fSMasatake YAMATO 	def->kindTable  = VerilogKinds;
20033db72c21SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (VerilogKinds);
20042e2a1af9SHiroo HAYASHI 	def->fieldTable = VerilogFields;
20052e2a1af9SHiroo HAYASHI 	def->fieldCount = ARRAY_SIZE (VerilogFields);
20063ae02089SMasatake YAMATO 	def->extensions = extensions;
20073ae02089SMasatake YAMATO 	def->parser     = findVerilogTags;
20083ae02089SMasatake YAMATO 	def->initialize = initializeVerilog;
20093ae02089SMasatake YAMATO 	return def;
20103ae02089SMasatake YAMATO }
20113ae02089SMasatake YAMATO 
SystemVerilogParser(void)20123ae02089SMasatake YAMATO extern parserDefinition* SystemVerilogParser (void)
20133ae02089SMasatake YAMATO {
20143ae02089SMasatake YAMATO 	static const char *const extensions [] = { "sv", "svh", "svi", NULL };
20153ae02089SMasatake YAMATO 	parserDefinition* def = parserNew ("SystemVerilog");
201609ae690fSMasatake YAMATO 	def->kindTable  = SystemVerilogKinds;
20173db72c21SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (SystemVerilogKinds);
2018af35bd7cSHiroo HAYASHI 	def->fieldTable = SystemVerilogFields;
2019af35bd7cSHiroo HAYASHI 	def->fieldCount = ARRAY_SIZE (SystemVerilogFields);
20203ae02089SMasatake YAMATO 	def->extensions = extensions;
20213ae02089SMasatake YAMATO 	def->parser     = findVerilogTags;
20223ae02089SMasatake YAMATO 	def->initialize = initializeSystemVerilog;
20233ae02089SMasatake YAMATO 	return def;
20243ae02089SMasatake YAMATO }
2025