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, ¬_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, ¬_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, ¬_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