• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nickg / nvc / 25986469887

17 May 2026 08:44AM UTC coverage: 92.22% (-0.04%) from 92.258%
25986469887

push

github

nickg
Add PicoRV32 to regression tests

78454 of 85073 relevant lines covered (92.22%)

648774.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.68
/src/vlog/vlog-parse.c
1
//
2
//  Copyright (C) 2024-2026  Nick Gasson
3
//
4
//  This program is free software: you can redistribute it and/or modify
5
//  it under the terms of the GNU General Public License as published by
6
//  the Free Software Foundation, either version 3 of the License, or
7
//  (at your option) any later version.
8
//
9
//  This program is distributed in the hope that it will be useful,
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
//  GNU General Public License for more details.
13
//
14
//  You should have received a copy of the GNU General Public License
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

18
#include "util.h"
19
#include "diag.h"
20
#include "ident.h"
21
#include "lib.h"
22
#include "object.h"
23
#include "parse.h"
24
#include "scan.h"
25
#include "vlog/vlog-node.h"
26
#include "vlog/vlog-phase.h"
27
#include "vlog/vlog-symtab.h"
28
#include "vlog/vlog-util.h"
29

30
#include <ctype.h>
31
#include <string.h>
32
#include <stdlib.h>
33
#include <assert.h>
34

35
static parse_state_t    state;
36
static vlog_kind_t      param_kind;
37
static vlog_net_kind_t  implicit_kind;
38
static vlog_symtab_t   *symtab;
39
static vlog_node_t      last_attr;
40
static vlog_node_t      atom_types[DT_BIT + 1];
41
static unsigned         next_namespace;
42

43
extern loc_t yylloc;
44

45
#define BEGIN_WITH_HEAD(s, t)                            \
46
   EXTEND(s);                                            \
47
   state.start_loc = (t) ? *vlog_loc(t) : LOC_INVALID;   \
48

49
#define BEGIN(s)  BEGIN_WITH_HEAD(s, NULL)
50

51
static vlog_node_t p_statement_or_null(void);
52
static vlog_node_t p_expression(void);
53
static vlog_node_t p_constant_expression(void);
54
static vlog_node_t p_data_type(void);
55
static void p_list_of_variable_decl_assignments(vlog_node_t parent,
56
                                                vlog_node_t datatype);
57
static vlog_node_t p_variable_lvalue(void);
58
static vlog_node_t p_select(ident_t id);
59
static vlog_net_kind_t p_net_type(void);
60
static void p_module_or_generate_item(vlog_node_t mod);
61
static void p_block_item_declaration(vlog_node_t parent);
62
static vlog_node_t p_attribute_instance(void);
63
static vlog_node_t  p_drive_strength(void);
64
static vlog_strength_t p_strength0(void);
65
static vlog_strength_t p_strength1(void);
66

67
static vlog_node_t peek_reference(void)
222✔
68
{
69
   assert(peek() == tID);
222✔
70
   ident_t id = state.tokenq[state.tokenq_tail].lval.ident;
222✔
71
   return vlog_symtab_query(symtab, id);
222✔
72
}
73

74
static void vlog_parse_error_cb(void)
20✔
75
{
76
   vlog_symtab_suppress(symtab);
20✔
77
}
20✔
78

79
static void set_timescale(uint64_t unit_value, const char *unit_name,
21✔
80
                          uint64_t prec_value, const char *prec_name,
81
                          const loc_t *loc)
82
{
83
   // See IEEE 1800-2017 section 22.7 for rules
84

85
   struct {
21✔
86
      uint64_t    value;
87
      const char *name;
88
      uint64_t    parsed;
89
   } args[] = {
21✔
90
      { unit_value, unit_name },
91
      { prec_value, prec_name },
92
   };
93

94
   for (int i = 0; i < ARRAY_LEN(args); i++) {
63✔
95
      static const struct {
96
         const char *name;
97
         int64_t value;
98
      } valid_units[] = {
99
         { "s", INT64_C(60000000000000) },
100
         { "ms", 1000000000000 },
101
         { "us", 1000000000 },
102
         { "ns", 1000000 },
103
         { "ps", 1000 },
104
         { "fs", 1 },
105
      };
106

107
      bool name_valid = false;
220✔
108
      for (int j = 0; j < ARRAY_LEN(valid_units); j++) {
220✔
109
         if (strcmp(valid_units[j].name, args[i].name) == 0) {
219✔
110
            args[i].parsed = valid_units[j].value;
41✔
111
            name_valid = true;
41✔
112
            break;
41✔
113
         }
114
      }
115

116
      if (!name_valid)
41✔
117
         error_at(loc, "invalid time unit name '%s'", args[i].name);
1✔
118

119
      if (args[i].value != 1 && args[i].value != 10 && args[i].value != 100) {
42✔
120
         diag_t *d = diag_new(DIAG_ERROR, loc);
1✔
121
         diag_printf(d, "invalid order of magnitude in `timescale directive");
1✔
122
         diag_hint(d, NULL, "the valid values are 1, 10, and 100");
1✔
123
         diag_emit(d);
1✔
124
      }
125

126
      args[i].parsed *= args[i].value;
42✔
127
   }
128

129
   // TODO: do something with parsed scale/precision
130
}
21✔
131

132
static void skip_over_attributes(void)
11,828✔
133
{
134
   while (peek() == tATTRBEGIN)
11,848✔
135
      last_attr = p_attribute_instance();
20✔
136
}
11,828✔
137

138
static void optional_attributes(void)
79,254✔
139
{
140
   if (peek() == tATTRBEGIN) {
79,254✔
141
      // If the current token is (* and there is a saved attribute
142
      // instance from skip_over_attributes() then the attribute must
143
      // have been placed incorrectly as there were other tokens between
144
      // the last closing *) and this
145
      if (last_attr != NULL)
7✔
146
         parse_error(vlog_loc(last_attr), "attribute instance is not "
1✔
147
                     "allowed here");
148

149
      do {
7✔
150
         (void)p_attribute_instance();
7✔
151
      } while (peek() == tATTRBEGIN);
7✔
152
   }
153

154
   last_attr = NULL;
79,254✔
155
}
79,254✔
156

157
static vlog_node_t dummy_expression(void)
×
158
{
159
   vlog_node_t v = vlog_new(V_NUMBER);
×
160
   vlog_set_number(v, number_from_bool(false));
×
161
   return v;
×
162
}
163

164
static vlog_node_t logic_type(void)
17✔
165
{
166
   vlog_node_t v = vlog_new(V_DATA_TYPE);
17✔
167
   vlog_set_subkind(v, DT_LOGIC);
17✔
168
   return v;
17✔
169
}
170

171
static vlog_node_t implicit_type(void)
80✔
172
{
173
   vlog_node_t v = vlog_new(V_DATA_TYPE);
80✔
174
   vlog_set_subkind(v, DT_IMPLICIT);
80✔
175
   return v;
80✔
176
}
177

178
static vlog_node_t make_integer_atom_type(data_type_t dt)
325✔
179
{
180
   if (atom_types[dt] == NULL) {
325✔
181
      int width;
196✔
182
      switch (dt) {
196✔
183
      case DT_BYTE:     width = 8; break;
184
      case DT_SHORTINT: width = 16; break;
5✔
185
      case DT_INT:      width = 32; break;
37✔
186
      case DT_LONGINT:  width = 64; break;
1✔
187
      case DT_INTEGER:  width = 32; break;
141✔
188
      case DT_TIME:     width = 64; break;
2✔
189
      default: should_not_reach_here();
190
      }
191

192
      vlog_node_t left = vlog_new(V_NUMBER);
196✔
193
      vlog_set_number(left, number_from_int(width - 1));
196✔
194

195
      vlog_node_t right = vlog_new(V_NUMBER);
196✔
196
      vlog_set_number(right, number_from_int(0));
196✔
197

198
      vlog_node_t r = vlog_new(V_DIMENSION);
196✔
199
      vlog_set_subkind(r, V_DIM_PACKED);
196✔
200
      vlog_set_left(r, left);
196✔
201
      vlog_set_right(r, right);
196✔
202

203
      atom_types[dt] = r;
196✔
204
   }
205

206
   vlog_node_t v = vlog_new(V_DATA_TYPE);
325✔
207
   vlog_set_subkind(v, dt);
325✔
208
   vlog_add_range(v, atom_types[dt]);
325✔
209

210
   vlog_set_loc(v, &state.last_loc);
325✔
211
   return v;
325✔
212
}
213

214
static ident_t default_label(const char *prefix)
1,883✔
215
{
216
   return ident_sprintf("%s#%d#%d", prefix, state.last_loc.first_line,
3,766✔
217
                        state.last_loc.first_column);
1,883✔
218
}
219

220
static vlog_gate_kind_t get_gate_kind(token_t tok)
58✔
221
{
222
   switch (tok) {
58✔
223
   case tAND:      return V_GATE_AND;
224
   case tNAND:     return V_GATE_NAND;
4✔
225
   case tOR:       return V_GATE_OR;
10✔
226
   case tNOR:      return V_GATE_NOR;
×
227
   case tXOR:      return V_GATE_XOR;
4✔
228
   case tXNOR:     return V_GATE_XNOR;
×
229
   case tNOT:      return V_GATE_NOT;
5✔
230
   case tNOTIF0:   return V_GATE_NOTIF0;
×
231
   case tNOTIF1:   return V_GATE_NOTIF1;
×
232
   case tBUF:      return V_GATE_BUF;
26✔
233
   case tBUFIF0:   return V_GATE_BUFIF0;
1✔
234
   case tBUFIF1:   return V_GATE_BUFIF1;
×
235
   case tTRAN:     return V_GATE_TRAN;
1✔
236
   case tTRANIF0:  return V_GATE_TRANIF0;
×
237
   case tTRANIF1:  return V_GATE_TRANIF1;
1✔
238
   case tRTRAN:    return V_GATE_RTRAN;
×
239
   case tRTRANIF0: return V_GATE_RTRANIF0;
×
240
   case tRTRANIF1: return V_GATE_RTRANIF1;
×
241
   default:        should_not_reach_here();
242
   }
243
}
244

245
static void declare_port(vlog_node_t mod, vlog_node_t port)
460✔
246
{
247
   ident_t id = vlog_ident(port);
460✔
248

249
   const int nports = vlog_ports(mod);
460✔
250
   bool found = false;
460✔
251
   for (int i = 0; i < nports; i++) {
3,286✔
252
      vlog_node_t p = vlog_port(mod, i);
2,826✔
253
      if (vlog_ident(p) == id) {
2,826✔
254
         vlog_set_ref(p, port);
460✔
255
         found = true;
460✔
256
      }
257
   }
258

259
   if (!found) {
460✔
260
      diag_t *d = diag_new(DIAG_ERROR, vlog_loc(port));
2✔
261
      diag_printf(d, "'%s' does not appear in module port list", istr(id));
2✔
262
      diag_hint(d, vlog_loc(mod), "module declaration for '%s'",
2✔
263
                istr(vlog_ident2(mod)));
264
      diag_emit(d);
2✔
265
   }
266
}
460✔
267

268
static vlog_node_t get_data_type(ident_t id)
57✔
269
{
270
   vlog_node_t v = vlog_symtab_query(symtab, id);
57✔
271
   if (v == NULL) {
57✔
272
      error_at(&state.last_loc, "no data type declaration for '%pi'", id);
1✔
273
      return logic_type();
1✔
274
   }
275
   else if (!is_data_type(v)) {
56✔
276
      diag_t *d = diag_new(DIAG_ERROR, &state.last_loc);
1✔
277
      diag_printf(d, "'%pi' is not a data type", id);
1✔
278
      diag_hint(d, vlog_loc(v), "'%pi' declared here", id);
1✔
279
      diag_emit(d);
1✔
280

281
      return logic_type();
1✔
282
   }
283

284
   return v;
285
}
286

287
static bool scan_block_item_declaration(void)
2,790✔
288
{
289
   return scan(tREG, tSTRUCT, tUNION, tTYPEDEF, tENUM, tSVINT, tINTEGER,
2,790✔
290
               tSVREAL, tSHORTREAL, tREALTIME, tBIT, tLOGIC, tSHORTINT, tTIME);
291
}
292

293
static bool scan_tf_item_declaration(void)
166✔
294
{
295
   return scan(tREG, tSTRUCT, tUNION, tTYPEDEF, tENUM, tSVINT, tINTEGER,
166✔
296
               tSVREAL, tSHORTREAL, tREALTIME, tBIT, tLOGIC, tSHORTINT, tTIME,
297
               tINPUT, tOUTPUT);
298
}
299

300
static ident_t p_identifier(void)
49,468✔
301
{
302
   if (consume(tID))
49,468✔
303
      return state.last_lval.ident;
49,467✔
304
   else
305
      return error_marker();
1✔
306
}
307

308
static void p_external_identifier(ident_t *id, ident_t *ext)
1,678✔
309
{
310
   if (consume(tID)) {
1,678✔
311
      *id = state.last_lval.ident;
1,678✔
312

313
      LOCAL_TEXT_BUF tb = tb_new();
1,678✔
314
      tb_istr(tb, state.last_lval.ident);
1,678✔
315
      tb_upcase(tb);
1,678✔
316

317
      *ext = ident_new(tb_get(tb));
1,678✔
318
   }
319
   else
320
      *id = *ext = error_marker();
×
321
}
1,678✔
322

323
static ident_t p_system_tf_identifier(void)
9,628✔
324
{
325
   if (consume(tSYSTASK))
9,628✔
326
      return state.last_lval.ident;
9,628✔
327
   else
328
      return error_marker();
×
329
}
330

331
static void p_attr_spec(void)
27✔
332
{
333
   // attr_name [ = constant_expression ]
334

335
   BEGIN("attribute specification");
54✔
336

337
   (void)p_identifier();
27✔
338

339
   if (optional(tEQ))
27✔
340
      (void)p_constant_expression();
1✔
341
}
27✔
342

343
static vlog_node_t p_attribute_instance(void)
27✔
344
{
345
   // (* attr_spec { , attr_spec } *)
346

347
   BEGIN("attribute instance");
54✔
348

349
   consume(tATTRBEGIN);
27✔
350

351
   vlog_node_t v = vlog_new(V_ATTR_INST);
27✔
352

353
   do {
27✔
354
      p_attr_spec();
27✔
355
   } while (optional(tCOMMA));
27✔
356

357
   consume(tATTREND);
27✔
358

359
   vlog_set_loc(v, CURRENT_LOC);
27✔
360
   return v;
27✔
361
}
362

363
static vlog_node_t p_unsigned_number(void)
20,983✔
364
{
365
   // decimal_digit { _ | decimal_digit }
366

367
   BEGIN("unsigned number");
41,966✔
368

369
   number_t n;
20,983✔
370
   if (consume(tUNSNUM)) {
20,983✔
371
      n = number_new(state.last_lval.str, CURRENT_LOC);
20,983✔
372
      free(state.last_lval.str);
20,983✔
373
   }
374
   else
375
      n = number_from_int(0);
×
376

377
   vlog_node_t v = vlog_new(V_NUMBER);
20,983✔
378
   vlog_set_number(v, n);
20,983✔
379
   vlog_set_loc(v, CURRENT_LOC);
20,983✔
380
   return v;
20,983✔
381
}
382

383
static vlog_node_t p_integral_number(void)
38,336✔
384
{
385
   // decimal_number | octal_number | binary_number | hex_number
386

387
   BEGIN("integral number");
76,672✔
388

389
   if (peek() == tUNSNUM)
38,336✔
390
      return p_unsigned_number();
16,365✔
391
   else {
392
      number_t n;
21,971✔
393
      if (consume(tNUMBER)) {
21,971✔
394
         n = number_new(state.last_lval.str, &state.last_loc);
21,970✔
395
         free(state.last_lval.str);
21,970✔
396
      }
397
      else
398
         n = number_from_int(0);
1✔
399

400
      vlog_node_t v = vlog_new(V_NUMBER);
21,971✔
401
      vlog_set_number(v, n);
21,971✔
402
      vlog_set_loc(v, CURRENT_LOC);
21,971✔
403
      return v;
21,971✔
404
   }
405
}
406

407
static vlog_node_t p_real_number(void)
410✔
408
{
409
   // fixed_point_number
410
   //   | unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number
411

412
   BEGIN("real number");
820✔
413

414
   consume(tREAL);
410✔
415

416
   vlog_node_t v = vlog_new(V_REAL);
410✔
417
   vlog_set_dval(v, state.last_lval.real);
410✔
418
   vlog_set_loc(v, CURRENT_LOC);
410✔
419
   return v;
410✔
420
}
421

422
static vlog_node_t p_number(void)
38,735✔
423
{
424
   // integral_number | real_number
425

426
   BEGIN("number");
77,470✔
427

428
   if (peek() == tREAL)
38,735✔
429
      return p_real_number();
405✔
430
   else
431
      return p_integral_number();
38,330✔
432
}
433

434
static vlog_node_t p_string_literal(void)
6,199✔
435
{
436
   // " { Any_ASCII_Characters } "
437

438
   BEGIN("string literal");
12,398✔
439

440
   number_t n;
6,199✔
441
   if (consume(tSTRING)) {
6,199✔
442
      text_buf_t *tb = state.last_lval.text;
6,199✔
443
      n = number_from_string(tb_get(tb), tb_len(tb));
6,199✔
444
      tb_free(tb);
6,199✔
445
   }
446
   else
447
      should_not_reach_here();
448

449
   vlog_node_t v = vlog_new(V_STRING);
6,199✔
450
   vlog_set_number(v, n);
6,199✔
451
   vlog_set_loc(v, CURRENT_LOC);
6,199✔
452
   return v;
12,398✔
453
}
454

455
static vlog_node_t p_primary_literal(void)
44,934✔
456
{
457
   // number | time_literal | unbased_unsized_literal | string_literal
458

459
   BEGIN("primary literal");
89,868✔
460

461
   switch (peek()) {
44,934✔
462
   case tNUMBER:
38,735✔
463
   case tUNSNUM:
464
   case tREAL:
465
      return p_number();
38,735✔
466
   case tSTRING:
6,199✔
467
      return p_string_literal();
6,199✔
468
   default:
×
469
      one_of(tNUMBER, tUNSNUM, tREAL, tSTRING);
×
470
      return dummy_expression();
×
471
   }
472
}
473

474
static vlog_node_t p_constant_select(ident_t id)
753✔
475
{
476
   // [ { . member_identifier constant_bit_select } . member_identifier ]
477
   //    constant_bit_select [ [ constant_part_select_range ] ]
478

479
   EXTEND("constant select");
1,506✔
480

481
   // Checked for constant-ness later
482
   return p_select(id);
753✔
483
}
484

485
static vlog_node_t p_constant_expression(void)
9,994✔
486
{
487
   // constant_primary | unary_operator { attribute_instance } constant_primary
488
   //   | constant_expression binary_operator { attribute_instance }
489
   //       constant_expression
490
   //   | constant_expression ? { attribute_instance }
491
   //       constant_expression : constant_expression
492

493
   BEGIN("constant expression");
19,988✔
494

495
   // Checked for constant-ness later
496
   return p_expression();
9,994✔
497
}
498

499
static void p_constant_range(vlog_node_t *left, vlog_node_t *right)
4,076✔
500
{
501
   // constant_expression : constant_expression
502

503
   BEGIN("constant range");
8,152✔
504

505
   *left = p_constant_expression();
4,076✔
506

507
   consume(tCOLON);
4,076✔
508

509
   *right = p_constant_expression();
4,076✔
510
}
4,076✔
511

512
static vlog_node_t p_constant_range_expression(void)
2✔
513
{
514
   // constant_expression | constant_part_select_range
515

516
   BEGIN("constant range expression");
4✔
517

518
   return p_constant_expression();
2✔
519
}
520

521
static vlog_node_t p_constant_mintypmax_expression(void)
8✔
522
{
523
   // constant_expression
524
   //   | constant_expression : constant_expression : constant_expression
525

526
   return p_constant_expression();
8✔
527
}
528

529
static vlog_node_t p_packed_dimension(void)
3,963✔
530
{
531
   // [ constant_range ] | unsized_dimension
532

533
   BEGIN("packed dimension");
7,926✔
534

535
   consume(tLSQUARE);
3,963✔
536

537
   vlog_node_t left, right;
3,963✔
538
   p_constant_range(&left, &right);
3,963✔
539

540
   consume(tRSQUARE);
3,963✔
541

542
   vlog_node_t v = vlog_new(V_DIMENSION);
3,963✔
543
   vlog_set_subkind(v, V_DIM_PACKED);
3,963✔
544
   vlog_set_left(v, left);
3,963✔
545
   vlog_set_right(v, right);
3,963✔
546
   vlog_set_loc(v, CURRENT_LOC);
3,963✔
547

548
   return v;
3,963✔
549
}
550

551
static vlog_node_t p_unpacked_dimension(void)
113✔
552
{
553
   // [ constant_range ] | [ constant_expression ]
554

555
   BEGIN("unpacked dimension");
226✔
556

557
   consume(tLSQUARE);
113✔
558

559
   vlog_node_t left, right;
113✔
560
   p_constant_range(&left, &right);
113✔
561

562
   consume(tRSQUARE);
113✔
563

564
   vlog_node_t v = vlog_new(V_DIMENSION);
113✔
565
   vlog_set_subkind(v, V_DIM_UNPACKED);
113✔
566
   vlog_set_left(v, left);
113✔
567
   vlog_set_right(v, right);
113✔
568
   vlog_set_loc(v, CURRENT_LOC);
113✔
569

570
   return v;
113✔
571
}
572

573
static vlog_node_t p_data_type_or_void(void)
81✔
574
{
575
   // data_type | void
576

577
   BEGIN("data type or void");
162✔
578

579
   if (optional(tVOID))
81✔
580
      return NULL;
581
   else
582
      return p_data_type();
80✔
583
}
584

585
static void p_struct_union_member(vlog_node_t v)
60✔
586
{
587
   // { attribute_instance } [ random_qualifier ] data_type_or_void
588
   //    list_of_variable_decl_assignments ;
589

590
   BEGIN("struct or union member");
120✔
591

592
   optional_attributes();
60✔
593

594
   vlog_node_t dt = p_data_type_or_void();
60✔
595
   p_list_of_variable_decl_assignments(v, dt);
60✔
596

597
   consume(tSEMI);
60✔
598
}
60✔
599

600
static void p_enum_name_declaration(vlog_node_t parent)
73✔
601
{
602
   // enum_identifier [ [ integral_number [ : integral_number ] ] ]
603
   //   [ = constant_expression ]
604

605
   BEGIN("enum name declaration");
146✔
606

607
   vlog_node_t v = vlog_new(V_ENUM_NAME);
73✔
608
   vlog_set_ident(v, p_identifier());
73✔
609
   vlog_set_type(v, parent);
73✔
610

611
   if (optional(tEQ))
73✔
612
      vlog_set_value(v, p_constant_expression());
27✔
613

614
   vlog_add_decl(parent, v);
73✔
615

616
   vlog_set_loc(v, CURRENT_LOC);
73✔
617
   vlog_symtab_put(symtab, v);
73✔
618
}
73✔
619

620
static vlog_node_t p_integer_atom_type(void)
302✔
621
{
622
   // byte | shortint | int | longint | integer | time
623

624
   BEGIN("integer atom type");
604✔
625

626
   data_type_t dt = DT_BYTE;
302✔
627
   switch (one_of(tBYTE, tSHORTINT, tSVINT, tLONGINT, tINTEGER, tTIME)) {
302✔
628
   case tBYTE:     dt = DT_BYTE; break;
629
   case tSHORTINT: dt = DT_SHORTINT; break;
630
   case tSVINT:    dt = DT_INT; break;
631
   case tLONGINT:  dt = DT_LONGINT; break;
632
   case tINTEGER:  dt = DT_INTEGER; break;
633
   case tTIME:     dt = DT_TIME; break;
634
   }
635

636
   return make_integer_atom_type(dt);
302✔
637
}
638

639
static vlog_node_t p_integer_vector_type(void)
3,495✔
640
{
641
   //  bit | logic | reg
642

643
   BEGIN("integer vector type");
6,990✔
644

645
   data_type_t dt = DT_LOGIC;
3,495✔
646
   switch (one_of(tBIT, tLOGIC, tREG)) {
3,495✔
647
   case tBIT:    dt = DT_BIT; break;
14✔
648
   case tLOGIC:
649
   case tREG:    dt = DT_LOGIC; break;
650
   }
651

652
   vlog_node_t v = vlog_new(V_DATA_TYPE);
3,495✔
653
   vlog_set_subkind(v, dt);
3,495✔
654
   vlog_set_loc(v, &state.last_loc);
3,495✔
655
   return v;
3,495✔
656
}
657

658
static vlog_node_t p_non_integer_type(void)
56✔
659
{
660
   // shortreal | real | realtime
661

662
   BEGIN("non-integer type");
112✔
663

664
   data_type_t dt = DT_REAL;
56✔
665
   switch (one_of(tSVREAL, tSHORTREAL, tREALTIME)) {
56✔
666
   case tSVREAL:    dt = DT_REAL; break;
667
   case tSHORTREAL: dt = DT_SHORTREAL; break;
2✔
668
   case tREALTIME:  dt = DT_REALTIME; break;
1✔
669
   }
670

671
   vlog_node_t v = vlog_new(V_DATA_TYPE);
56✔
672
   vlog_set_subkind(v, dt);
56✔
673
   vlog_set_loc(v, &state.last_loc);
56✔
674
   return v;
56✔
675
}
676

677
static vlog_node_t p_struct_union(void)
33✔
678
{
679
   // struct | union [ tagged ]
680

681
   BEGIN("struct or union");
66✔
682

683
   switch (one_of(tSTRUCT, tUNION)) {
33✔
684
   case tUNION:
11✔
685
      {
686
         vlog_node_t v = vlog_new(V_UNION_DECL);
11✔
687
         optional(tTAGGED);
11✔
688
         return v;
11✔
689
      }
690
   case tSTRUCT:
22✔
691
   default:
692
      return vlog_new(V_STRUCT_DECL);
22✔
693
   }
694
}
695

696
static vlog_flags_t p_signing(void)
129✔
697
{
698
   // signed | unsigned
699

700
   BEGIN("signing");
258✔
701

702
   switch (one_of(tSIGNED, tUNSIGNED)) {
129✔
703
   case tSIGNED: return VLOG_F_SIGNED;
704
   default: return 0;
25✔
705
   }
706
}
707

708
static vlog_node_t p_enum_base_type(void)
17✔
709
{
710
   // integer_atom_type [ signing ]
711
   //   | integer_vector_type [ signing ] [ packed_dimension ]
712
   //   | type_identifier [ packed_dimension ]
713

714
   BEGIN("enum base type");
34✔
715

716
   switch (peek()) {
17✔
717
   case tBYTE:
11✔
718
   case tSHORTINT:
719
   case tSVINT:
720
   case tLONGINT:
721
   case tINTEGER:
722
   case tTIME:
723
      {
724
         vlog_node_t v = p_integer_atom_type();
11✔
725

726
         if (scan(tSIGNED, tUNSIGNED))
11✔
727
            vlog_set_flags(v, p_signing());
×
728
         else
729
            vlog_set_flags(v, VLOG_F_SIGNED);
11✔
730

731
         return v;
732
      }
733

734
   case tBIT:
6✔
735
   case tLOGIC:
736
   case tREG:
737
      {
738
         vlog_node_t v = p_integer_vector_type();
6✔
739

740
         if (scan(tSIGNED, tUNSIGNED))
6✔
741
            vlog_set_flags(v, p_signing());
×
742

743
         if (scan(tLSQUARE))
6✔
744
            vlog_add_range(v, p_packed_dimension());
6✔
745

746
         return v;
747
      }
748

749
   default:
×
750
      return get_data_type(p_identifier());
×
751
   }
752
}
753

754
static vlog_node_t p_data_type(void)
3,957✔
755
{
756
   // integer_vector_type [ signing ] { packed_dimension }
757
   //   | integer_atom_type [ signing ] | non_integer_type
758
   //   | struct_union [ packed [ signing ] ]
759
   //       { struct_union_member { struct_union_member } } { packed_dimension }
760
   //   | enum [ enum_base_type ] { enum_name_declaration
761
   //       { , enum_name_declaration } } { packed_dimension }
762
   //   | string | chandle
763
   //   | virtual [ interface ] interface_identifier
764
   //       [ parameter_value_assignment ] [ . modport_identifier ]
765
   //   | [ class_scope | package_scope ] type_identifier { packed_dimension }
766
   //   | class_type | event | ps_covergroup_identifier | type_reference
767

768
   BEGIN("data type");
7,914✔
769

770
   switch (peek()) {
3,957✔
771
   case tBIT:
3,489✔
772
   case tLOGIC:
773
   case tREG:
774
      {
775
         vlog_node_t v = p_integer_vector_type();
3,489✔
776

777
         if (scan(tSIGNED, tUNSIGNED))
3,489✔
778
            vlog_set_flags(v, p_signing());
65✔
779

780
         while (peek() == tLSQUARE)
6,446✔
781
            vlog_add_range(v, p_packed_dimension());
2,957✔
782

783
         return v;
784
      }
785

786
   case tBYTE:
291✔
787
   case tSHORTINT:
788
   case tSVINT:
789
   case tLONGINT:
790
   case tINTEGER:
791
   case tTIME:
792
      {
793
         vlog_node_t v = p_integer_atom_type();
291✔
794

795
         if (scan(tSIGNED, tUNSIGNED))
291✔
796
            vlog_set_flags(v, p_signing());
1✔
797
         else
798
            vlog_set_flags(v, VLOG_F_SIGNED);
290✔
799

800
         return v;
801
      }
802

803
   case tSVREAL:
56✔
804
   case tREALTIME:
805
   case tSHORTREAL:
806
      return p_non_integer_type();
56✔
807

808
   case tSTRUCT:
33✔
809
   case tUNION:
810
      {
811
         vlog_node_t v = p_struct_union();
33✔
812

813
         if (optional(tPACKED)) {
33✔
814
            vlog_set_flags(v, VLOG_F_PACKED);
26✔
815

816
            if (scan(tSIGNED, tUNSIGNED))
26✔
817
               vlog_set_flags(v, p_signing());
×
818
         }
819

820
         consume(tLBRACE);
33✔
821

822
         vlog_symtab_push(symtab, v);
33✔
823

824
         do {
60✔
825
            p_struct_union_member(v);
60✔
826
         } while (not_at_token(tRBRACE));
60✔
827

828
         vlog_symtab_pop(symtab);
33✔
829

830
         consume(tRBRACE);
33✔
831

832
         if (peek() == tLSQUARE)
33✔
833
            vlog_add_range(v, p_packed_dimension());
×
834

835
         vlog_set_loc(v, CURRENT_LOC);
33✔
836
         return v;
33✔
837
      }
838

839
   case tENUM:
26✔
840
      {
841
         consume(tENUM);
26✔
842

843
         vlog_node_t v = vlog_new(V_ENUM_DECL);
26✔
844

845
         if (peek() != tLBRACE)
26✔
846
            vlog_set_type(v, p_enum_base_type());
17✔
847
         else {
848
            vlog_node_t dt = make_integer_atom_type(DT_INT);
9✔
849
            vlog_set_flags(dt, VLOG_F_SIGNED);
9✔
850

851
            vlog_set_type(v, dt);
9✔
852
         }
853

854
         consume(tLBRACE);
26✔
855

856
         do {
73✔
857
            p_enum_name_declaration(v);
73✔
858
         } while (optional(tCOMMA));
73✔
859

860
         consume(tRBRACE);
26✔
861

862
         while (peek() == tLSQUARE)
28✔
863
            vlog_add_range(v, p_packed_dimension());
2✔
864

865
         vlog_set_loc(v, CURRENT_LOC);
26✔
866
         return v;
26✔
867
      }
868

869
   case tEVENT:
1✔
870
      {
871
         consume(tEVENT);
1✔
872

873
         vlog_node_t v = vlog_new(V_DATA_TYPE);
1✔
874
         vlog_set_subkind(v, DT_EVENT);
1✔
875
         vlog_set_loc(v, &state.last_loc);
1✔
876

877
         return v;
1✔
878
      }
879

880
   case tID:
57✔
881
      return get_data_type(p_identifier());
57✔
882

883
   case tSTRINGK:
4✔
884
      {
885
         consume(tSTRINGK);
4✔
886

887
         vlog_node_t v = vlog_new(V_DATA_TYPE);
4✔
888
         vlog_set_subkind(v, DT_STRING);
4✔
889
         vlog_set_loc(v, &state.last_loc);
4✔
890

891
         return v;
4✔
892
      }
893

894
   default:
×
895
      one_of(tBIT, tLOGIC, tREG, tBYTE, tSHORTINT, tSVINT, tLONGINT, tINTEGER,
×
896
             tTIME, tSVREAL, tREALTIME, tSHORTREAL, tSTRUCT, tUNION, tENUM,
897
             tEVENT, tID, tSTRINGK);
898
      return logic_type();
×
899
   }
900
}
901

902
static vlog_node_t p_implicit_data_type(void)
1,942✔
903
{
904
   // [ signing ] { packed_dimension }
905

906
   BEGIN("implicit data type");
3,884✔
907

908
   vlog_node_t v = vlog_new(V_DATA_TYPE);
1,942✔
909
   vlog_set_subkind(v, DT_IMPLICIT);
1,942✔
910

911
   if (scan(tSIGNED, tUNSIGNED))
1,942✔
912
      vlog_set_flags(v, p_signing());
63✔
913

914
   while (peek() == tLSQUARE)
2,939✔
915
      vlog_add_range(v, p_packed_dimension());
997✔
916

917
   vlog_set_loc(v, CURRENT_LOC);
1,942✔
918
   return v;
1,942✔
919
}
920

921
static vlog_node_t p_data_type_or_implicit(void)
5,669✔
922
{
923
   // data_type | implicit_data_type
924

925
   BEGIN("data type or implicit");
11,338✔
926

927
   switch (peek()) {
5,669✔
928
   case tID:
926✔
929
      if (peek_nth(2) == tID)
926✔
930
         return p_data_type();
45✔
931
      else
932
         return p_implicit_data_type();
881✔
933
      break;
3,767✔
934
   case tREG:
3,767✔
935
   case tSTRUCT:
936
   case tUNION:
937
   case tENUM:
938
   case tSVINT:
939
   case tINTEGER:
940
   case tSVREAL:
941
   case tSHORTREAL:
942
   case tREALTIME:
943
   case tTIME:
944
   case tLOGIC:
945
   case tBIT:
946
   case tSHORTINT:
947
   case tLONGINT:
948
   case tBYTE:
949
   case tEVENT:
950
   case tSTRINGK:
951
      return p_data_type();
3,767✔
952
   default:
976✔
953
      return p_implicit_data_type();
976✔
954
   }
955
}
956

957
static void p_net_port_type(vlog_net_kind_t *kind, vlog_node_t *dt)
541✔
958
{
959
   // [ net_type ] data_type_or_implicit | net_type_identifier
960
   //   | interconnect implicit_data_type
961

962
   BEGIN("net port type");
1,082✔
963

964
   if (scan(tSUPPLY0, tSUPPLY1, tTRI, tTRIAND, tTRIOR, tTRIREG,
541✔
965
            tTRI0, tTRI1, tUWIRE, tWIRE, tWAND, tWOR))
966
      *kind = p_net_type();
86✔
967
   else
968
      *kind = V_NET_WIRE;
455✔
969

970
   *dt = p_data_type_or_implicit();
541✔
971
}
541✔
972

973
static vlog_node_t p_var_data_type(void)
24✔
974
{
975
   // data_type | var data_type_or_implicit
976

977
   BEGIN("var data type");
48✔
978

979
   return p_data_type();
24✔
980
}
981

982
static vlog_node_t p_variable_port_type(void)
24✔
983
{
984
   // var_data_type
985

986
   BEGIN("variable port type");
48✔
987

988
   return p_var_data_type();
24✔
989
}
990

991
static void p_list_of_port_identifiers(vlog_node_t mod, v_port_kind_t kind,
408✔
992
                                       vlog_node_t datatype)
993
{
994
   // port_identifier { unpacked_dimension }
995
   //    { , port_identifier { unpacked_dimension } }
996

997
   BEGIN("list of port identifiers");
816✔
998

999
   do {
436✔
1000
      ident_t id, ext;
436✔
1001
      p_external_identifier(&id, &ext);
436✔
1002

1003
      vlog_node_t v = vlog_new(V_PORT_DECL);
436✔
1004
      vlog_set_subkind(v, kind);
436✔
1005
      vlog_set_ident(v, id);
436✔
1006
      vlog_set_ident2(v, ext);
436✔
1007
      vlog_set_type(v, datatype);
436✔
1008
      vlog_set_loc(v, &state.last_loc);
436✔
1009

1010
      vlog_add_decl(mod, v);
436✔
1011
      vlog_symtab_put(symtab, v);
436✔
1012

1013
      declare_port(mod, v);
436✔
1014
   } while (optional(tCOMMA));
436✔
1015
}
408✔
1016

1017
static void p_list_of_variable_port_identifiers(vlog_node_t mod,
24✔
1018
                                                v_port_kind_t kind,
1019
                                                vlog_node_t datatype)
1020
{
1021
   // port_identifier { variable_dimension } [ = constant_expression ]
1022
   //   { , port_identifier { variable_dimension } [ = constant_expression ] }
1023

1024
   BEGIN("list of variable port identifiers");
48✔
1025

1026
   do {
24✔
1027
      ident_t id, ext;
24✔
1028
      p_external_identifier(&id, &ext);
24✔
1029

1030
      vlog_node_t v = vlog_new(V_PORT_DECL);
24✔
1031
      vlog_set_subkind(v, kind);
24✔
1032
      vlog_set_ident(v, id);
24✔
1033
      vlog_set_ident2(v, ext);
24✔
1034
      vlog_set_type(v, datatype);
24✔
1035
      vlog_set_loc(v, &state.last_loc);
24✔
1036

1037
      if (optional(tEQ))
24✔
1038
         vlog_set_value(v, p_constant_expression());
4✔
1039

1040
      vlog_add_decl(mod, v);
24✔
1041
      vlog_symtab_put(symtab, v);
24✔
1042

1043
      declare_port(mod, v);
24✔
1044
   } while (optional(tCOMMA));
24✔
1045
}
24✔
1046

1047
static void p_inout_declaration(vlog_node_t mod)
1✔
1048
{
1049
   // inout net_port_type list_of_port_identifiers
1050

1051
   BEGIN("inout declaration");
2✔
1052

1053
   consume(tINOUT);
1✔
1054

1055
   vlog_node_t dt;
1✔
1056
   vlog_net_kind_t kind;
1✔
1057
   p_net_port_type(&kind, &dt);
1✔
1058

1059
   p_list_of_port_identifiers(mod, V_PORT_INOUT, dt);
1✔
1060
}
1✔
1061

1062
static void p_input_declaration(vlog_node_t mod)
233✔
1063
{
1064
   // input net_port_type list_of_port_identifiers
1065
   //   | input variable_port_type list_of_variable_identifiers
1066

1067
   BEGIN("input declaration");
466✔
1068

1069
   consume(tINPUT);
233✔
1070

1071
   vlog_node_t dt;
233✔
1072
   vlog_net_kind_t kind;
233✔
1073
   switch (peek()) {
233✔
1074
   case tREG:
×
1075
      dt = p_variable_port_type();
×
1076
      p_list_of_variable_port_identifiers(mod, V_PORT_INPUT, dt);
×
1077
      break;
×
1078
   default:
233✔
1079
      p_net_port_type(&kind, &dt);
233✔
1080
      p_list_of_port_identifiers(mod, V_PORT_INPUT, dt);
233✔
1081
      break;
233✔
1082
   }
1083
}
233✔
1084

1085
static void p_output_declaration(vlog_node_t mod)
198✔
1086
{
1087
   // output net_port_type list_of_port_identifiers
1088
   //   | output variable_port_type list_of_variable_port_identifiers
1089

1090
   BEGIN("output declaration");
396✔
1091

1092
   consume(tOUTPUT);
198✔
1093

1094
   switch (peek()) {
198✔
1095
   case tREG:
24✔
1096
      {
1097
         vlog_node_t dt = p_variable_port_type();
24✔
1098
         p_list_of_variable_port_identifiers(mod, V_PORT_OUTPUT, dt);
24✔
1099
      }
1100
      break;
24✔
1101
   default:
174✔
1102
      {
1103
         vlog_node_t dt;
174✔
1104
         vlog_net_kind_t kind;
174✔
1105
         p_net_port_type(&kind, &dt);
174✔
1106
         p_list_of_port_identifiers(mod, V_PORT_OUTPUT, dt);
174✔
1107
      }
1108
      break;
174✔
1109
   }
1110
}
198✔
1111

1112
static void p_port_declaration(vlog_node_t mod)
432✔
1113
{
1114
   // { attribute_instance } inout_declaration
1115
   //   | { attribute_instance } input_declaration
1116
   //   | { attribute_instance } output_declaration
1117
   //   | { attribute_instance } ref_declaration
1118
   //   | { attribute_instance } interface_port_declaration
1119

1120
   BEGIN("port declaration");
864✔
1121

1122
   switch (peek()) {
432✔
1123
   case tINOUT: p_inout_declaration(mod); break;
1✔
1124
   case tINPUT: p_input_declaration(mod); break;
233✔
1125
   case tOUTPUT: p_output_declaration(mod); break;
198✔
1126
   default: should_not_reach_here();
1127
   }
1128
}
432✔
1129

1130
static void p_net_port_header(v_port_kind_t *dir, vlog_node_t *dt)
133✔
1131
{
1132
   // [ port_direction ] net_port_type
1133

1134
   BEGIN("net port header");
266✔
1135

1136
   if (optional(tINPUT))
133✔
1137
      *dir = V_PORT_INPUT;
72✔
1138
   else if (optional(tINOUT))
61✔
1139
      *dir = V_PORT_INOUT;
×
1140
   else if (optional(tOUTPUT))
61✔
1141
      *dir = V_PORT_OUTPUT;
61✔
1142

1143
   vlog_net_kind_t kind;
133✔
1144
   p_net_port_type(&kind, dt);
133✔
1145
}
133✔
1146

1147
static void p_part_select_range(vlog_node_t ps)
1,677✔
1148
{
1149
   // constant_expression : constant_expression
1150
   //   | expression +: constant_expression
1151
   //   | expression -: constant_expression
1152

1153
   BEGIN("part select range");
3,354✔
1154

1155
   vlog_range_kind_t kind = V_RANGE_CONST;
1,677✔
1156
   switch (one_of(tCOLON, tINDEXPOS, tINDEXNEG)) {
1,677✔
1157
   case tINDEXPOS: kind = V_RANGE_POS; break;
641✔
1158
   case tINDEXNEG: kind = V_RANGE_NEG; break;
608✔
1159
   }
1160

1161
   vlog_set_subkind(ps, kind);
1,677✔
1162
   vlog_set_right(ps, p_constant_expression());
1,677✔
1163
}
1,677✔
1164

1165
static vlog_node_t p_hierarchical_identifier(ident_t id)
10✔
1166
{
1167
   // [ $root . ] { identifier constant_bit_select . } identifier
1168

1169
   EXTEND("hierarchical identifier");
20✔
1170

1171
   if (id == NULL)
10✔
1172
      id = p_identifier();
3✔
1173

1174
   vlog_node_t v = vlog_new(V_HIER_REF);
10✔
1175
   vlog_set_ident(v, id);
10✔
1176

1177
   consume(tDOT);
10✔
1178

1179
   ident_t suffix = NULL;
10✔
1180
   do {
11✔
1181
      suffix = ident_prefix(suffix, p_identifier(), '.');
11✔
1182
      vlog_set_ident2(v, suffix);
11✔
1183
   } while (optional(tDOT));
11✔
1184

1185
   vlog_set_loc(v, CURRENT_LOC);
10✔
1186
   vlog_symtab_lookup(symtab, v);
10✔
1187
   return v;
10✔
1188
}
1189

1190
static vlog_node_t p_select(ident_t id)
41,133✔
1191
{
1192
   // [ { . member_identifier bit_select } . member_identifier ]
1193
   //    { [ expression ] } [ [ part_select_range ] ]
1194

1195
   EXTEND("select");
82,266✔
1196

1197
   vlog_node_t d = vlog_symtab_query(symtab, id), prefix;
41,133✔
1198
   if (d != NULL && vlog_kind(d) == V_MOD_INST)
41,133✔
1199
      prefix = p_hierarchical_identifier(id);
2✔
1200
   else if (d == NULL && peek() == tDOT) {
41,131✔
1201
      // Assume this is a hierarchical reference to a later instance
1202
      prefix = p_hierarchical_identifier(id);
5✔
1203
   }
1204
   else {
1205
      prefix = vlog_new(V_REF);
41,126✔
1206
      vlog_set_ident(prefix, id);
41,126✔
1207
      vlog_set_loc(prefix, CURRENT_LOC);
41,126✔
1208

1209
      vlog_symtab_lookup(symtab, prefix);
41,126✔
1210

1211
      while (optional(tDOT)) {
41,367✔
1212
         vlog_node_t ref = vlog_new(V_MEMBER_REF);
241✔
1213
         vlog_set_ident(ref, p_identifier());
241✔
1214
         vlog_set_value(ref, prefix);
241✔
1215
         vlog_set_loc(ref, CURRENT_LOC);
241✔
1216

1217
         vlog_symtab_lookup(symtab, ref);
241✔
1218

1219
         prefix = ref;
241✔
1220
      }
1221
   }
1222

1223
   if (optional(tLSQUARE)) {
41,133✔
1224
      do {
2,743✔
1225
         vlog_node_t expr = p_expression();
2,743✔
1226
         if (scan(tCOLON, tINDEXPOS, tINDEXNEG)) {
2,743✔
1227
            vlog_node_t ps = vlog_new(V_PART_SELECT);
1,677✔
1228
            vlog_set_left(ps, expr);
1,677✔
1229
            vlog_set_value(ps, prefix);
1,677✔
1230

1231
            p_part_select_range(ps);
1,677✔
1232

1233
            consume(tRSQUARE);
1,677✔
1234

1235
            vlog_set_loc(ps, CURRENT_LOC);
1,677✔
1236
            return ps;
1,677✔
1237
         }
1238

1239
         if (vlog_kind(prefix) == V_BIT_SELECT)
1,066✔
1240
            vlog_add_param(prefix, expr);
84✔
1241
         else {
1242
            vlog_node_t bs = vlog_new(V_BIT_SELECT);
982✔
1243
            vlog_set_loc(bs, CURRENT_LOC);
982✔
1244
            vlog_set_value(bs, prefix);
982✔
1245
            vlog_add_param(bs, expr);
982✔
1246

1247
            prefix = bs;
982✔
1248
         }
1249

1250
         consume(tRSQUARE);
1,066✔
1251
      } while (optional(tLSQUARE));
1,066✔
1252
   }
1253

1254
   return prefix;
1255
}
1256

1257
static void p_list_of_arguments(vlog_node_t call)
6,628✔
1258
{
1259
   // [ expression ] { , [ expression ] } { , . identifier ( [ expression ] ) }
1260
   //    | . identifier ( [ expression ] ) { , . identifier ( [ expression ] ) }
1261

1262
   BEGIN("list of arguments");
13,256✔
1263

1264
   if (peek() == tRPAREN)
6,628✔
1265
      return;
65✔
1266

1267
   do {
13,568✔
1268
      if (peek() == tCOMMA) {
13,568✔
1269
         vlog_node_t v = vlog_new(V_EMPTY);
282✔
1270
         vlog_set_loc(v, &state.last_loc);
282✔
1271
         vlog_add_param(call, v);
282✔
1272
      }
1273
      else
1274
         vlog_add_param(call, p_expression());
13,286✔
1275
   } while (optional(tCOMMA));
13,568✔
1276
}
1277

1278
static vlog_node_t p_system_tf_call(vlog_kind_t kind)
9,628✔
1279
{
1280
   // system_tf_identifier [ ( list_of_arguments ) ]
1281

1282
   BEGIN("system task or function call");
19,256✔
1283

1284
   vlog_node_t v = vlog_new(kind);
9,628✔
1285
   vlog_set_ident(v, p_system_tf_identifier());
9,628✔
1286

1287
   if (optional(tLPAREN)) {
9,628✔
1288
      p_list_of_arguments(v);
6,193✔
1289
      consume(tRPAREN);
6,193✔
1290
   }
1291

1292
   vlog_set_loc(v, CURRENT_LOC);
9,628✔
1293
   return v;
9,628✔
1294
}
1295

1296
static vlog_node_t p_tf_call(vlog_kind_t kind)
439✔
1297
{
1298
   // ps_or_hierarchical_tf_identifier { attribute_instance }
1299
   //    [ ( list_of_arguments ) ]
1300

1301
   BEGIN("task or function call");
878✔
1302

1303
   vlog_node_t v = vlog_new(kind);
439✔
1304
   vlog_set_ident(v, p_identifier());
439✔
1305

1306
   optional_attributes();
439✔
1307

1308
   if (optional(tLPAREN)) {
439✔
1309
      p_list_of_arguments(v);
432✔
1310
      consume(tRPAREN);
432✔
1311
   }
1312

1313
   vlog_set_loc(v, CURRENT_LOC);
439✔
1314
   vlog_symtab_lookup(symtab, v);
439✔
1315
   return v;
439✔
1316
}
1317

1318
static vlog_node_t p_subroutine_call(vlog_kind_t kind)
10,067✔
1319
{
1320
   // tf_call | system_tf_call | method_call | [ std:: ] randomize_call
1321

1322
   BEGIN("subroutine call");
20,134✔
1323

1324
   if (peek() == tSYSTASK)
10,067✔
1325
      return p_system_tf_call(kind);
9,628✔
1326
   else
1327
      return p_tf_call(kind);
439✔
1328
}
1329

1330
static vlog_node_t p_mintypmax_expression(void)
43,961✔
1331
{
1332
   // expression | expression : expression : expression
1333

1334
   BEGIN("mintypmax expression");
87,922✔
1335

1336
   vlog_node_t e = p_expression();
43,961✔
1337

1338
   if (optional(tCOLON)) {
43,961✔
1339
      vlog_node_t mtm = vlog_new(V_MIN_TYP_MAX);
1✔
1340
      vlog_set_left(mtm, e);
1✔
1341
      vlog_set_value(mtm, p_expression());
1✔
1342

1343
      consume(tCOLON);
1✔
1344
      vlog_set_right(mtm, p_expression());
1✔
1345

1346
      return mtm;
1✔
1347
   }
1348

1349
   return e;
1350
}
1351

1352
static vlog_node_t p_concatenation(vlog_node_t head)
325✔
1353
{
1354
   // { expression { , expression } }
1355

1356
   BEGIN_WITH_HEAD("concatenation", head);
650✔
1357

1358
   if (head == NULL) {
325✔
1359
      consume(tLBRACE);
93✔
1360
      head = p_expression();
93✔
1361
   }
1362

1363
   vlog_node_t v = vlog_new(V_CONCAT);
325✔
1364
   vlog_add_param(v, head);
325✔
1365

1366
   while (optional(tCOMMA))
723✔
1367
      vlog_add_param(v, p_expression());
398✔
1368

1369
   consume(tRBRACE);
325✔
1370

1371
   vlog_set_loc(v, CURRENT_LOC);
325✔
1372
   return v;
325✔
1373
}
1374

1375
static vlog_node_t p_multiple_concatenation(vlog_node_t head)
93✔
1376
{
1377
   // { expression concatenation }
1378

1379
   BEGIN_WITH_HEAD("multiple concatenation", head);
186✔
1380

1381
   vlog_node_t v = p_concatenation(NULL);
93✔
1382
   vlog_set_value(v, head);
93✔
1383

1384
   consume(tRBRACE);
93✔
1385

1386
   vlog_set_loc(v, CURRENT_LOC);
93✔
1387
   return v;
93✔
1388
}
1389

1390
static vlog_node_t p_package_identifier(void)
3✔
1391
{
1392
   // identifier
1393

1394
   BEGIN("package identifier");
6✔
1395

1396
   ident_t id = p_identifier();
3✔
1397

1398
   lib_t work = lib_work();
3✔
1399
   ident_t qual = ident_prefix(lib_name(work), id, '.');
3✔
1400
   object_t *obj = lib_get_generic(lib_work(), qual, NULL);
3✔
1401
   vlog_node_t v = vlog_from_object(obj);
3✔
1402
   if (v == NULL || vlog_kind(v) != V_PACKAGE) {
3✔
1403
      parse_error(&state.last_loc, "no package named '%pi' in working "
×
1404
                  "library", id);
1405
      return NULL;
×
1406
   }
1407

1408
   return v;
1409
}
1410

1411
static vlog_node_t p_package_scope(void)
×
1412
{
1413
   // package_identifier :: | $unit ::
1414

1415
   BEGIN("package scope");
×
1416

1417
   switch (peek()) {
×
1418
   case tID:
×
1419
      {
1420
         vlog_node_t v = p_package_identifier();
×
1421
         consume(tSCOPE);
×
1422
         return v;
×
1423
      }
1424
   default:
×
1425
      one_of(tID);
×
1426
      return NULL;
×
1427
   }
1428
}
1429

1430
static vlog_node_t p_primary(void)
121,189✔
1431
{
1432
   // primary_literal | empty_queue
1433
   // | [ class_qualifier | package_scope ] hierarchical_identifier select
1434
   // | concatenation [ [ range_expression ] ]
1435
   // | multiple_concatenation [ [ range_expression ] ]
1436
   // | function_subroutine_call
1437
   // | let_expression | ( mintypmax_expression ) | cast
1438
   // | assignment_pattern_expression | streaming_concatenation
1439
   // | sequence_method_call | this | $ | null
1440

1441
   BEGIN("primary");
242,378✔
1442

1443
   switch (peek()) {
121,189✔
1444
   case tID:
29,434✔
1445
      switch (peek_nth(2)) {
29,434✔
1446
      case tLPAREN:
310✔
1447
      case tATTRBEGIN:
1448
         return p_subroutine_call(V_USER_FCALL);
310✔
1449
      case tSCOPE:
×
1450
         p_package_scope();
×
1451
      default:
29,124✔
1452
         return p_select(p_identifier());
29,124✔
1453
      }
1454
   case tSTRING:
44,934✔
1455
   case tNUMBER:
1456
   case tUNSNUM:
1457
   case tREAL:
1458
      return p_primary_literal();
44,934✔
1459
   case tSYSTASK:
2,934✔
1460
      return p_subroutine_call(V_SYS_FCALL);
2,934✔
1461
   case tLPAREN:
43,544✔
1462
      {
1463
         consume(tLPAREN);
43,544✔
1464
         vlog_node_t expr = p_mintypmax_expression();
43,544✔
1465
         consume(tRPAREN);
43,544✔
1466
         return expr;
43,544✔
1467
      }
1468
   case tLBRACE:
325✔
1469
      {
1470
         consume(tLBRACE);
325✔
1471

1472
         vlog_node_t head = p_expression();
325✔
1473
         if (peek() == tLBRACE)
325✔
1474
            return p_multiple_concatenation(head);
93✔
1475
         else
1476
            return p_concatenation(head);
232✔
1477
      }
1478
   case tNULL:
18✔
1479
      {
1480
         consume(tNULL);
18✔
1481

1482
         vlog_node_t v = vlog_new(V_NULL);
18✔
1483
         vlog_set_loc(v, CURRENT_LOC);
18✔
1484
         return v;
18✔
1485
      }
1486

1487
   default:
×
1488
      one_of(tID, tSTRING, tNUMBER, tUNSNUM, tREAL, tSYSTASK, tLPAREN,
×
1489
             tLBRACE, tNULL);
1490
      return p_select(error_marker());
×
1491
   }
1492
}
1493

1494
static vlog_binary_t p_binary_operator(void)
31,197✔
1495
{
1496
   // + | - | * | / | % | == | != | === | !== | ==? | !=? | && | ||
1497
   //  | ** | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | <<
1498
   //  | >>> | <<< | -> | <->
1499

1500
   BEGIN("binary operator");
62,394✔
1501

1502
   switch (one_of(tBAR, tPLUS, tAMP, tCASEEQ, tCASENEQ, tLOGOR,
31,197✔
1503
                  tLOGEQ, tLOGNEQ, tDBLAMP, tSHIFTLL, tSHIFTRL,
1504
                  tSHIFTLA, tSHIFTRA, tLT, tGT, tLE, tGE, tMINUS,
1505
                  tTIMES, tOVER, tPERCENT, tPOWER, tCARET, tTILDECARET,
1506
                  tTILDEAMP, tTILDEBAR)) {
1507
   case tBAR:        return V_BINARY_OR;
1508
   case tAMP:        return V_BINARY_AND;
1,252✔
1509
   case tCASEEQ:     return V_BINARY_CASE_EQ;
1,539✔
1510
   case tCASENEQ:    return V_BINARY_CASE_NEQ;
3,917✔
1511
   case tLOGEQ:      return V_BINARY_LOG_EQ;
1,744✔
1512
   case tLOGNEQ:     return V_BINARY_LOG_NEQ;
1,760✔
1513
   case tLOGOR:      return V_BINARY_LOG_OR;
2,330✔
1514
   case tDBLAMP:     return V_BINARY_LOG_AND;
1,518✔
1515
   case tSHIFTLL:    return V_BINARY_SHIFT_LL;
42✔
1516
   case tSHIFTRL:    return V_BINARY_SHIFT_RL;
32✔
1517
   case tSHIFTLA:    return V_BINARY_SHIFT_LA;
10✔
1518
   case tSHIFTRA:    return V_BINARY_SHIFT_RA;
27✔
1519
   case tLT:         return V_BINARY_LT;
1,373✔
1520
   case tGT:         return V_BINARY_GT;
1,425✔
1521
   case tLE:         return V_BINARY_LEQ;
1,400✔
1522
   case tGE:         return V_BINARY_GEQ;
1,452✔
1523
   case tMINUS:      return V_BINARY_MINUS;
1,777✔
1524
   case tTIMES:      return V_BINARY_TIMES;
1,373✔
1525
   case tOVER:       return V_BINARY_DIVIDE;
1,332✔
1526
   case tPERCENT:    return V_BINARY_MOD;
1,330✔
1527
   case tPOWER:      return V_BINARY_EXP;
17✔
1528
   case tCARET:      return V_BINARY_XOR;
1,211✔
1529
   case tTILDECARET: return V_BINARY_XNOR;
6✔
1530
   case tTILDEAMP:   return V_BINARY_NAND;
16✔
1531
   case tTILDEBAR:   return V_BINARY_NOR;
20✔
1532
   case tPLUS:
2,753✔
1533
   default:          return V_BINARY_PLUS;
2,753✔
1534
   }
1535
}
1536

1537
static vlog_unary_t p_unary_operator(void)
9,275✔
1538
{
1539
   // + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
1540

1541
   BEGIN("unary operator");
18,550✔
1542

1543
   switch (one_of(tMINUS, tPLUS, tTILDE, tBANG, tAMP, tBAR, tCARET,
9,275✔
1544
                  tTILDEAMP, tTILDEBAR, tTILDECARET)) {
1545
   case tMINUS:      return V_UNARY_NEG;
1546
   case tTILDE:      return V_UNARY_BITNEG;
1,246✔
1547
   case tBANG:       return V_UNARY_NOT;
1,333✔
1548
   case tAMP:        return V_UNARY_AND;
1,309✔
1549
   case tBAR:        return V_UNARY_OR;
1,233✔
1550
   case tCARET:      return V_UNARY_XOR;
1,177✔
1551
   case tTILDEAMP:   return V_UNARY_NAND;
5✔
1552
   case tTILDEBAR:   return V_UNARY_NOR;
4✔
1553
   case tTILDECARET: return V_UNARY_XNOR;
×
1554
   case tPLUS:
1,330✔
1555
   default:          return V_UNARY_IDENTITY;
1,330✔
1556
   }
1557
}
1558

1559
static vlog_incdec_t p_inc_or_dec_operator(void)
42✔
1560
{
1561
   // ++ | --
1562

1563
   BEGIN("inc or dec operator");
84✔
1564

1565
   switch (one_of(tPLUSPLUS, tMINUSMINUS)) {
42✔
1566
   case tMINUSMINUS: return V_INCDEC_MINUS;
1567
   case tPLUSPLUS:
41✔
1568
   default: return V_INCDEC_PLUS;
41✔
1569
   }
1570
}
1571

1572
static vlog_node_t p_inc_or_dec_expression(vlog_node_t head)
40✔
1573
{
1574
   // inc_or_dec_operator { attribute_instance } variable_lvalue
1575
   //   | variable_lvalue { attribute_instance } inc_or_dec_operator
1576

1577
   BEGIN_WITH_HEAD("inc or dec expression", head);
80✔
1578

1579
   vlog_node_t v = vlog_new(head ? V_POSTFIX : V_PREFIX);
46✔
1580
   vlog_set_subkind(v, p_inc_or_dec_operator());
40✔
1581
   vlog_set_target(v, head ?: p_variable_lvalue());
40✔
1582

1583
   vlog_set_loc(v, CURRENT_LOC);
40✔
1584
   return v;
40✔
1585
}
1586

1587
static vlog_node_t p_nonbinary_expression(void)
121,195✔
1588
{
1589
   // primary | unary_operator { attribute_instance } primary
1590
   //   | inc_or_dec_expression | ( operator_assignment )
1591
   //   | conditional_expression | inside_expression | tagged_union_expression
1592

1593
   switch (peek()) {
121,195✔
1594
   case tID:
111,914✔
1595
   case tSTRING:
1596
   case tNUMBER:
1597
   case tUNSNUM:
1598
   case tREAL:
1599
   case tSYSTASK:
1600
   case tLPAREN:
1601
   case tLBRACE:
1602
   case tNULL:
1603
      return p_primary();
111,914✔
1604
   case tMINUS:
9,275✔
1605
   case tPLUS:
1606
   case tTILDE:
1607
   case tBANG:
1608
   case tAMP:
1609
   case tBAR:
1610
   case tCARET:
1611
   case tTILDEAMP:
1612
   case tTILDEBAR:
1613
   case tTILDECARET:
1614
      {
1615
         vlog_node_t v = vlog_new(V_UNARY);
9,275✔
1616
         vlog_set_subkind(v, p_unary_operator());
9,275✔
1617

1618
         optional_attributes();
9,275✔
1619

1620
         vlog_set_value(v, p_primary());
9,275✔
1621
         vlog_set_loc(v, CURRENT_LOC);
9,275✔
1622
         return v;
9,275✔
1623
      }
1624
   case tPLUSPLUS:
5✔
1625
   case tMINUSMINUS:
1626
      return p_inc_or_dec_expression(NULL);
5✔
1627
   default:
1✔
1628
      one_of(tID, tSTRING, tNUMBER, tUNSNUM, tREAL, tSYSTASK, tLPAREN,
1✔
1629
             tLBRACE, tNULL, tMINUS, tTILDE, tBANG, tAMP, tBAR, tCARET,
1630
             tTILDEAMP, tTILDEBAR, tPLUSPLUS, tTILDECARET, tMINUSMINUS);
1631
      return p_select(error_marker());
1✔
1632
   }
1633
}
1634

1635
static vlog_node_t p_conditional_expression(vlog_node_t head)
1,506✔
1636
{
1637
   // cond_predicate ? { attribute_instance } expression : expression
1638

1639
   BEGIN_WITH_HEAD("conditional expression", head);
3,012✔
1640

1641
   vlog_node_t v = vlog_new(V_COND_EXPR);
1,506✔
1642
   vlog_set_value(v, head);
1,506✔
1643

1644
   consume(tQUESTION);
1,506✔
1645

1646
   optional_attributes();
1,506✔
1647

1648
   vlog_set_left(v, p_expression());
1,506✔
1649

1650
   consume(tCOLON);
1,506✔
1651

1652
   vlog_set_right(v, p_expression());
1,506✔
1653

1654
   vlog_set_loc(v, CURRENT_LOC);
1,506✔
1655
   return v;
1,506✔
1656
}
1657

1658
static bool peek_binary_operator(int *prec)
156,460✔
1659
{
1660
   // See LRM 1800-2017 section 11.3.2 for operator precedence table
1661

1662
   switch (peek()) {
156,460✔
1663
   case tPOWER:      *prec = 12; return true;
21✔
1664
   case tTIMES:
4,047✔
1665
   case tOVER:
1666
   case tPERCENT:    *prec = 11; return true;
4,047✔
1667
   case tPLUS:
4,574✔
1668
   case tMINUS:      *prec = 10; return true;
4,574✔
1669
   case tSHIFTLL:
113✔
1670
   case tSHIFTRL:
1671
   case tSHIFTLA:
1672
   case tSHIFTRA:    *prec = 9;  return true;
113✔
1673
   case tLT:
5,678✔
1674
   case tGT:
1675
   case tLE:
1676
   case tGE:         *prec = 8;  return true;
5,678✔
1677
   case tCASEEQ:
10,204✔
1678
   case tCASENEQ:
1679
   case tLOGEQ:
1680
   case tLOGNEQ:     *prec = 7;  return true;
10,204✔
1681
   case tTILDEAMP:
1,270✔
1682
   case tAMP:        *prec = 6;  return true;
1,270✔
1683
   case tTILDECARET:
1,217✔
1684
   case tCARET:      *prec = 5;  return true;
1,217✔
1685
   case tTILDEBAR:
1,562✔
1686
   case tBAR:        *prec = 4;  return true;
1,562✔
1687
   case tDBLAMP:     *prec = 3;  return true;
1,806✔
1688
   case tLOGOR:      *prec = 2;  return true;
4,795✔
1689
   case tQUESTION:   *prec = 1;  return true;
1,516✔
1690
   default:
1691
      return false;
1692
   }
1693
}
1694

1695
static vlog_node_t p_binary_expression(vlog_node_t lhs, int min_prec)
91,279✔
1696
{
1697
   // Precedence climbing method, see
1698
   //    https://en.wikipedia.org/wiki/Operator-precedence_parser
1699

1700
   int prec1;
91,279✔
1701
   while (peek_binary_operator(&prec1) && prec1 >= min_prec) {
123,982✔
1702
      if (peek() == tQUESTION)
32,703✔
1703
         lhs = p_conditional_expression(lhs);
1,506✔
1704
      else {
1705
         vlog_node_t v = vlog_new(V_BINARY);
31,197✔
1706
         vlog_set_subkind(v, p_binary_operator());
31,197✔
1707
         vlog_set_left(v, lhs);
31,197✔
1708

1709
         optional_attributes();
31,197✔
1710

1711
         vlog_node_t rhs = p_nonbinary_expression();
31,197✔
1712

1713
         int prec2;
31,197✔
1714
         while (peek_binary_operator(&prec2) && prec2 > prec1)
32,478✔
1715
            rhs = p_binary_expression(rhs, prec1 + (prec2 > prec1));
1,281✔
1716

1717
         vlog_set_right(v, rhs);
31,197✔
1718
         vlog_set_loc(v, CURRENT_LOC);
31,197✔
1719
         lhs = v;
31,197✔
1720
      }
1721
   }
1722

1723
   return lhs;
91,279✔
1724
}
1725

1726
static vlog_node_t p_expression(void)
89,998✔
1727
{
1728
   // primary | unary_operator { attribute_instance } primary
1729
   //   | inc_or_dec_expression | ( operator_assignment )
1730
   //   | expression binary_operator { attribute_instance } expression
1731
   //   | conditional_expression | inside_expression | tagged_union_expression
1732

1733
   BEGIN("expression");
179,996✔
1734

1735
   vlog_node_t head = p_nonbinary_expression();
89,998✔
1736
   return p_binary_expression(head, 0);
89,998✔
1737
}
1738

1739
static void p_event_expression(vlog_node_t ctrl)
277✔
1740
{
1741
   // [ edge_identifier ] expression [ iff expression ]
1742
   //   | sequence_instance [ iff expression ]
1743
   //   | event_expression or event_expression
1744
   //   | event_expression , event_expression
1745
   //   | ( event_expression )
1746

1747
   BEGIN("event expression");
554✔
1748

1749
   do {
311✔
1750
      if (optional(tLPAREN)) {
311✔
1751
         p_event_expression(ctrl);
1✔
1752
         consume(tRPAREN);
1✔
1753
      }
1754
      else {
1755
         vlog_node_t v = vlog_new(V_EVENT);
310✔
1756

1757
         if (optional(tPOSEDGE))
310✔
1758
            vlog_set_subkind(v, V_EVENT_POSEDGE);
109✔
1759
         else if (optional(tNEGEDGE))
201✔
1760
            vlog_set_subkind(v, V_EVENT_NEGEDGE);
44✔
1761
         else
1762
            vlog_set_subkind(v, V_EVENT_LEVEL);
157✔
1763

1764
         vlog_set_value(v, p_expression());
310✔
1765
         vlog_set_loc(v, CURRENT_LOC);
310✔
1766

1767
         vlog_add_param(ctrl, v);
310✔
1768
      }
1769
   } while (optional(tOR) || optional(tCOMMA));
311✔
1770
}
277✔
1771

1772
static vlog_node_t p_cond_predicate(void)
2,465✔
1773
{
1774
   // expression_or_cond_pattern { &&& expression_or_cond_pattern }
1775

1776
   BEGIN("cond predicate");
4,930✔
1777

1778
   return p_expression();
2,465✔
1779
}
1780

1781
static vlog_node_t p_event_control(void)
355✔
1782
{
1783
   // @ hierarchical_event_identifier | @ ( event_expression )
1784
   //    | @* | @ (*) | @ ps_or_hierarchical_sequence_identifier
1785

1786
   BEGIN("event control");
710✔
1787

1788
   consume(tAT);
355✔
1789

1790
   vlog_node_t v = vlog_new(V_EVENT_CONTROL);
355✔
1791

1792
   switch (one_of(tLPAREN, tTIMES, tPARENSTAR)) {
355✔
1793
   case tLPAREN:
277✔
1794
      if (peek() == tATTREND)
277✔
1795
         consume(tATTREND);   // Lexing ambiguity
1✔
1796
      else {
1797
         p_event_expression(v);
276✔
1798
         consume(tRPAREN);
276✔
1799
      }
1800
      break;
1801
   case tTIMES:
1802
   case tPARENSTAR:
1803
      break;
1804
   }
1805

1806
   vlog_set_loc(v, CURRENT_LOC);
355✔
1807
   return v;
355✔
1808
}
1809

1810
static vlog_node_t p_delay_value(void)
4,624✔
1811
{
1812
   // unsigned_number | real_number | ps_identifier | time_literal | 1step
1813

1814
   BEGIN("delay value");
9,248✔
1815

1816
   switch (peek()) {
4,624✔
1817
   case tREAL:
5✔
1818
      return p_real_number();
5✔
1819
   case tID:
1✔
1820
      {
1821
         vlog_node_t v = vlog_new(V_REF);
1✔
1822
         vlog_set_ident(v, p_identifier());
1✔
1823
         vlog_set_loc(v, CURRENT_LOC);
1✔
1824

1825
         vlog_symtab_lookup(symtab, v);
1✔
1826
         return v;
1✔
1827
      }
1828
   case tUNSNUM:
4,618✔
1829
   default:
1830
      return p_unsigned_number();
4,618✔
1831
   }
1832
}
1833

1834
static vlog_node_t p_delay_control(void)
4,623✔
1835
{
1836
   // # delay_value | # ( mintypmax_expression )
1837

1838
   BEGIN("delay control");
9,246✔
1839

1840
   consume(tHASH);
4,623✔
1841

1842
   vlog_node_t v = vlog_new(V_DELAY_CONTROL);
4,623✔
1843

1844
   if (peek() != tLPAREN)
4,623✔
1845
      vlog_set_value(v, p_delay_value());
4,619✔
1846
   else
1847
      vlog_set_value(v, p_mintypmax_expression());
4✔
1848

1849
   vlog_set_loc(v, CURRENT_LOC);
4,623✔
1850
   return v;
4,623✔
1851
}
1852

1853
static void p_delay3(void)
7✔
1854
{
1855
   // # delay_value | # ( mintypmax_expression [ , mintypmax_expression
1856
   //   [ , mintypmax_expression ] ] )
1857

1858
   BEGIN("delay3");
14✔
1859

1860
   consume(tHASH);
7✔
1861

1862
   if (peek() != tLPAREN)
7✔
1863
      p_delay_value();
3✔
1864
   else {
1865
      consume(tLPAREN);
4✔
1866

1867
      int expr_cnt = 0;
4✔
1868
      do {
12✔
1869
         (void)p_mintypmax_expression();
12✔
1870
         expr_cnt++;
12✔
1871
      } while (optional(tCOMMA) && (expr_cnt < 3));
12✔
1872

1873
      consume(tRPAREN);
4✔
1874
   }
1875
}
7✔
1876

1877
static void p_delay2(void)
2✔
1878
{
1879
   // # delay_value | # ( mintypmax_expression [ , mintypmax_expression ] )
1880

1881
   BEGIN("delay2");
4✔
1882

1883
   consume(tHASH);
2✔
1884

1885
   if (peek() != tLPAREN)
2✔
1886
      p_delay_value();
1✔
1887
   else {
1888
      consume(tLPAREN);
1✔
1889

1890
      (void)p_mintypmax_expression();
1✔
1891

1892
      if (optional(tCOMMA))
1✔
1893
         (void)p_mintypmax_expression();
1✔
1894

1895
      consume(tRPAREN);
1✔
1896
   }
1897
}
2✔
1898

1899
static vlog_node_t p_delay_or_event_control(void)
50✔
1900
{
1901
   // delay_control | event_control | repeat ( expression ) event_control
1902

1903
   BEGIN("delay or event control");
100✔
1904

1905
   return p_delay_control();
50✔
1906
}
1907

1908
static vlog_node_t p_variable_lvalue(void)
11,296✔
1909
{
1910
   // [ implicit_class_handle . | package_scope ]
1911
   //      hierarchical_variable_identifier select
1912
   //   | { variable_lvalue { , variable_lvalue } }
1913
   //   | [ assignment_pattern_expression_type ]
1914
   //      assignment_pattern_variable_lvalue
1915
   //   | streaming_concatenation
1916

1917
   BEGIN("variable lvalue");
22,592✔
1918

1919
   if (optional(tLBRACE)) {
11,296✔
1920
      vlog_node_t v = vlog_new(V_CONCAT);
41✔
1921

1922
      do {
86✔
1923
         vlog_add_param(v, p_variable_lvalue());
86✔
1924
      } while (optional(tCOMMA));
86✔
1925

1926
      consume(tRBRACE);
41✔
1927

1928
      vlog_set_loc(v, CURRENT_LOC);
41✔
1929
      return v;
41✔
1930
   }
1931
   else {
1932
      ident_t id = p_identifier();
11,255✔
1933
      vlog_node_t v = p_select(id);
11,255✔
1934

1935
      vlog_set_loc(v, CURRENT_LOC);
11,255✔
1936
      return v;
11,255✔
1937
   }
1938
}
1939

1940
static vlog_node_t p_net_lvalue(void)
764✔
1941
{
1942
   // ps_or_hierarchical_net_identifier constant_select
1943
   //   | { net_lvalue { , net_lvalue } }
1944
   //   | [ assignment_pattern_expression_type ] assignment_pattern_net_lvalue
1945

1946
   BEGIN("net lvalue");
1,528✔
1947

1948
   if (optional(tLBRACE)) {
764✔
1949
      vlog_node_t v = vlog_new(V_CONCAT);
11✔
1950

1951
      do {
22✔
1952
         vlog_add_param(v, p_net_lvalue());
22✔
1953
      } while (optional(tCOMMA));
22✔
1954

1955
      consume(tRBRACE);
11✔
1956

1957
      vlog_set_loc(v, CURRENT_LOC);
11✔
1958
      return v;
11✔
1959
   }
1960
   else {
1961
      ident_t id = p_identifier();
753✔
1962
      vlog_node_t v = p_constant_select(id);
753✔
1963

1964
      vlog_set_loc(v, CURRENT_LOC);
753✔
1965
      return v;
753✔
1966
   }
1967
}
1968

1969
static vlog_node_t p_class_new(vlog_node_t dt)
8✔
1970
{
1971
   // [ class_scope ] new [ ( list_of_arguments ) ]
1972
   //    | new expression
1973

1974
   BEGIN("class new");
16✔
1975

1976
   consume(tNEW);
8✔
1977

1978
   if (dt == NULL || vlog_kind(dt) != V_CLASS_DECL) {
8✔
1979
      error_at(&state.last_loc, "new class expression must have class type");
1✔
1980
      dt = NULL;
1✔
1981
   }
1982

1983
   vlog_node_t v = vlog_new(V_CLASS_NEW);
8✔
1984
   vlog_set_type(v, dt);
8✔
1985

1986
   if (optional(tLPAREN)) {
8✔
1987
      p_list_of_arguments(v);
2✔
1988
      consume(tRPAREN);
2✔
1989
   }
1990

1991
   vlog_set_loc(v, CURRENT_LOC);
8✔
1992
   return v;
8✔
1993
}
1994

1995
static vlog_assign_t p_assignment_operator(void)
180✔
1996
{
1997
   // = | += | -= | *= | /= | %= | &= | |= | ^= | <<= | >>= | <<<= | >>>=
1998

1999
   BEGIN("assignment operator");
360✔
2000

2001
   switch (one_of(tEQ, tPLUSEQ, tMINUSEQ, tTIMESEQ, tDIVEQ, tPERCENTEQ, tAMPEQ,
180✔
2002
                  tBAREQ, tCARETEQ, tLSLEQ, tLSREQ, tASLEQ, tASREQ)) {
2003
   case tPLUSEQ:    return V_ASSIGN_PLUS;
2004
   case tMINUSEQ:   return V_ASSIGN_MINUS;
2005
   case tTIMESEQ:   return V_ASSIGN_TIMES;
2006
   case tDIVEQ:     return V_ASSIGN_DIVIDE;
2007
   case tPERCENTEQ: return V_ASSIGN_MOD;
2008
   case tAMPEQ:     return V_ASSIGN_AND;
2009
   case tBAREQ:     return V_ASSIGN_OR;
2010
   case tCARETEQ:   return V_ASSIGN_XOR;
2011
   case tLSLEQ:     return V_ASSIGN_SHIFT_LL;
2012
   case tLSREQ:     return V_ASSIGN_SHIFT_RL;
2013
   case tASLEQ:     return V_ASSIGN_SHIFT_LA;
2014
   case tASREQ:     return V_ASSIGN_SHIFT_RA;
2015
   default:         return V_ASSIGN_EQUALS;
2016
   }
2017
}
2018

2019
static vlog_node_t p_operator_assignment(vlog_node_t lhs)
180✔
2020
{
2021
   // variable_lvalue assignment_operator expression
2022

2023
   BEGIN_WITH_HEAD("operator assignment", lhs);
360✔
2024

2025
   vlog_node_t v = vlog_new(V_OP_ASSIGN);
180✔
2026
   vlog_set_subkind(v, p_assignment_operator());
180✔
2027
   vlog_set_target(v, lhs);
180✔
2028

2029
   vlog_set_value(v, p_expression());
180✔
2030

2031
   vlog_set_loc(v, CURRENT_LOC);
180✔
2032
   return v;
180✔
2033
}
2034

2035
static vlog_node_t p_blocking_assignment(vlog_node_t lhs)
10,674✔
2036
{
2037
   // variable_lvalue = delay_or_event_control expression
2038
   //   | nonrange_variable_lvalue = dynamic_array_new
2039
   //   | [ implicit_class_handle . | class_scope | package_scope ]
2040
   //         hierarchical_variable_identifier select = class_new
2041
   //   | operator_assignment
2042

2043
   BEGIN_WITH_HEAD("blocking assignment", lhs);
21,348✔
2044

2045
   switch (peek()) {
10,674✔
2046
   case tPLUSEQ:
108✔
2047
   case tMINUSEQ:
2048
   case tTIMESEQ:
2049
   case tDIVEQ:
2050
   case tPERCENTEQ:
2051
   case tAMPEQ:
2052
   case tBAREQ:
2053
   case tCARETEQ:
2054
   case tLSLEQ:
2055
   case tLSREQ:
2056
   case tASLEQ:
2057
   case tASREQ:
2058
      return p_operator_assignment(lhs);
108✔
2059
   }
2060

2061
   consume(tEQ);
10,566✔
2062

2063
   vlog_node_t v = vlog_new(V_BASSIGN);
10,566✔
2064
   vlog_set_target(v, lhs);
10,566✔
2065

2066
   if (peek() == tNEW)
10,566✔
2067
      vlog_set_value(v, p_class_new(vlog_get_type(lhs)));
8✔
2068
   else {
2069
      if (scan(tHASH, tAT))
10,558✔
2070
         vlog_set_delay(v, p_delay_or_event_control());
33✔
2071

2072
      vlog_set_value(v, p_expression());
10,558✔
2073
   }
2074

2075
   vlog_set_loc(v, CURRENT_LOC);
10,566✔
2076
   return v;
10,566✔
2077
}
2078

2079
static vlog_node_t p_nonblocking_assignment(vlog_node_t lhs)
332✔
2080
{
2081
   // variable_lvalue <= [ delay_or_event_control ] expression
2082

2083
   BEGIN_WITH_HEAD("non-blocking assignment", lhs);
664✔
2084

2085
   consume(tLE);
332✔
2086

2087
   vlog_node_t v = vlog_new(V_NBASSIGN);
332✔
2088
   vlog_set_target(v, lhs);
332✔
2089

2090
   if (scan(tHASH, tAT))
332✔
2091
      vlog_set_delay(v, p_delay_or_event_control());
17✔
2092

2093
   vlog_set_value(v, p_expression());
332✔
2094

2095
   vlog_set_loc(v, CURRENT_LOC);
332✔
2096
   return v;
332✔
2097
}
2098

2099
static vlog_node_t p_procedural_timing_control(void)
4,916✔
2100
{
2101
   // delay_control | event_control | cycle_delay
2102

2103
   BEGIN("procedural timing control");
9,832✔
2104

2105
   switch (peek()) {
4,916✔
2106
   case tAT:
355✔
2107
      return p_event_control();
355✔
2108
   case tHASH:
4,561✔
2109
      return p_delay_control();
4,561✔
2110
   default:
×
2111
      should_not_reach_here();
2112
   }
2113
}
2114

2115
static vlog_node_t p_procedural_timing_control_statement(void)
4,916✔
2116
{
2117
   // procedural_timing_control statement_or_null
2118

2119
   BEGIN("procedural timing control statement");
9,832✔
2120

2121
   vlog_node_t v = vlog_new(V_TIMING);
4,916✔
2122
   vlog_set_value(v, p_procedural_timing_control());
4,916✔
2123

2124
   vlog_node_t s = p_statement_or_null();
4,916✔
2125
   if (s != NULL)
4,916✔
2126
      vlog_add_stmt(v, s);
596✔
2127

2128
   vlog_set_loc(v, CURRENT_LOC);
4,916✔
2129
   return v;
4,916✔
2130
}
2131

2132
static vlog_node_t p_seq_block(ident_t id)
2,651✔
2133
{
2134
   // begin [ : block_identifier ] { block_item_declaration }
2135
   //   { statement_or_null } end [ : block_identifier ]
2136

2137
   BEGIN("sequential block");
5,302✔
2138

2139
   consume(tBEGIN);
2,651✔
2140

2141
   vlog_node_t v = vlog_new(V_BLOCK);
2,651✔
2142
   vlog_set_ident(v, id);
2,651✔
2143
   vlog_set_loc(v, CURRENT_LOC);
2,651✔
2144

2145
   vlog_symtab_push(symtab, v);
2,651✔
2146

2147
   if (optional(tCOLON)) {
2,651✔
2148
      ident_t name = p_identifier();
14✔
2149
      if (vlog_has_ident(v))
14✔
2150
         parse_error(&state.last_loc, "cannot specify both a statement label "
1✔
2151
                     "and a block name");
2152
      else
2153
         vlog_set_ident(v, name);
13✔
2154
   }
2155

2156
   skip_over_attributes();
2,651✔
2157

2158
   while (scan_block_item_declaration()) {
2,667✔
2159
      p_block_item_declaration(v);
16✔
2160
      skip_over_attributes();
16✔
2161
   }
2162

2163
   while (not_at_token(tEND)) {
25,658✔
2164
      vlog_node_t s = p_statement_or_null();
23,007✔
2165
      if (s != NULL)
23,007✔
2166
         vlog_add_stmt(v, s);
23,006✔
2167
   }
2168

2169
   vlog_symtab_pop(symtab);
2,651✔
2170

2171
   consume(tEND);
2,651✔
2172

2173
   if (optional(tCOLON)) {
2,651✔
2174
      ident_t name = p_identifier();
6✔
2175
      if (!vlog_has_ident(v))
6✔
2176
         parse_error(&state.last_loc, "initial block does not have a label");
1✔
2177
      else if (name != vlog_ident(v))
5✔
2178
         parse_error(&state.last_loc, "'%s' does not match label '%s'",
1✔
2179
                     istr(name), istr(vlog_ident(v)));
2180
   }
2181

2182
   return v;
2,651✔
2183
}
2184

2185
static vlog_node_t p_par_block(ident_t id)
7✔
2186
{
2187
   // fork [ : block_identifier ] { block_item_declaration }
2188
   //   { statement_or_null } join_keyword [ : block_identifier ]
2189

2190
   BEGIN("parallel block");
14✔
2191

2192
   consume(tFORK);
7✔
2193

2194
   vlog_node_t v = vlog_new(V_FORK);
7✔
2195
   vlog_set_ident(v, id);
7✔
2196
   vlog_set_loc(v, CURRENT_LOC);
7✔
2197

2198
   vlog_symtab_push(symtab, v);
7✔
2199

2200
   if (optional(tCOLON)) {
7✔
2201
      ident_t name = p_identifier();
4✔
2202
      if (vlog_has_ident(v))
4✔
2203
         parse_error(&state.last_loc, "cannot specify both a statement label "
1✔
2204
                     "and a block name");
2205
      else
2206
         vlog_set_ident(v, name);
3✔
2207
   }
2208

2209
   skip_over_attributes();
7✔
2210

2211
   while (scan_block_item_declaration()) {
9✔
2212
      p_block_item_declaration(v);
2✔
2213
      skip_over_attributes();
2✔
2214
   }
2215

2216
   while (not_at_token(tJOIN)) {
14✔
2217
      vlog_node_t s = p_statement_or_null();
7✔
2218
      if (s != NULL)
7✔
2219
         vlog_add_stmt(v, s);
7✔
2220
   }
2221

2222
   vlog_symtab_pop(symtab);
7✔
2223

2224
   consume(tJOIN);
7✔
2225

2226
   if (optional(tCOLON)) {
7✔
2227
      ident_t name = p_identifier();
5✔
2228
      if (!vlog_has_ident(v))
5✔
2229
         parse_error(&state.last_loc, "fork block does not have a label");
1✔
2230
      else if (name != vlog_ident(v))
4✔
2231
         parse_error(&state.last_loc, "'%s' does not match label '%s'",
1✔
2232
                     istr(name), istr(vlog_ident(v)));
2233
   }
2234

2235
   return v;
7✔
2236
}
2237

2238
static vlog_node_t p_subroutine_call_statement(void)
6,823✔
2239
{
2240
   // subroutine_call ; | void ' ( function_subroutine_call ) ;
2241

2242
   BEGIN("subroutine call statement");
13,646✔
2243

2244
   vlog_node_t v;
6,823✔
2245
   switch (peek()) {
6,823✔
2246
   case tSYSTASK:
6,694✔
2247
      v = p_subroutine_call(V_SYS_TCALL);
6,694✔
2248
      break;
6,694✔
2249
   case tVOID:
2✔
2250
      {
2251
         consume(tVOID);
2✔
2252
         consume(tTICK);
2✔
2253
         consume(tLPAREN);
2✔
2254

2255
         const vlog_kind_t kind =
4✔
2256
            peek() == tSYSTASK ? V_SYS_FCALL : V_USER_FCALL;
2✔
2257

2258
         v = vlog_new(V_VOID_CALL);
2✔
2259
         vlog_set_value(v, p_subroutine_call(kind));
2✔
2260

2261
         consume(tRPAREN);
2✔
2262
      }
2263
      break;
2✔
2264
   case tID:
127✔
2265
   default:
2266
      v = p_subroutine_call(V_USER_TCALL);
127✔
2267
      break;
127✔
2268
   }
2269

2270
   consume(tSEMI);
6,823✔
2271

2272
   vlog_set_loc(v, CURRENT_LOC);
6,823✔
2273
   return v;
6,823✔
2274
}
2275

2276
static vlog_node_t p_conditional_statement(void)
2,428✔
2277
{
2278
   // [ unique_priority ] if ( cond_predicate ) statement_or_null
2279
   //     { else if ( cond_predicate ) statement_or_null }
2280
   //     [ else statement_or_null ]
2281

2282
   BEGIN("conditional statement");
4,856✔
2283

2284
   vlog_node_t v = vlog_new(V_IF);
2,428✔
2285

2286
   consume(tIF);
2,428✔
2287
   consume(tLPAREN);
2,428✔
2288

2289
   vlog_node_t c0 = vlog_new(V_COND);
2,428✔
2290
   vlog_set_value(c0, p_cond_predicate());
2,428✔
2291
   vlog_add_cond(v, c0);
2,428✔
2292

2293
   consume(tRPAREN);
2,428✔
2294

2295
   vlog_node_t s0 = p_statement_or_null();
2,428✔
2296
   if (s0 != NULL)
2,428✔
2297
      vlog_add_stmt(c0, s0);
2,417✔
2298

2299
   bool stop = false;
2300
   while (!stop && optional(tELSE)) {
2,851✔
2301
      vlog_node_t c = vlog_new(V_COND);
423✔
2302
      vlog_add_cond(v, c);
423✔
2303

2304
      if (optional(tIF)) {
423✔
2305
         consume(tLPAREN);
37✔
2306
         vlog_set_value(c, p_cond_predicate());
37✔
2307
         consume(tRPAREN);
37✔
2308
      }
2309
      else
2310
         stop = true;
2311

2312
      vlog_node_t s = p_statement_or_null();
423✔
2313
      if (s != NULL)
423✔
2314
         vlog_add_stmt(c, s);
422✔
2315
   }
2316

2317
   vlog_set_loc(v, CURRENT_LOC);
2,428✔
2318
   return v;
2,428✔
2319
}
2320

2321
static vlog_node_t p_variable_assignment(vlog_kind_t kind)
90✔
2322
{
2323
   // variable_lvalue = expression
2324

2325
   BEGIN("variable assignment");
180✔
2326

2327
   vlog_node_t v = vlog_new(kind);
90✔
2328
   vlog_set_target(v, p_variable_lvalue());
90✔
2329

2330
   consume(tEQ);
90✔
2331

2332
   vlog_set_value(v, p_expression());
90✔
2333

2334
   vlog_set_loc(v, CURRENT_LOC);
90✔
2335
   return v;
90✔
2336
}
2337

2338
static void p_list_of_variable_assignments(vlog_node_t parent)
88✔
2339
{
2340
   // variable_assignment { , variable_assignment }
2341

2342
   BEGIN("list of variable assignments");
176✔
2343

2344
   do {
88✔
2345
      vlog_node_t v = p_variable_assignment(V_BASSIGN);
88✔
2346
      vlog_add_stmt(parent, v);
88✔
2347
   } while (optional(tCOMMA));
88✔
2348
}
88✔
2349

2350
static void p_for_variable_declaration(vlog_node_t parent)
7✔
2351
{
2352
   // [ var ] data_type variable_identifier = expression
2353
   //   { , variable_identifier = expression }
2354

2355
   BEGIN("for variable declaration");
14✔
2356

2357
   optional(tVAR);
7✔
2358

2359
   vlog_node_t dt = p_data_type();
7✔
2360

2361
   do {
7✔
2362
      vlog_node_t v = vlog_new(V_VAR_DECL);
7✔
2363
      vlog_set_ident(v, p_identifier());
7✔
2364
      vlog_set_type(v, dt);
7✔
2365

2366
      consume(tEQ);
7✔
2367

2368
      vlog_set_value(v, p_expression());
7✔
2369

2370
      vlog_set_loc(v, CURRENT_LOC);
7✔
2371
      vlog_add_decl(parent, v);
7✔
2372

2373
      vlog_symtab_put(symtab, v);
7✔
2374
   } while (optional(tCOMMA));
7✔
2375
}
7✔
2376

2377
static vlog_node_t p_for_initialization(void)
95✔
2378
{
2379
   // list_of_variable_assignments
2380
   //   | for_variable_declaration { , for_variable_declaration }
2381

2382
   BEGIN("for initialization");
190✔
2383

2384
   vlog_node_t v = vlog_new(V_FOR_INIT);
95✔
2385

2386
   if (scan(tREG, tSTRUCT, tUNION, tENUM, tSVINT, tINTEGER, tSVREAL,
95✔
2387
            tSHORTREAL, tREALTIME, tLOGIC, tVAR)) {
2388
      do {
7✔
2389
         p_for_variable_declaration(v);
7✔
2390
      } while (optional(tCOMMA));
7✔
2391
   }
2392
   else
2393
      p_list_of_variable_assignments(v);
88✔
2394

2395
   vlog_set_loc(v, CURRENT_LOC);
95✔
2396
   return v;
95✔
2397
}
2398

2399
static vlog_node_t p_for_step(void)
95✔
2400
{
2401
   // operator_assignment | inc_or_dec_expression | function_subroutine_call
2402

2403
   BEGIN("for step");
190✔
2404

2405
   vlog_node_t v = vlog_new(V_FOR_STEP);
95✔
2406

2407
   switch (peek()) {
95✔
2408
   case tPLUSPLUS:
1✔
2409
   case tMINUSMINUS:
2410
      vlog_add_stmt(v, p_inc_or_dec_expression(NULL));
1✔
2411
      break;
1✔
2412
   default:
94✔
2413
      {
2414
         vlog_node_t head = p_variable_lvalue();
94✔
2415

2416
         switch (peek()) {
94✔
2417
         case tPLUSPLUS:
22✔
2418
         case tMINUSMINUS:
2419
            vlog_add_stmt(v, p_inc_or_dec_expression(head));
22✔
2420
            break;
22✔
2421
         default:
72✔
2422
            vlog_add_stmt(v, p_operator_assignment(head));
72✔
2423
            break;
72✔
2424
         }
2425
      }
2426
      break;
2427
   }
2428

2429
   vlog_set_loc(v, CURRENT_LOC);
95✔
2430
   return v;
95✔
2431
}
2432

2433
static vlog_node_t p_loop_statement(void)
135✔
2434
{
2435
   // forever statement_or_null
2436
   //   | repeat ( expression ) statement_or_null
2437
   //   | while ( expression ) statement_or_null
2438
   //   | for ( [ for_initialization ] ; [ expression ] ; [ for_step ] )
2439
   //       statement_or_null
2440
   //   | do statement_or_null while ( expression ) ;
2441
   //   | foreach ( ps_or_hierarchical_array_identifier [ loop_variables ] )
2442
   //       statement
2443

2444
   BEGIN("loop statement");
270✔
2445

2446
   switch (one_of(tFOREVER, tWHILE, tREPEAT, tDO, tFOR)) {
135✔
2447
   case tFOREVER:
13✔
2448
      {
2449
         vlog_node_t v = vlog_new(V_FOREVER);
13✔
2450

2451
         vlog_node_t s = p_statement_or_null();
13✔
2452
         if (s != NULL)
13✔
2453
            vlog_add_stmt(v, s);
13✔
2454

2455
         vlog_set_loc(v, CURRENT_LOC);
13✔
2456
         return v;
13✔
2457
      }
2458

2459
   case tWHILE:
6✔
2460
      {
2461
         vlog_node_t v = vlog_new(V_WHILE);
6✔
2462

2463
         consume(tLPAREN);
6✔
2464
         vlog_set_value(v, p_expression());
6✔
2465
         consume(tRPAREN);
6✔
2466

2467
         vlog_node_t s = p_statement_or_null();
6✔
2468
         if (s != NULL)
6✔
2469
            vlog_add_stmt(v, s);
4✔
2470

2471
         vlog_set_loc(v, CURRENT_LOC);
6✔
2472
         return v;
6✔
2473
      }
2474

2475
   case tREPEAT:
18✔
2476
      {
2477
         vlog_node_t v = vlog_new(V_REPEAT);
18✔
2478

2479
         consume(tLPAREN);
18✔
2480
         vlog_set_value(v, p_expression());
18✔
2481
         consume(tRPAREN);
18✔
2482

2483
         vlog_node_t s = p_statement_or_null();
18✔
2484
         if (s != NULL)
18✔
2485
            vlog_add_stmt(v, s);
18✔
2486

2487
         vlog_set_loc(v, CURRENT_LOC);
18✔
2488
         return v;
18✔
2489
      }
2490

2491
   case tDO:
2✔
2492
      {
2493
         vlog_node_t v = vlog_new(V_DO_WHILE);
2✔
2494

2495
         vlog_node_t s = p_statement_or_null();
2✔
2496
         if (s != NULL)
2✔
2497
            vlog_add_stmt(v, s);
2✔
2498

2499
         consume(tWHILE);
2✔
2500

2501
         consume(tLPAREN);
2✔
2502
         vlog_set_value(v, p_expression());
2✔
2503
         consume(tRPAREN);
2✔
2504
         consume(tSEMI);
2✔
2505

2506
         vlog_set_loc(v, CURRENT_LOC);
2✔
2507
         return v;
2✔
2508
      }
2509

2510
   case tFOR:
96✔
2511
      {
2512
         vlog_node_t v = vlog_new(V_FOR_LOOP);
96✔
2513

2514
         vlog_symtab_push(symtab, v);
96✔
2515

2516
         consume(tLPAREN);
96✔
2517

2518
         if (not_at_token(tSEMI))
96✔
2519
            vlog_set_left(v, p_for_initialization());
95✔
2520
         else
2521
            vlog_set_left(v, vlog_new(V_FOR_INIT));
1✔
2522

2523
         consume(tSEMI);
96✔
2524

2525
         if (not_at_token(tSEMI))
96✔
2526
            vlog_set_value(v, p_expression());
94✔
2527

2528
         consume(tSEMI);
96✔
2529

2530
         if (not_at_token(tRPAREN))
96✔
2531
            vlog_set_right(v, p_for_step());
95✔
2532
         else
2533
            vlog_set_right(v, vlog_new(V_FOR_STEP));
1✔
2534

2535
         consume(tRPAREN);
96✔
2536

2537
         vlog_node_t s = p_statement_or_null();
96✔
2538
         if (s != NULL)
96✔
2539
            vlog_add_stmt(v, s);
93✔
2540

2541
         vlog_symtab_pop(symtab);
96✔
2542

2543
         vlog_set_loc(v, CURRENT_LOC);
96✔
2544
         return v;
96✔
2545
      }
2546

2547
   default:
×
2548
      should_not_reach_here();
2549
   }
2550
}
2551

2552
static vlog_node_t p_wait_statement(void)
1✔
2553
{
2554
   // wait ( expression ) statement_or_null
2555
   //   | wait fork ;
2556
   //   | wait_order ( hierarchical_identifier { , hierarchical_identifier } )
2557
   //       action_block
2558

2559
   BEGIN("wait statement");
2✔
2560

2561
   consume(tWAIT);
1✔
2562

2563
   vlog_node_t v = vlog_new(V_WAIT);
1✔
2564

2565
   consume(tLPAREN);
1✔
2566

2567
   vlog_set_value(v, p_expression());
1✔
2568

2569
   consume(tRPAREN);
1✔
2570

2571
   vlog_node_t s = p_statement_or_null();
1✔
2572
   if (s != NULL)
1✔
2573
      vlog_add_stmt(v, s);
1✔
2574

2575
   vlog_set_loc(v, CURRENT_LOC);
1✔
2576
   return v;
1✔
2577
}
2578

2579
static vlog_node_t p_case_item(void)
196✔
2580
{
2581
   // case_item_expression { , case_item_expression } : statement_or_null
2582
   //   | default [ : ] statement_or_null
2583

2584
   BEGIN("case item");
392✔
2585

2586
   vlog_node_t v = vlog_new(V_CASE_ITEM);
196✔
2587

2588
   if (optional(tDEFAULT))
196✔
2589
      optional(tCOLON);
43✔
2590
   else {
2591
      do {
157✔
2592
         vlog_add_param(v, p_expression());
157✔
2593
      } while (optional(tCOMMA));
157✔
2594

2595
      consume(tCOLON);
153✔
2596
   }
2597

2598
   vlog_set_loc(v, CURRENT_LOC);
196✔
2599

2600
   vlog_node_t s = p_statement_or_null();
196✔
2601
   if (s != NULL)
196✔
2602
      vlog_add_stmt(v, s);
195✔
2603

2604
   return v;
196✔
2605
}
2606

2607
static vlog_node_t p_case_statement(void)
54✔
2608
{
2609
   // [ unique_priority ] case_keyword ( case_expression )
2610
   //        case_item { case_item } endcase
2611
   //   | [ unique_priority ] case_keyword ( case_expression ) matches
2612
   //        case_pattern_item { case_pattern_item } endcase
2613
   //   | [ unique_priority ] case ( case_expression ) inside case_inside_item
2614
   //        { case_inside_item } endcase
2615

2616
   BEGIN("case statement");
108✔
2617

2618
   vlog_case_kind_t kind = V_CASE_NORMAL;
54✔
2619
   switch (one_of(tCASE, tCASEX, tCASEZ)) {
54✔
2620
   case tCASEX: kind = V_CASE_X; break;
9✔
2621
   case tCASEZ: kind = V_CASE_Z; break;
12✔
2622
   }
2623

2624
   vlog_node_t v = vlog_new(V_CASE);
54✔
2625
   vlog_set_subkind(v, kind);
54✔
2626

2627
   consume(tLPAREN);
54✔
2628

2629
   vlog_set_value(v, p_expression());
54✔
2630

2631
   consume(tRPAREN);
54✔
2632

2633
   do {
196✔
2634
      vlog_add_stmt(v, p_case_item());
196✔
2635
   } while (not_at_token(tENDCASE));
196✔
2636

2637
   consume(tENDCASE);
54✔
2638

2639
   vlog_set_loc(v, CURRENT_LOC);
54✔
2640
   return v;
54✔
2641
}
2642

2643
static vlog_node_t p_event_trigger(void)
1✔
2644
{
2645
   // -> hierarchical_event_identifier ;
2646
   //   | ->> [ delay_or_event_control ] hierarchical_event_identifier ;
2647

2648
   BEGIN("event trigger");
2✔
2649

2650
   consume(tIFIMPL);
1✔
2651

2652
   vlog_node_t v = vlog_new(V_EVENT_TRIGGER);
1✔
2653
   vlog_set_ident(v, p_identifier());
1✔
2654

2655
   consume(tSEMI);
1✔
2656

2657
   vlog_set_loc(v, CURRENT_LOC);
1✔
2658
   return v;
1✔
2659
}
2660

2661
static vlog_node_t p_procedural_continuous_assignment(void)
4✔
2662
{
2663
   // assign variable_assignment | deassign variable_lvalue
2664
   //   | force variable_assignment | force net_assignment
2665
   //   | release variable_lvalue | release net_lvalue
2666

2667
   BEGIN("procedural continuous assignment");
8✔
2668

2669
   switch (one_of(tASSIGN, tDEASSIGN, tFORCE, tRELEASE)) {
4✔
2670
   case tASSIGN:
1✔
2671
   default:
2672
      return p_variable_assignment(V_ASSIGN);
1✔
2673
   case tDEASSIGN:
1✔
2674
      {
2675
         vlog_node_t v = vlog_new(V_DEASSIGN);
1✔
2676
         vlog_set_target(v, p_variable_lvalue());
1✔
2677
         vlog_set_loc(v, CURRENT_LOC);
1✔
2678
         return v;
1✔
2679
      }
2680
   case tFORCE:
1✔
2681
      return p_variable_assignment(V_FORCE);
1✔
2682
   case tRELEASE:
1✔
2683
      {
2684
         vlog_node_t v = vlog_new(V_RELEASE);
1✔
2685
         vlog_set_target(v, p_variable_lvalue());
1✔
2686
         vlog_set_loc(v, CURRENT_LOC);
1✔
2687
         return v;
1✔
2688
      }
2689
   }
2690
}
2691

2692
static vlog_node_t p_disable_statement(void)
1✔
2693
{
2694
   // disable hierarchical_task_identifier ;
2695
   //   | disable hierarchical_block_identifier ;
2696
   //   | disable fork ;
2697

2698
   BEGIN("disable statement");
2✔
2699

2700
   consume(tDISABLE);
1✔
2701

2702
   vlog_node_t v = vlog_new(V_DISABLE);
1✔
2703
   vlog_set_ident(v, p_identifier());
1✔
2704

2705
   consume(tSEMI);
1✔
2706

2707
   vlog_set_loc(v, CURRENT_LOC);
1✔
2708
   return v;
1✔
2709
}
2710

2711
static vlog_node_t p_jump_statement(void)
7✔
2712
{
2713
   // return [ expression ] ; | break ; | continue ;
2714

2715
   BEGIN("jump statement");
14✔
2716

2717
   switch (one_of(tRETURN)) {
7✔
2718
   case tRETURN:
7✔
2719
      {
2720
         vlog_node_t v = vlog_new(V_RETURN);
7✔
2721

2722
         vlog_node_t subr = vlog_symtab_subr(symtab);
7✔
2723
         if (subr == NULL)
7✔
2724
            parse_error(&state.last_loc, "return statement can only be used "
1✔
2725
                        "in a subroutine");
2726
         else
2727
            vlog_set_ref(v, subr);
6✔
2728

2729
         if (peek() != tSEMI)
7✔
2730
            vlog_set_value(v, p_expression());
5✔
2731

2732
         consume(tSEMI);
7✔
2733

2734
         vlog_set_loc(v, CURRENT_LOC);
7✔
2735
         return v;
14✔
2736
      }
2737
   default:
×
2738
      should_not_reach_here();
2739
   }
2740
}
2741

2742
static vlog_node_t p_statement_item(ident_t id)
28,048✔
2743
{
2744
   // blocking_assignment ; | nonblocking_assignment ;
2745
   //   | procedural_continuous_assignment ; | case_statement
2746
   //   | conditional_statement | inc_or_dec_expression ;
2747
   //   | subroutine_call_statement | disable_statement
2748
   //   | event_trigger | loop_statement | jump_statement
2749
   //   | par_block | procedural_timing_control_statement
2750
   //   | seq_block | wait_statement | procedural_assertion_statement
2751
   //   | clocking_drive ; | randsequence_statement | randcase_statement
2752
   //   | expect_property_statement
2753

2754
   BEGIN("statement item");
56,096✔
2755

2756
   switch (peek()) {
28,048✔
2757
   case tID:
11,104✔
2758
      switch (peek_nth(2)) {
11,104✔
2759
      case tLPAREN:
127✔
2760
      case tSEMI:
2761
      case tATTRBEGIN:
2762
         return p_subroutine_call_statement();
127✔
2763
      default:
10,977✔
2764
         {
2765
            vlog_node_t lhs = p_variable_lvalue(), v;
10,977✔
2766

2767
            switch (peek()) {
10,977✔
2768
            case tLE:
328✔
2769
               v = p_nonblocking_assignment(lhs);
328✔
2770
               break;
328✔
2771
            case tPLUSPLUS:
12✔
2772
            case tMINUSMINUS:
2773
               v = p_inc_or_dec_expression(lhs);
12✔
2774
               break;
12✔
2775
            default:
10,637✔
2776
               v = p_blocking_assignment(lhs);
10,637✔
2777
               break;
10,637✔
2778
            }
2779

2780
            consume(tSEMI);
10,977✔
2781
            return v;
10,977✔
2782
         }
2783
      }
2784
   case tLBRACE:
41✔
2785
      {
2786
         vlog_node_t lhs = p_variable_lvalue(), v;
41✔
2787

2788
         if (peek() == tLE)
41✔
2789
            v = p_nonblocking_assignment(lhs);
4✔
2790
         else
2791
            v = p_blocking_assignment(lhs);
37✔
2792

2793
         consume(tSEMI);
41✔
2794
         return v;
41✔
2795
      }
2796
   case tDISABLE:
1✔
2797
      return p_disable_statement();
1✔
2798
   case tAT:
4,916✔
2799
   case tHASH:
2800
      return p_procedural_timing_control_statement();
4,916✔
2801
   case tBEGIN:
2,651✔
2802
      return p_seq_block(id);
2,651✔
2803
   case tFORK:
7✔
2804
      return p_par_block(id);
7✔
2805
   case tSYSTASK:
6,696✔
2806
   case tVOID:
2807
      return p_subroutine_call_statement();
6,696✔
2808
   case tIF:
2,428✔
2809
      return p_conditional_statement();
2,428✔
2810
   case tFOREVER:
135✔
2811
   case tWHILE:
2812
   case tREPEAT:
2813
   case tDO:
2814
   case tFOR:
2815
      return p_loop_statement();
135✔
2816
   case tWAIT:
1✔
2817
      return p_wait_statement();
1✔
2818
   case tCASE:
54✔
2819
   case tCASEX:
2820
   case tCASEZ:
2821
      return p_case_statement();
54✔
2822
   case tIFIMPL:
1✔
2823
      return p_event_trigger();
1✔
2824
   case tASSIGN:
4✔
2825
   case tDEASSIGN:
2826
   case tFORCE:
2827
   case tRELEASE:
2828
      {
2829
         vlog_node_t v = p_procedural_continuous_assignment();
4✔
2830
         consume(tSEMI);
4✔
2831
         return v;
4✔
2832
      }
2833
   case tRETURN:
7✔
2834
      return p_jump_statement();
7✔
2835
   default:
2✔
2836
      one_of(tID, tAT, tHASH, tBEGIN, tFORK, tSYSTASK, tVOID, tIF, tFOREVER,
2✔
2837
             tWHILE, tREPEAT, tDO, tFOR, tWAIT, tCASE, tCASEX, tCASEZ, tIFIMPL,
2838
             tASSIGN, tDEASSIGN, tFORCE, tRELEASE, tRETURN);
2839
      drop_tokens_until(&state, tSEMI);
2✔
2840
      return vlog_new(V_BLOCK);  // Dummy statement
2✔
2841
   }
2842
}
2843

2844
static vlog_node_t p_statement(void)
28,048✔
2845
{
2846
   // [ block_identifier : ] { attribute_instance } statement_item
2847

2848
   BEGIN("statement");
56,096✔
2849

2850
   ident_t id = NULL;
28,048✔
2851
   if (peek() == tID && peek_nth(2) == tCOLON) {
28,048✔
2852
      id = p_identifier();
6✔
2853
      consume(tCOLON);
6✔
2854
   }
2855

2856
   optional_attributes();
28,048✔
2857

2858
   return p_statement_item(id);
28,048✔
2859
}
2860

2861
static vlog_node_t p_statement_or_null(void)
32,061✔
2862
{
2863
   // statement | { attribute_instance } ;
2864

2865
   BEGIN("statement or null");
64,122✔
2866

2867
   if (optional(tSEMI))
32,061✔
2868
      return NULL;
2869
   else
2870
      return p_statement();
27,721✔
2871
}
2872

2873
static vlog_node_t p_always_construct(void)
326✔
2874
{
2875
   // always_keyword statement
2876

2877
   BEGIN("always construct");
652✔
2878

2879
   vlog_node_t v = vlog_new(V_ALWAYS);
326✔
2880

2881
   switch (one_of(tALWAYS, tALWAYSCOMB, tALWAYSFF, tALWAYSLATCH)) {
326✔
2882
   case tALWAYSCOMB:  vlog_set_subkind(v, V_ALWAYS_COMB);  break;
1✔
2883
   case tALWAYSFF:    vlog_set_subkind(v, V_ALWAYS_FF);    break;
1✔
2884
   case tALWAYSLATCH: vlog_set_subkind(v, V_ALWAYS_LATCH); break;
5✔
2885
   default:           vlog_set_subkind(v, V_ALWAYS_PLAIN); break;
319✔
2886
   }
2887

2888
   vlog_set_ident(v, default_label("always"));
326✔
2889
   vlog_add_stmt(v, p_statement());
326✔
2890

2891
   vlog_set_loc(v, CURRENT_LOC);
326✔
2892
   return v;
326✔
2893
}
2894

2895
static vlog_node_t p_final_construct(void)
1✔
2896
{
2897
   // final function_statement
2898

2899
   BEGIN("final construct");
2✔
2900

2901
   consume(tFINAL);
1✔
2902

2903
   vlog_node_t v = vlog_new(V_FINAL);
1✔
2904
   vlog_set_ident(v, default_label("final"));
1✔
2905
   vlog_add_stmt(v, p_statement());
1✔
2906

2907
   vlog_set_loc(v, CURRENT_LOC);
1✔
2908
   return v;
1✔
2909
}
2910

2911
static vlog_node_t p_initial_construct(void)
795✔
2912
{
2913
   // initial statement_or_null
2914

2915
   BEGIN("initial construct");
1,590✔
2916

2917
   consume(tINITIAL);
795✔
2918

2919
   vlog_node_t v = vlog_new(V_INITIAL);
795✔
2920
   vlog_set_ident(v, default_label("initial"));
795✔
2921

2922
   vlog_node_t s = p_statement_or_null();
795✔
2923
   if (s != NULL)
795✔
2924
      vlog_add_stmt(v, s);
795✔
2925

2926
   vlog_set_loc(v, CURRENT_LOC);
795✔
2927
   return v;
795✔
2928
}
2929

2930
static vlog_node_t p_net_assignment(vlog_node_t delay, vlog_node_t strength)
660✔
2931
{
2932
   // net_lvalue = expression
2933

2934
   BEGIN("net assignment");
1,320✔
2935

2936
   vlog_symtab_set_implicit(symtab, implicit_kind);
660✔
2937

2938
   vlog_node_t v = vlog_new(V_ASSIGN);
660✔
2939
   vlog_set_target(v, p_net_lvalue());
660✔
2940
   vlog_set_ident(v, default_label("assign"));
660✔
2941
   vlog_set_delay(v, delay);
660✔
2942
   if (strength != NULL)
660✔
2943
      vlog_add_param(v, strength);
51✔
2944

2945
   vlog_symtab_set_implicit(symtab, V_NET_NONE);
660✔
2946

2947
   consume(tEQ);
660✔
2948

2949
   vlog_set_value(v, p_expression());
660✔
2950

2951
   vlog_set_loc(v, CURRENT_LOC);
660✔
2952
   return v;
660✔
2953
}
2954

2955
static void p_list_of_net_assignments(vlog_node_t mod, vlog_node_t delay,
660✔
2956
                                      vlog_node_t strength)
2957
{
2958
   // net_assignment { , net_assignment }
2959

2960
   BEGIN("list of net assignments");
1,320✔
2961

2962
   do {
660✔
2963
      vlog_add_stmt(mod, p_net_assignment(delay, strength));
660✔
2964
   } while (optional(tCOMMA));
660✔
2965
}
660✔
2966

2967
static void p_continuous_assign(vlog_node_t mod)
660✔
2968
{
2969
   // assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;
2970
   //   | assign [ delay_control ] list_of_variable_assignments ;
2971

2972
   BEGIN("continuous assignment");
1,320✔
2973

2974
   consume(tASSIGN);
660✔
2975

2976
   vlog_node_t delay = NULL;
660✔
2977
   vlog_node_t strength = NULL;
660✔
2978
   if (peek() == tLPAREN) {
660✔
2979
      strength = p_drive_strength();
51✔
2980
      if (peek() == tHASH)
51✔
2981
         p_delay3();
2✔
2982
   } else if (peek() == tHASH)
609✔
2983
      delay = p_delay_control();
12✔
2984

2985
   p_list_of_net_assignments(mod, delay, strength);
660✔
2986

2987
   consume(tSEMI);
660✔
2988
}
660✔
2989

2990
static vlog_net_kind_t p_net_type(void)
1,003✔
2991
{
2992
   // supply0 | supply1 | tri | triand | trior | trireg | tri0
2993
   //   | tri1 | uwire | wire | wand | wor
2994

2995
   BEGIN("net type");
2,006✔
2996

2997
   switch (one_of(tWIRE, tUWIRE, tSUPPLY0, tSUPPLY1, tTRI, tTRIAND,
1,003✔
2998
                  tTRIOR, tTRIREG, tTRI0, tTRI1, tWAND, tWOR)) {
2999
   case tSUPPLY0: return V_NET_SUPPLY0;
3000
   case tSUPPLY1: return V_NET_SUPPLY1;
4✔
3001
   case tTRI:     return V_NET_TRI;
1✔
3002
   case tTRIAND:  return V_NET_TRIAND;
2✔
3003
   case tTRIOR:   return V_NET_TRIOR;
2✔
3004
   case tTRIREG:  return V_NET_TRIREG;
1✔
3005
   case tTRI0:    return V_NET_TRI0;
4✔
3006
   case tTRI1:    return V_NET_TRI1;
2✔
3007
   case tUWIRE:   return V_NET_UWIRE;
1✔
3008
   case tWAND:    return V_NET_WAND;
1✔
3009
   case tWOR:     return V_NET_WOR;
1✔
3010
   case tWIRE:
976✔
3011
   default:       return V_NET_WIRE;
976✔
3012
   }
3013
}
3014

3015
static vlog_node_t p_net_decl_assignment(vlog_net_kind_t kind,
1,010✔
3016
                                         vlog_node_t datatype)
3017
{
3018
   // net_identifier { unpacked_dimension } [ = expression ]
3019

3020
   BEGIN("net declaration assignment");
2,020✔
3021

3022
   vlog_node_t v = vlog_new(V_NET_DECL);
1,010✔
3023
   vlog_set_subkind(v, kind);
1,010✔
3024
   vlog_set_type(v, datatype);
1,010✔
3025
   vlog_set_ident(v, p_identifier());
1,010✔
3026

3027
   while (peek() == tLSQUARE)
1,024✔
3028
      vlog_add_range(v, p_unpacked_dimension());
14✔
3029

3030
   if (optional(tEQ))
1,010✔
3031
      vlog_set_value(v, p_expression());
401✔
3032

3033
   vlog_set_loc(v, CURRENT_LOC);
1,010✔
3034
   vlog_symtab_put(symtab, v);
1,010✔
3035
   return v;
1,010✔
3036
}
3037

3038
static void p_list_of_net_decl_assignments(vlog_node_t mod,
917✔
3039
                                           vlog_net_kind_t kind,
3040
                                           vlog_node_t datatype)
3041
{
3042
   // net_decl_assignment { , net_decl_assignment }
3043

3044
   BEGIN("list of net declaration assignments");
1,834✔
3045

3046
   do {
1,010✔
3047
      vlog_node_t v = p_net_decl_assignment(kind, datatype);
1,010✔
3048
      vlog_add_decl(mod, v);
1,010✔
3049
   } while (optional(tCOMMA));
1,010✔
3050
}
917✔
3051

3052
static vlog_node_t p_drive_strength(void)
55✔
3053
{
3054
   //( strength0 , strength1 ) | ( strength1 , strength0 )
3055
   //| ( strength0 , highz1 )  | ( strength1 , highz0 )
3056
   //| ( highz0 , strength1 )  | ( highz1 , strength0 )
3057

3058
   BEGIN("drive strength");
110✔
3059

3060
   consume(tLPAREN);
55✔
3061

3062
   vlog_strength_t s0, s1;
55✔
3063
   switch (peek()) {
55✔
3064
   case tSUPPLY0:
5✔
3065
   case tSTRONG0:
3066
   case tPULL0:
3067
   case tWEAK0:
3068
      {
3069
         s0 = p_strength0();
5✔
3070
         consume(tCOMMA);
5✔
3071
         if (optional(tHIGHZ1))
5✔
3072
            s1 = V_STRENGTH_HIGHZ;
3073
         else
3074
            s1 = p_strength1();
4✔
3075
      }
3076
      break;
3077
   case tHIGHZ0:
1✔
3078
      {
3079
         s0 = V_STRENGTH_HIGHZ;
1✔
3080
         consume(tHIGHZ0);
1✔
3081
         consume(tCOMMA);
1✔
3082
         s1 = p_strength1();
1✔
3083
      }
3084
      break;
1✔
3085
   case tSUPPLY1:
48✔
3086
   case tSTRONG1:
3087
   case tPULL1:
3088
   case tWEAK1:
3089
      {
3090
         s1 = p_strength1();
48✔
3091
         consume(tCOMMA);
48✔
3092
         if (optional(tHIGHZ0))
48✔
3093
            s0 = V_STRENGTH_HIGHZ;
3094
         else
3095
            s0 = p_strength0();
48✔
3096
      }
3097
      break;
3098
   case tHIGHZ1:
1✔
3099
      {
3100
         s1 = V_STRENGTH_HIGHZ;
1✔
3101
         consume(tHIGHZ1);
1✔
3102
         consume(tCOMMA);
1✔
3103
         s0 = p_strength0();
1✔
3104
      }
3105
      break;
1✔
3106
   default:
×
3107
      should_not_reach_here();
3108
   }
3109

3110
   consume(tRPAREN);
55✔
3111

3112
   vlog_node_t v = vlog_new(V_STRENGTH);
55✔
3113
   vlog_set_subkind(v, MAKE_STRENGTH(s0, s1));
55✔
3114
   vlog_set_loc(v, CURRENT_LOC);
55✔
3115

3116
   return v;
55✔
3117
}
3118

3119
static vlog_strength_t p_charge_strength(void)
2✔
3120
{
3121
   // ( small ) | ( medium ) | ( large )
3122

3123
   BEGIN("drive charge");
4✔
3124

3125
   consume(tLPAREN);
2✔
3126

3127
   vlog_strength_t s;
2✔
3128
   switch (one_of(tSMALL, tMEDIUM, tLARGE)) {
2✔
3129
   default:
3130
   case tSMALL:  s = V_STRENGTH_SMALL;
3131
   case tMEDIUM: s = V_STRENGTH_MEDIUM;
2✔
3132
   case tLARGE:  s = V_STRENGTH_LARGE;
2✔
3133
   }
3134

3135
   consume(tRPAREN);
2✔
3136

3137
   return s;
2✔
3138
}
3139

3140
static void p_net_declaration(vlog_node_t mod)
918✔
3141
{
3142
   // net_type [ drive_strength | charge_strength ] [ vectored | scalared ]
3143
   //     data_type_or_implicit [ delay3 ] list_of_net_decl_assignments ;
3144
   //  | net_type_identifier [ delay_control ] list_of_net_decl_assignments ;
3145
   //  | interconnect implicit_data_type [ # delay_value ] net_identifier
3146
   //     { unpacked_dimension } [ , net_identifier { unpacked_dimension } ] ;
3147

3148
   BEGIN("net declaration");
1,836✔
3149

3150
   ident_t id;
918✔
3151
   vlog_node_t dt;
918✔
3152
   vlog_net_kind_t kind = V_NET_WIRE;
918✔
3153

3154
   switch (peek()) {
918✔
3155
   case tINTERCONNECT:
1✔
3156
      {
3157
         consume(tINTERCONNECT);
1✔
3158

3159
         dt = p_implicit_data_type();
1✔
3160

3161
         if (optional(tHASH))
1✔
3162
            p_delay_value();
1✔
3163

3164
         do {
1✔
3165
            id = p_identifier();
1✔
3166
            if (peek() == tLSQUARE)
1✔
3167
               p_unpacked_dimension();
1✔
3168
         } while (optional(tCOMMA));
1✔
3169
      }
3170
      break;
3171

3172
   case tID:
×
3173
      {
3174
         id = p_identifier();
×
3175
         dt = vlog_symtab_query(symtab, id);
×
3176
         if (dt == NULL)
×
3177
            should_not_reach_here();
3178
         // TODO check that the identifier is actually
3179
         // a user declared nettype
3180

3181
         if (peek() == tHASH)
×
3182
            p_delay_control();
×
3183

3184
         p_list_of_net_decl_assignments(mod, kind, dt);
×
3185
      }
3186
      break;
×
3187

3188
   default:
917✔
3189
      {
3190
         kind = p_net_type();
917✔
3191

3192
         if (peek() == tLPAREN) {
917✔
3193
            switch (peek_nth(2)) {
4✔
3194
            case tHIGHZ0:
2✔
3195
            case tHIGHZ1:
3196
            case tSUPPLY0:
3197
            case tSUPPLY1:
3198
            case tSTRONG0:
3199
            case tSTRONG1:
3200
            case tPULL0:
3201
            case tPULL1:
3202
            case tWEAK0:
3203
            case tWEAK1:
3204
               p_drive_strength();
2✔
3205
               break;
2✔
3206
            case tSMALL:
2✔
3207
            case tMEDIUM:
3208
            case tLARGE:
3209
               if (kind != V_NET_TRIREG)
2✔
3210
                  parse_error(&state.last_loc, "charge strength only allowed "
1✔
3211
                              "with the trireg keyword");
3212
               p_charge_strength();
2✔
3213
               break;
2✔
3214
            default:
×
3215
               one_of(tHIGHZ0, tHIGHZ1, tSUPPLY0, tSUPPLY1, tSTRONG0, tSTRONG1,
×
3216
                     tPULL0, tPULL1, tWEAK0, tWEAK1, tSMALL, tMEDIUM, tLARGE);
3217
               drop_tokens_until(&state, tSEMI);
×
3218
               return;
×
3219
            }
3220
         }
3221

3222
         bool need_packed = false;
917✔
3223
         if (optional(tVECTORED) || optional(tSCALARED))
917✔
3224
            need_packed = true;
3225

3226
         dt = p_data_type_or_implicit();
917✔
3227

3228
         if (need_packed) {
917✔
3229
            bool has_packed = false;
2✔
3230
            unsigned ranges = vlog_ranges(dt);
2✔
3231
            for (unsigned i = 0; i < ranges; i++) {
3✔
3232
               vlog_node_t r = vlog_range(dt, i);
1✔
3233
               if (vlog_subkind(r) == V_DIM_PACKED)
1✔
3234
                  has_packed |= true;
1✔
3235
            }
3236
            if (!has_packed)
2✔
3237
               parse_error(&state.last_loc, "vectored and scalared keywords "
1✔
3238
                           "are only allowed with at least a packed dimension");
3239
         }
3240

3241
         if (peek() == tHASH)
917✔
3242
            p_delay3();
5✔
3243

3244
         p_list_of_net_decl_assignments(mod, kind, dt);
917✔
3245
      }
3246
   }
3247

3248
   consume(tSEMI);
918✔
3249
}
3250

3251
static vlog_node_t p_unsized_dimension(void)
1✔
3252
{
3253
   // [ ]
3254

3255
   BEGIN("unsized dimension");
2✔
3256

3257
   consume(tLSQUARE);
1✔
3258
   consume(tRSQUARE);
1✔
3259

3260
   vlog_node_t v = vlog_new(V_DIMENSION);
1✔
3261
   vlog_set_subkind(v, V_DIM_UNSIZED);
1✔
3262
   vlog_set_loc(v, CURRENT_LOC);
1✔
3263

3264
   return v;
1✔
3265
}
3266

3267
static vlog_node_t p_variable_dimension(void)
99✔
3268
{
3269
   // unsized_dimension | unpacked_dimension | associative_dimension
3270
   //   | queue_dimension
3271

3272
   BEGIN("variable dimension");
198✔
3273

3274
   switch (peek_nth(2)) {
99✔
3275
   case tRSQUARE:
1✔
3276
      return p_unsized_dimension();
1✔
3277
   default:
98✔
3278
      return p_unpacked_dimension();
98✔
3279
   }
3280
}
3281

3282
static vlog_node_t p_variable_decl_assignment(vlog_node_t datatype)
4,351✔
3283
{
3284
   // variable_identifier { variable_dimension } [ = expression ]
3285
   //   | dynamic_array_variable_identifier unsized_dimension
3286
   //       { variable_dimension } [ = dynamic_array_new ]
3287
   //   | class_variable_identifier [ = class_new ]
3288

3289
   BEGIN("variable declaration assignment");
8,702✔
3290

3291
   vlog_node_t v = vlog_new(V_VAR_DECL);
4,351✔
3292
   vlog_set_ident(v, p_identifier());
4,351✔
3293
   vlog_set_type(v, datatype);
4,351✔
3294

3295
   while (peek() == tLSQUARE)
4,450✔
3296
      vlog_add_range(v, p_variable_dimension());
99✔
3297

3298
   if (optional(tEQ))
4,351✔
3299
      vlog_set_value(v, p_expression());
255✔
3300

3301
   vlog_set_loc(v, CURRENT_LOC);
4,351✔
3302
   vlog_symtab_put(symtab, v);
4,351✔
3303
   return v;
4,351✔
3304
}
3305

3306
static void p_list_of_variable_decl_assignments(vlog_node_t parent,
3,763✔
3307
                                                vlog_node_t datatype)
3308
{
3309
   // variable_decl_assignment { , variable_decl_assignment }
3310

3311
   BEGIN("list of variable declaration assignments");
7,526✔
3312

3313
   do {
4,351✔
3314
      vlog_add_decl(parent, p_variable_decl_assignment(datatype));
4,351✔
3315
   } while (optional(tCOMMA));
4,351✔
3316
}
3,763✔
3317

3318
static vlog_node_t p_type_declaration(void)
33✔
3319
{
3320
   // typedef data_type type_identifier { variable_dimension } ;
3321
   //   | typedef interface_instance_identifier constant_bit_select .
3322
   //       type_identifier type_identifier ;
3323
   //   | typedef [ enum | struct | union | class | interface class ]
3324
   //       type_identifier ;
3325

3326
   BEGIN("type declaration");
66✔
3327

3328
   consume(tTYPEDEF);
33✔
3329

3330
   vlog_node_t v = vlog_new(V_TYPE_DECL);
33✔
3331
   vlog_set_type(v, p_data_type());
33✔
3332
   vlog_set_ident(v, p_identifier());
33✔
3333

3334
   consume(tSEMI);
33✔
3335

3336
   vlog_set_loc(v, CURRENT_LOC);
33✔
3337
   vlog_symtab_put(symtab, v);
33✔
3338
   return v;
33✔
3339
}
3340

3341
static vlog_node_t p_package_import_item(void)
3✔
3342
{
3343
   // package_identifier :: identifier | package_identifier :: *
3344

3345
   BEGIN("package import item");
6✔
3346

3347
   vlog_node_t pack = p_package_identifier();
3✔
3348

3349
   vlog_node_t v = vlog_new(V_IMPORT_DECL);
3✔
3350
   vlog_set_ref(v, pack);
3✔
3351

3352
   consume(tSCOPE);
3✔
3353

3354
   if (peek() == tID)
3✔
3355
      vlog_set_ident(v, p_identifier());
1✔
3356
   else
3357
      one_of(tTIMES, tID);
2✔
3358

3359
   vlog_set_loc(v, CURRENT_LOC);
3✔
3360
   vlog_symtab_import(symtab, v);
3✔
3361
   return v;
3✔
3362
}
3363

3364
static void p_package_import_declaration(vlog_node_t parent)
3✔
3365
{
3366
   // import package_import_item { , package_import_item } ;
3367

3368
   BEGIN("package import declaration");
6✔
3369

3370
   consume(tIMPORT);
3✔
3371

3372
   do {
3✔
3373
      vlog_add_decl(parent, p_package_import_item());
3✔
3374
   } while (optional(tCOMMA));
3✔
3375

3376
   consume(tSEMI);
3✔
3377
}
3✔
3378

3379
static void p_data_declaration(vlog_node_t mod)
3,739✔
3380
{
3381
   // [ const ] [ var ] [ lifetime ] data_type_or_implicit
3382
   //     list_of_variable_decl_assignments ;
3383
   //  | type_declaration | package_import_declaration | net_type_declaration
3384

3385
   BEGIN("data declaration");
7,478✔
3386

3387
   switch (peek()) {
3,739✔
3388
   case tTYPEDEF:
33✔
3389
      vlog_add_decl(mod, p_type_declaration());
33✔
3390
      break;
33✔
3391
   case tIMPORT:
3✔
3392
      p_package_import_declaration(mod);
3✔
3393
      break;
3✔
3394
   default:
3,703✔
3395
      {
3396
         optional(tVAR);
3,703✔
3397

3398
         vlog_node_t dt = p_data_type_or_implicit();
3,703✔
3399
         p_list_of_variable_decl_assignments(mod, dt);
3,703✔
3400

3401
         consume(tSEMI);
3,703✔
3402
      }
3403
   }
3404
}
3,739✔
3405

3406
static v_port_kind_t p_port_direction(void)
134✔
3407
{
3408
   // input | output | inout | ref
3409

3410
   BEGIN("port direction");
268✔
3411

3412
   switch (one_of(tINPUT, tOUTPUT, tINOUT)) {
134✔
3413
   case tINPUT:  return V_PORT_INPUT;
3414
   case tOUTPUT: return V_PORT_OUTPUT;
4✔
3415
   case tINOUT:  return V_PORT_INOUT;
1✔
3416
   default:      return V_PORT_INPUT;
3417
   }
3418
}
3419

3420
static v_port_kind_t p_tf_port_direction(void)
134✔
3421
{
3422
   // port_direction | const ref
3423

3424
   BEGIN("task or function port direction");
268✔
3425

3426
   return p_port_direction();
134✔
3427
}
3428

3429
static vlog_node_t p_tf_port_item(void)
87✔
3430
{
3431
   // { attribute_instance } [ tf_port_direction ] [ var ]
3432
   //    data_type_or_implicit [ port_identifier { variable_dimension }
3433
   //    [ = expression ] ]
3434

3435
   BEGIN("task or function port item");
174✔
3436

3437
   vlog_node_t v = vlog_new(V_TF_PORT_DECL);
87✔
3438

3439
   skip_over_attributes();
87✔
3440

3441
   if (scan(tINPUT, tOUTPUT, tINOUT))
87✔
3442
      vlog_set_subkind(v, p_tf_port_direction());
64✔
3443
   else
3444
      vlog_set_subkind(v, V_PORT_INPUT);
23✔
3445

3446
   vlog_set_type(v, p_data_type_or_implicit());
87✔
3447

3448
   if (peek() == tID) {
87✔
3449
      vlog_set_ident(v, p_identifier());
86✔
3450

3451
      if (optional(tEQ))
86✔
3452
         vlog_set_value(v, p_expression());
8✔
3453
   }
3454

3455
   vlog_set_loc(v, CURRENT_LOC);
87✔
3456
   return v;
87✔
3457
}
3458

3459
static void p_tf_port_list(vlog_node_t tf)
69✔
3460
{
3461
   // tf_port_item { , tf_port_item }
3462

3463
   BEGIN("task or function port list");
138✔
3464

3465
   do {
85✔
3466
      vlog_node_t v = p_tf_port_item();
85✔
3467
      vlog_add_port(tf, v);
85✔
3468

3469
      if (vlog_has_ident(v))  // Ignore unnamed ports
85✔
3470
         vlog_symtab_put(symtab, v);
84✔
3471
   } while (optional(tCOMMA));
85✔
3472
}
69✔
3473

3474
static void p_list_of_tf_variable_identifiers(vlog_node_t tf,
70✔
3475
                                              v_port_kind_t kind,
3476
                                              vlog_node_t dt)
3477
{
3478
   // port_identifier { variable_dimension } [ = expression ]
3479
   //    { , port_identifier { variable_dimension } [ = expression ] }
3480

3481
   BEGIN("list of task or function variable identifiers");
140✔
3482

3483
   do {
80✔
3484
      vlog_node_t v = vlog_new(V_TF_PORT_DECL);
80✔
3485
      vlog_set_subkind(v, kind);
80✔
3486
      vlog_set_type(v, dt);
80✔
3487
      vlog_set_ident(v, p_identifier());
80✔
3488
      vlog_set_loc(v, &state.last_loc);
80✔
3489

3490
      if (optional(tEQ))
80✔
3491
         vlog_set_value(v, p_expression());
1✔
3492

3493
      vlog_add_port(tf, v);
80✔
3494
      vlog_symtab_put(symtab, v);
80✔
3495
   } while (optional(tCOMMA));
80✔
3496
}
70✔
3497

3498
static void p_tf_port_declaration(vlog_node_t tf)
70✔
3499
{
3500
   // { attribute_instance } tf_port_direction [ var ] data_type_or_implicit
3501
   //    list_of_tf_variable_identifiers ;
3502

3503
   BEGIN("task or function port declaration");
140✔
3504

3505
   v_port_kind_t kind = p_tf_port_direction();
70✔
3506

3507
   optional(tVAR);
70✔
3508

3509
   vlog_node_t dt = p_data_type_or_implicit();
70✔
3510

3511
   p_list_of_tf_variable_identifiers(tf, kind, dt);
70✔
3512

3513
   consume(tSEMI);
70✔
3514
}
70✔
3515

3516
static void p_tf_item_declaration(vlog_node_t tf)
95✔
3517
{
3518
   // block_item_declaration | tf_port_declaration
3519

3520
   BEGIN("task or function item declaration");
190✔
3521

3522
   switch (peek()) {
95✔
3523
   case tINPUT:
70✔
3524
   case tOUTPUT:
3525
   case tCONST:
3526
      p_tf_port_declaration(tf);
70✔
3527
      break;
70✔
3528
   default:
25✔
3529
      p_block_item_declaration(tf);
25✔
3530
      break;
25✔
3531
   }
3532
}
95✔
3533

3534
static void p_task_body_declaration(vlog_node_t task)
37✔
3535
{
3536
   // [ interface_identifier . | class_scope ] task_identifier ;
3537
   //    { tf_item_declaration } { statement_or_null }
3538
   //    endtask [ : task_identifier ]
3539
   // | [ interface_identifier . | class_scope ] task_identifier
3540
   //    ( [ tf_port_list ] ) ; { block_item_declaration }
3541
   //    { statement_or_null } endtask [ : task_identifier ]
3542

3543
   BEGIN("task body declaration");
74✔
3544

3545
   ident_t id = p_identifier();
37✔
3546
   vlog_set_ident(task, id);
37✔
3547
   vlog_set_loc(task, &state.last_loc);
37✔
3548

3549
   vlog_symtab_put(symtab, task);
37✔
3550

3551
   vlog_symtab_push(symtab, task);
37✔
3552

3553
   if (optional(tLPAREN)) {
37✔
3554
      if (peek() != tRPAREN)
7✔
3555
         p_tf_port_list(task);
7✔
3556
      consume(tRPAREN);
7✔
3557

3558
      consume(tSEMI);
7✔
3559

3560
      skip_over_attributes();
7✔
3561

3562
      while (scan_block_item_declaration()) {
7✔
3563
         p_block_item_declaration(task);
×
3564
         skip_over_attributes();
×
3565
      }
3566
   }
3567
   else {
3568
      consume(tSEMI);
30✔
3569

3570
      skip_over_attributes();
30✔
3571

3572
      while (scan_tf_item_declaration()) {
72✔
3573
         p_tf_item_declaration(task);
42✔
3574
         skip_over_attributes();
42✔
3575
      }
3576
   }
3577

3578
   while (not_at_token(tENDTASK)) {
77✔
3579
      vlog_node_t s = p_statement_or_null();
40✔
3580
      if (s != NULL)
40✔
3581
         vlog_add_stmt(task, s);
40✔
3582
   }
3583

3584
   consume(tENDTASK);
37✔
3585

3586
   if (optional(tCOLON)) {
37✔
3587
      ident_t name = p_identifier();
2✔
3588
      if (id != name)
2✔
3589
         error_at(&state.last_loc, "'%s' does not match task name '%s'",
1✔
3590
                  istr(name), istr(id));
3591
   }
3592

3593
   vlog_symtab_pop(symtab);
37✔
3594
}
37✔
3595

3596
static void p_lifetime(void)
1✔
3597
{
3598
   // static | automatic
3599

3600
   BEGIN("lifetime");
2✔
3601

3602
   one_of(tAUTOMATIC);
1✔
3603
}
1✔
3604

3605
static vlog_node_t p_task_declaration(void)
37✔
3606
{
3607
   // task [ dynamic_override_specifiers ] [ lifetime ] task_body_declaration
3608

3609
   BEGIN("task declaration");
74✔
3610

3611
   vlog_node_t v = vlog_new(V_TASK_DECL);
37✔
3612

3613
   consume(tTASK);
37✔
3614

3615
   if (scan(tAUTOMATIC))
37✔
3616
      p_lifetime();
×
3617

3618
   p_task_body_declaration(v);
37✔
3619

3620
   vlog_set_loc(v, CURRENT_LOC);
37✔
3621
   return v;
37✔
3622
}
3623

3624
static vlog_node_t p_function_data_type_or_implicit(void)
106✔
3625
{
3626
   // data_type_or_void | implicit_data_type
3627

3628
   BEGIN("function data type or implicit");
212✔
3629

3630
   switch (peek()) {
106✔
3631
   case tREG:
21✔
3632
   case tSTRUCT:
3633
   case tUNION:
3634
   case tENUM:
3635
   case tSVINT:
3636
   case tINTEGER:
3637
   case tSVREAL:
3638
   case tSHORTREAL:
3639
   case tREALTIME:
3640
   case tLOGIC:
3641
   case tBIT:
3642
   case tSHORTINT:
3643
   case tSTRINGK:
3644
   case tEVENT:
3645
   case tVOID:
3646
      return p_data_type_or_void();
21✔
3647
   case tID:
11✔
3648
      {
3649
         vlog_node_t dt = peek_reference();
11✔
3650
         if (dt != NULL && is_data_type(dt)) {
11✔
3651
            consume(tID);
1✔
3652
            return dt;
1✔
3653
         }
3654
         else
3655
            return p_implicit_data_type();
10✔
3656
      }
3657
   default:
74✔
3658
      return p_implicit_data_type();
74✔
3659
   }
3660
}
3661

3662
static void p_function_body_declaration(vlog_node_t func)
106✔
3663
{
3664
   // function_data_type_or_implicit [ interface_identifier . | class_scope ]
3665
   //    function_identifier ; { tf_item_declaration }
3666
   //    { function_statement_or_null } endfunction [ : function_identifier ]
3667
   // | function_data_type_or_implicit [ interface_identifier . | class_scope ]
3668
   //    function_identifier ( [ tf_port_list ] ) ; { block_item_declaration }
3669
   //    { function_statement_or_null } endfunction [ : function_identifier ]
3670

3671
   BEGIN("function body declaration");
212✔
3672

3673
   vlog_set_type(func, p_function_data_type_or_implicit());
106✔
3674

3675
   ident_t id = p_identifier();
106✔
3676
   vlog_set_ident(func, id);
106✔
3677
   vlog_set_loc(func, &state.last_loc);
106✔
3678

3679
   vlog_symtab_put(symtab, func);
106✔
3680

3681
   vlog_symtab_push(symtab, func);
106✔
3682

3683
   if (optional(tLPAREN)) {
106✔
3684
      if (peek() != tRPAREN)
65✔
3685
         p_tf_port_list(func);
62✔
3686
      consume(tRPAREN);
65✔
3687

3688
      consume(tSEMI);
65✔
3689

3690
      skip_over_attributes();
65✔
3691

3692
      while (scan_block_item_declaration()) {
105✔
3693
         p_block_item_declaration(func);
40✔
3694
         skip_over_attributes();
40✔
3695
      }
3696
   }
3697
   else {
3698
      consume(tSEMI);
41✔
3699

3700
      skip_over_attributes();
41✔
3701

3702
      while (scan_tf_item_declaration()) {
94✔
3703
         p_tf_item_declaration(func);
53✔
3704
         skip_over_attributes();
53✔
3705
      }
3706
   }
3707

3708
   while (not_at_token(tENDFUNCTION)) {
216✔
3709
      vlog_node_t s = p_statement_or_null();
110✔
3710
      if (s != NULL)
110✔
3711
         vlog_add_stmt(func, s);
110✔
3712
   }
3713

3714
   consume(tENDFUNCTION);
106✔
3715

3716
   if (optional(tCOLON)) {
106✔
3717
      ident_t name = p_identifier();
3✔
3718
      if (id != name)
3✔
3719
         error_at(&state.last_loc, "'%s' does not match function name '%s'",
1✔
3720
                  istr(name), istr(id));
3721
   }
3722

3723
   vlog_symtab_pop(symtab);
106✔
3724
}
106✔
3725

3726
static vlog_node_t p_function_declaration(void)
106✔
3727
{
3728
   // function [ lifetime ] function_body_declaration
3729

3730
   BEGIN("function declaration");
212✔
3731

3732
   vlog_node_t v = vlog_new(V_FUNC_DECL);
106✔
3733

3734
   consume(tFUNCTION);
106✔
3735

3736
   if (scan(tAUTOMATIC))
106✔
3737
      p_lifetime();
1✔
3738

3739
   p_function_body_declaration(v);
106✔
3740

3741
   vlog_set_loc(v, CURRENT_LOC);
106✔
3742
   return v;
106✔
3743
}
3744

3745
static vlog_node_t p_constant_param_expression(void)
399✔
3746
{
3747
   // mintypmax_expression | data_type | $
3748

3749
   BEGIN("constant parameter expression");
798✔
3750

3751
   return p_mintypmax_expression();
399✔
3752
}
3753

3754
static vlog_node_t p_param_assignment(vlog_node_t datatype, vlog_kind_t kind)
415✔
3755
{
3756
   // parameter_identifier { unpacked_dimension }
3757
   //   [ = constant_param_expression ]
3758

3759
   BEGIN("parameter assignment");
830✔
3760

3761
   vlog_node_t v = vlog_new(kind);
415✔
3762
   vlog_set_ident(v, p_identifier());
415✔
3763
   vlog_set_type(v, datatype);
415✔
3764

3765
   if (optional(tEQ))
415✔
3766
      vlog_set_value(v, p_constant_param_expression());
399✔
3767

3768
   vlog_set_loc(v, CURRENT_LOC);
415✔
3769
   return v;
415✔
3770
}
3771

3772
static void p_list_of_param_assignments(vlog_node_t parent,
353✔
3773
                                        vlog_node_t datatype,
3774
                                        vlog_kind_t kind)
3775
{
3776
   // param_assignment { , param_assignment }
3777

3778
   BEGIN("list of parameter assignments");
706✔
3779

3780
   do {
415✔
3781
      vlog_node_t v = p_param_assignment(datatype, kind);
415✔
3782
      vlog_symtab_put(symtab, v);
415✔
3783
      vlog_add_decl(parent, v);
415✔
3784
   } while (peek_nth(2) == tID && optional(tCOMMA));
415✔
3785
}
353✔
3786

3787
static void p_parameter_declaration(vlog_node_t mod)
225✔
3788
{
3789
   // parameter data_type_or_implicit list_of_param_assignments
3790

3791
   BEGIN("parameter declaration");
450✔
3792

3793
   consume(tPARAMETER);
225✔
3794

3795
   vlog_node_t dt = p_data_type_or_implicit();
225✔
3796
   p_list_of_param_assignments(mod, dt, param_kind);
225✔
3797
}
225✔
3798

3799
static void p_local_parameter_declaration(vlog_node_t mod)
126✔
3800
{
3801
   // localparam data_type_or_implicit list_of_param_assignments
3802

3803
   BEGIN("local parameter declaration");
252✔
3804

3805
   consume(tLOCALPARAM);
126✔
3806

3807
   vlog_node_t dt = p_data_type_or_implicit();
126✔
3808
   p_list_of_param_assignments(mod, dt, V_LOCALPARAM);
126✔
3809
}
126✔
3810

3811
static void p_class_property(vlog_node_t parent)
15✔
3812
{
3813
   // { property_qualifier } data_declaration
3814
   //   | const { class_item_qualifier } data_type const_identifier
3815
   //       [ = constant_expression ] ;
3816

3817
   BEGIN("class property");
30✔
3818

3819
   p_data_declaration(parent);
15✔
3820
}
15✔
3821

3822
static void p_class_constructor_arg(vlog_node_t parent)
2✔
3823
{
3824
   // tf_port_item | default
3825

3826
   BEGIN("class constructor argument");
4✔
3827

3828
   vlog_node_t v = p_tf_port_item();
2✔
3829
   vlog_symtab_put(symtab, v);
2✔
3830
   vlog_add_param(parent, v);
2✔
3831
}
2✔
3832

3833
static void p_class_constructor_arg_list(vlog_node_t parent)
2✔
3834
{
3835
   // class_constructor_arg { , class_constructor_arg }
3836

3837
   BEGIN("class constructor argument list");
4✔
3838

3839
   do {
2✔
3840
      p_class_constructor_arg(parent);
2✔
3841
   } while (optional(tCOMMA));
2✔
3842
}
2✔
3843

3844
static vlog_node_t p_class_constructor_declaration(void)
2✔
3845
{
3846
   // function [ class_scope ] new [ ( [ class_constructor_arg_list ] ) ] ;
3847
   //   { block_item_declaration }
3848
   //   [ super . new [ ( [ list_of_arguments | default ] ) ] ; ]
3849
   //   { function_statement_or_null }
3850
   //   endfunction [ : new]
3851

3852
   BEGIN("class constructor declaration");
4✔
3853

3854
   consume(tFUNCTION);
2✔
3855
   consume(tNEW);
2✔
3856

3857
   vlog_node_t v = vlog_new(V_CONSTRUCTOR);
2✔
3858
   vlog_set_ident(v, ident_new("new"));
2✔
3859

3860
   vlog_symtab_push(symtab, v);
2✔
3861

3862
   if (optional(tLPAREN)) {
2✔
3863
      if (not_at_token(tRPAREN))
2✔
3864
         p_class_constructor_arg_list(v);
2✔
3865

3866
      consume(tRPAREN);
2✔
3867
   }
3868

3869
   consume(tSEMI);
2✔
3870

3871
   skip_over_attributes();
2✔
3872

3873
   while (scan_block_item_declaration()) {
2✔
3874
      p_block_item_declaration(v);
×
3875
      skip_over_attributes();
×
3876
   }
3877

3878
   if (optional(tSUPER)) {
2✔
3879
      consume(tDOT);
1✔
3880
      consume(tNEW);
1✔
3881

3882
      vlog_node_t call = vlog_new(V_SUPER_CALL);
1✔
3883
      vlog_set_loc(call, &state.last_loc);
1✔
3884

3885
      if (optional(tLPAREN)) {
1✔
3886
         p_list_of_arguments(call);
1✔
3887
         consume(tRPAREN);
1✔
3888
      }
3889

3890
      vlog_add_stmt(v, call);
1✔
3891
   }
3892

3893
   while (not_at_token(tENDFUNCTION)) {
5✔
3894
      vlog_node_t s = p_statement_or_null();
3✔
3895
      if (s != NULL)
3✔
3896
         vlog_add_stmt(v, s);
2✔
3897
   }
3898

3899
   consume(tENDFUNCTION);
2✔
3900

3901
   if (optional(tCOLON))
2✔
3902
      consume(tNEW);
2✔
3903

3904
   vlog_symtab_pop(symtab);
2✔
3905

3906
   vlog_set_loc(v, CURRENT_LOC);
2✔
3907
   return v;
2✔
3908
}
3909

3910
static void p_method_qualifier(void)
1✔
3911
{
3912
   // [ pure ] virtual | class_item_qualifier
3913

3914
   BEGIN("method qualifier");
2✔
3915

3916
   consume(tVIRTUAL);
1✔
3917
}
1✔
3918

3919
static void p_class_method(vlog_node_t class)
3✔
3920
{
3921
   // { method_qualifier } task_declaration
3922
   //    | { method_qualifier } function_declaration
3923
   //    | pure virtual { class_item_qualifier } method_prototype ;
3924
   //    | extern { method_qualifier } method_prototype ;
3925
   //    | { method_qualifier } class_constructor_declaration
3926
   //    | extern { method_qualifier } class_constructor_prototype
3927

3928
   BEGIN("class method");
6✔
3929

3930
   if (scan(tVIRTUAL))
3✔
3931
      p_method_qualifier();
1✔
3932

3933
   switch (peek()) {
3✔
3934
   case tFUNCTION:
3✔
3935
      if (peek_nth(2) == tNEW)
3✔
3936
         vlog_add_decl(class, p_class_constructor_declaration());
2✔
3937
      else
3938
         vlog_add_decl(class, p_function_declaration());
1✔
3939
      break;
3940
   default:
×
3941
      one_of(tFUNCTION);
×
3942
      break;
×
3943
   }
3944
}
3✔
3945

3946
static void p_class_item(vlog_node_t parent)
19✔
3947
{
3948
   // { attribute_instance } class_property
3949
   //   | { attribute_instance } class_method
3950
   //   | { attribute_instance } class_constraint
3951
   //   | { attribute_instance } class_declaration
3952
   //   | { attribute_instance } covergroup_declaration
3953
   //   | local_parameter_declaration ;
3954
   //   | parameter_declaration | ;
3955

3956
   BEGIN("class item");
38✔
3957

3958
   optional_attributes();
19✔
3959

3960
   switch (peek()) {
19✔
3961
   case tSEMI:
1✔
3962
      consume(tSEMI);
1✔
3963
      break;
1✔
3964
   case tFUNCTION:
3✔
3965
   case tTASK:
3966
   case tVIRTUAL:
3967
      p_class_method(parent);
3✔
3968
      break;
3✔
3969
   default:
15✔
3970
      p_class_property(parent);
15✔
3971
      break;
15✔
3972
   }
3973
}
19✔
3974

3975
static void p_class_type(void)
2✔
3976
{
3977
   // ps_class_identifier [ parameter_value_assignment ]
3978
   //   { :: class_identifier [ parameter_value_assignment ] }
3979

3980
   BEGIN("class type");
4✔
3981

3982
   (void)p_identifier();
2✔
3983
}
2✔
3984

3985
static vlog_node_t p_class_declaration(void)
12✔
3986
{
3987
   // [ virtual ] class [ lifetime ] class_identifier [ parameter_port_list ]
3988
   //   [ extends class_type [ ( list_of_arguments ) ] ]
3989
   //   [ implements interface_class_type { , interface_class_type } ] ;
3990
   //   { class_item } endclass [ : class_identifier ]
3991

3992
   BEGIN("class declaration");
24✔
3993

3994
   vlog_node_t v = vlog_new(V_CLASS_DECL);
12✔
3995

3996
   optional(tVIRTUAL);
12✔
3997

3998
   consume(tCLASS);
12✔
3999

4000
   ident_t name = p_identifier();
12✔
4001
   vlog_set_ident(v, name);
12✔
4002

4003
   if (optional(tEXTENDS))
12✔
4004
      p_class_type();
2✔
4005

4006
   consume(tSEMI);
12✔
4007

4008
   vlog_symtab_push(symtab, v);
12✔
4009

4010
   while (not_at_token(tENDCLASS))
31✔
4011
      p_class_item(v);
19✔
4012

4013
   vlog_symtab_pop(symtab);
12✔
4014

4015
   consume(tENDCLASS);
12✔
4016

4017
   if (optional(tCOLON)) {
12✔
4018
      ident_t end_name = p_identifier();
10✔
4019
      if (name != end_name)
10✔
4020
         error_at(&state.last_loc, "'%s' does not match class name '%s'",
1✔
4021
                  istr(end_name), istr(name));
4022
   }
4023

4024
   vlog_set_loc(v, CURRENT_LOC);
12✔
4025
   vlog_symtab_put(symtab, v);
12✔
4026
   return v;
12✔
4027
}
4028

4029
static void p_block_item_declaration(vlog_node_t parent)
83✔
4030
{
4031
   // { attribute_instance } data_declaration
4032
   //   | { attribute_instance } local_parameter_declaration ;
4033
   //   | { attribute_instance } parameter_declaration ;
4034
   //   | { attribute_instance } overload_declaration
4035
   //   | { attribute_instance } let_declaration
4036

4037
   BEGIN("block item declaration");
166✔
4038

4039
   optional_attributes();
83✔
4040

4041
   switch (peek()) {
83✔
4042
   case tREG:
83✔
4043
   case tSTRUCT:
4044
   case tUNION:
4045
   case tTYPEDEF:
4046
   case tENUM:
4047
   case tSVINT:
4048
   case tINTEGER:
4049
   case tSVREAL:
4050
   case tSHORTREAL:
4051
   case tREALTIME:
4052
   case tBIT:
4053
   case tLOGIC:
4054
   case tSHORTINT:
4055
   case tTIME:
4056
      p_data_declaration(parent);
83✔
4057
      break;
83✔
4058
   default:
×
4059
      should_not_reach_here();
4060
   }
4061
}
83✔
4062

4063
static void p_package_or_generate_item_declaration(vlog_node_t parent)
5,012✔
4064
{
4065
   // net_declaration | data_declaration | task_declaration
4066
   //   | function_declaration | checker_declaration | dpi_import_export
4067
   //   | extern_constraint_declaration | class_declaration
4068
   //   | class_constructor_declaration | local_parameter_declaration ;
4069
   //   | parameter_declaration ; | covergroup_declaration
4070
   //   | overload_declaration | assertion_item_declaration | ;
4071

4072
   BEGIN("package or generate item declaration");
10,024✔
4073

4074
   switch (peek()) {
5,012✔
4075
   case tWIRE:
918✔
4076
   case tUWIRE:
4077
   case tSUPPLY0:
4078
   case tSUPPLY1:
4079
   case tTRI:
4080
   case tTRI0:
4081
   case tTRI1:
4082
   case tTRIAND:
4083
   case tTRIOR:
4084
   case tTRIREG:
4085
   case tWAND:
4086
   case tWOR:
4087
   case tINTERCONNECT:
4088
      p_net_declaration(parent);
918✔
4089
      break;
918✔
4090
   case tREG:
3,641✔
4091
   case tSTRUCT:
4092
   case tUNION:
4093
   case tTYPEDEF:
4094
   case tENUM:
4095
   case tSVINT:
4096
   case tINTEGER:
4097
   case tSVREAL:
4098
   case tSHORTREAL:
4099
   case tREALTIME:
4100
   case tTIME:
4101
   case tEVENT:
4102
   case tID:
4103
   case tVAR:
4104
   case tLOGIC:
4105
   case tBIT:
4106
   case tSHORTINT:
4107
   case tLONGINT:
4108
   case tBYTE:
4109
   case tSTRINGK:
4110
   case tIMPORT:
4111
      p_data_declaration(parent);
3,641✔
4112
      break;
3,641✔
4113
   case tTASK:
37✔
4114
      vlog_add_decl(parent, p_task_declaration());
37✔
4115
      break;
37✔
4116
   case tFUNCTION:
105✔
4117
      vlog_add_decl(parent, p_function_declaration());
105✔
4118
      break;
105✔
4119
   case tLOCALPARAM:
121✔
4120
      p_local_parameter_declaration(parent);
121✔
4121
      consume(tSEMI);
121✔
4122
      break;
121✔
4123
   case tPARAMETER:
178✔
4124
      p_parameter_declaration(parent);
178✔
4125
      consume(tSEMI);
178✔
4126
      break;
178✔
4127
   case tCLASS:
12✔
4128
   case tVIRTUAL:
4129
      vlog_add_decl(parent, p_class_declaration());
12✔
4130
      break;
12✔
4131
   default:
×
4132
      one_of(tWIRE, tUWIRE, tSUPPLY0, tSUPPLY1, tTRI, tTRI0, tTRI1, tTRIAND,
×
4133
             tTRIOR, tTRIREG, tWAND, tWOR, tINTERCONNECT, tREG, tSTRUCT, tUNION,
4134
             tTYPEDEF, tENUM, tSVINT, tINTEGER, tSVREAL, tSHORTREAL, tREALTIME,
4135
             tTIME, tEVENT, tID, tVAR, tLOGIC, tBIT, tSHORTINT, tLONGINT, tBYTE,
4136
             tSTRINGK, tIMPORT, tTASK, tFUNCTION, tLOCALPARAM, tPARAMETER,
4137
             tCLASS, tVIRTUAL);
4138
      drop_tokens_until(&state, tSEMI);
×
4139
      break;
×
4140
   }
4141
}
5,012✔
4142

4143
static void p_list_of_genvar_identifiers(vlog_node_t mod, vlog_node_t dt)
14✔
4144
{
4145
   // genvar_identifier { , genvar_identifier }
4146

4147
   BEGIN("list of genvar identifiers");
28✔
4148

4149
   do {
14✔
4150
      vlog_node_t v = vlog_new(V_GENVAR_DECL);
14✔
4151
      vlog_set_ident(v, p_identifier());
14✔
4152
      vlog_set_type(v, dt);
14✔
4153
      vlog_set_loc(v, CURRENT_LOC);
14✔
4154

4155
      vlog_add_decl(mod, v);
14✔
4156

4157
      vlog_symtab_put(symtab, v);
14✔
4158
   } while (optional(tCOMMA));
14✔
4159
}
14✔
4160

4161
static void p_genvar_declaration(vlog_node_t mod)
14✔
4162
{
4163
   // genvar list_of_genvar_identifiers ;
4164

4165
   BEGIN("genvar declaration");
28✔
4166

4167
   consume(tGENVAR);
14✔
4168

4169
   vlog_node_t dt = make_integer_atom_type(DT_INTEGER);
14✔
4170
   vlog_set_flags(dt, VLOG_F_SIGNED);
14✔
4171

4172
   p_list_of_genvar_identifiers(mod, dt);
14✔
4173

4174
   consume(tSEMI);
14✔
4175
}
14✔
4176

4177
static void p_module_or_generate_item_declaration(vlog_node_t mod)
5,002✔
4178
{
4179
   // package_or_generate_item_declaration | genvar_declaration
4180
   //   | clocking_declaration | default clocking clocking_identifier ;
4181
   //   | default disable iff expression_or_dist ;
4182

4183
   BEGIN("module or generate item declaration");
10,004✔
4184

4185
   switch (peek()) {
5,002✔
4186
   case tGENVAR:
14✔
4187
      p_genvar_declaration(mod);
14✔
4188
      break;
14✔
4189
   default:
4,988✔
4190
      p_package_or_generate_item_declaration(mod);
4,988✔
4191
      break;
4,988✔
4192
   }
4193
}
5,002✔
4194

4195
static void p_generate_item(vlog_node_t parent)
134✔
4196
{
4197
   // module_or_generate_item | interface_or_generate_item
4198
   //   | checker_or_generate_item
4199

4200
   BEGIN("generate item");
268✔
4201

4202
   p_module_or_generate_item(parent);
134✔
4203
}
134✔
4204

4205
static vlog_node_t p_generate_block(void)
73✔
4206
{
4207
   // generate_item
4208
   //   | [ generate_block_identifier : ] begin [ : generate_block_identifier ]
4209
   //         { generate_item } end [ : generate_block_identifier ]
4210

4211
   BEGIN("generate block");
146✔
4212

4213
   vlog_node_t b = vlog_new(V_BLOCK);
73✔
4214

4215
   if (scan(tID, tBEGIN)) {
73✔
4216
      if (peek() == tID) {
56✔
4217
         vlog_set_ident(b, p_identifier());
1✔
4218
         consume(tCOLON);
1✔
4219
      }
4220

4221
      consume(tBEGIN);
56✔
4222

4223
      if (optional(tCOLON)) {
56✔
4224
         ident_t name = p_identifier();
28✔
4225
         if (vlog_has_ident(b))    // 1800-2023 section 9.3.5
28✔
4226
            parse_error(&state.last_loc, "cannot specify both a label and a "
1✔
4227
                        "name for the same block");
4228
         else
4229
            vlog_set_ident(b, name);
27✔
4230
      }
4231

4232
      vlog_symtab_push(symtab, b);
56✔
4233

4234
      while (not_at_token(tEND))
154✔
4235
         p_generate_item(b);
98✔
4236

4237
      vlog_symtab_pop(symtab);
56✔
4238

4239
      consume(tEND);
56✔
4240

4241
      if (optional(tCOLON)) {
56✔
4242
         ident_t name = p_identifier();
2✔
4243
         if (!vlog_has_ident(b))
2✔
4244
            parse_error(&state.last_loc, "block does not have a label");
1✔
4245
         else if (name != vlog_ident(b))
1✔
4246
            parse_error(&state.last_loc, "'%s' does not match label '%s'",
1✔
4247
                        istr(name), istr(vlog_ident(b)));
4248
      }
4249
   }
4250
   else
4251
      p_generate_item(b);
17✔
4252

4253
   if (!vlog_has_ident(b))
73✔
4254
      vlog_set_ident(b, default_label("genblk"));
45✔
4255

4256
   vlog_set_loc(b, CURRENT_LOC);
73✔
4257
   return b;
73✔
4258
}
4259

4260
static vlog_node_t p_if_generate_construct(void)
34✔
4261
{
4262
   // if ( constant_expression ) generate_block
4263
   //   { else if ( constant_expression ) generate_block }
4264
   //   [ else generate_block ]
4265

4266
   BEGIN("if generate construct");
68✔
4267

4268
   vlog_node_t v = vlog_new(V_IF_GENERATE);
34✔
4269

4270
   consume(tIF);
34✔
4271
   consume(tLPAREN);
34✔
4272

4273
   vlog_node_t c0 = vlog_new(V_COND);
34✔
4274
   vlog_set_value(c0, p_constant_expression());
34✔
4275

4276
   consume(tRPAREN);
34✔
4277

4278
   vlog_set_loc(c0, CURRENT_LOC);
34✔
4279
   vlog_add_stmt(c0, p_generate_block());
34✔
4280

4281
   vlog_add_cond(v, c0);
34✔
4282

4283
   while (optional(tELSE)) {
44✔
4284
      if (peek() == tIF) {
21✔
4285
         // else if ( constant_expression ) generate_block
4286
         consume(tIF);
10✔
4287
         consume(tLPAREN);
10✔
4288

4289
         vlog_node_t cn = vlog_new(V_COND);
10✔
4290
         vlog_set_value(cn, p_constant_expression());
10✔
4291

4292
         consume(tRPAREN);
10✔
4293

4294
         vlog_set_loc(cn, CURRENT_LOC);
10✔
4295
         vlog_add_stmt(cn, p_generate_block());
10✔
4296

4297
         vlog_add_cond(v, cn);
10✔
4298
      }
4299
      else {
4300
         // else generate_block (no condition = default branch)
4301
         vlog_node_t ce = vlog_new(V_COND);
11✔
4302
         vlog_set_loc(ce, &state.last_loc);
11✔
4303
         vlog_add_stmt(ce, p_generate_block());
11✔
4304

4305
         vlog_add_cond(v, ce);
11✔
4306
         break;
11✔
4307
      }
4308
   }
4309

4310
   vlog_set_loc(v, CURRENT_LOC);
34✔
4311
   return v;
34✔
4312
}
4313

4314
static vlog_node_t p_case_generate_construct(void)
1✔
4315
{
4316
   // case ( constant_expression )
4317
   //   case_generate_item { case_generate_item } endcase
4318
   //
4319
   // Lowered to V_IF_GENERATE with equality comparisons so the existing
4320
   // simplifier and elaborator handle it without a new node kind.
4321

4322
   BEGIN("case generate construct");
2✔
4323

4324
   consume(tCASE);
1✔
4325
   consume(tLPAREN);
1✔
4326

4327
   vlog_node_t selector = p_constant_expression();
1✔
4328

4329
   consume(tRPAREN);
1✔
4330

4331
   vlog_node_t v = vlog_new(V_IF_GENERATE);
1✔
4332

4333
   while (not_at_token(tENDCASE)) {
4✔
4334
      vlog_node_t cn = vlog_new(V_COND);
3✔
4335

4336
      if (optional(tDEFAULT)) {
3✔
4337
         // default branch: no condition (like else)
4338
         optional(tCOLON);
×
4339
      }
4340
      else {
4341
         // case_generate_item: constant_expression { , constant_expression }
4342
         //   : generate_block
4343
         // Build equality comparison: selector == label
4344
         // For multiple labels, OR them: (sel == l1) || (sel == l2)
4345
         vlog_node_t cond = NULL;
4346
         do {
3✔
4347
            vlog_node_t eq = vlog_new(V_BINARY);
3✔
4348
            vlog_set_subkind(eq, V_BINARY_LOG_EQ);
3✔
4349
            vlog_set_left(eq, selector);
3✔
4350
            vlog_set_right(eq, p_constant_expression());
3✔
4351
            vlog_set_loc(eq, CURRENT_LOC);
3✔
4352

4353
            if (cond == NULL) {
3✔
4354
               cond = eq;
4355
            }
4356
            else {
4357
               vlog_node_t lor = vlog_new(V_BINARY);
×
4358
               vlog_set_subkind(lor, V_BINARY_LOG_OR);
×
4359
               vlog_set_left(lor, cond);
×
4360
               vlog_set_right(lor, eq);
×
4361
               vlog_set_loc(lor, CURRENT_LOC);
×
4362
               cond = lor;
×
4363
            }
4364
         } while (optional(tCOMMA));
3✔
4365

4366
         consume(tCOLON);
3✔
4367
         vlog_set_value(cn, cond);
3✔
4368
      }
4369

4370
      vlog_set_loc(cn, CURRENT_LOC);
3✔
4371
      vlog_add_stmt(cn, p_generate_block());
3✔
4372
      vlog_add_cond(v, cn);
3✔
4373
   }
4374

4375
   consume(tENDCASE);
1✔
4376

4377
   vlog_set_loc(v, CURRENT_LOC);
1✔
4378
   return v;
1✔
4379
}
4380

4381
static vlog_node_t p_conditional_generate_construct(void)
35✔
4382
{
4383
   // if_generate_construct | case_generate_construct
4384

4385
   BEGIN("conditional generate construct");
70✔
4386

4387
   switch (peek()) {
35✔
4388
   case tIF:
34✔
4389
      return p_if_generate_construct();
34✔
4390
   case tCASE:
1✔
4391
      return p_case_generate_construct();
1✔
4392
   default:
×
4393
      should_not_reach_here();
4394
   }
4395
}
4396

4397
static vlog_node_t p_genvar_initialization(void)
15✔
4398
{
4399
   // [ genvar ] genvar_identifier = constant_expression
4400

4401
   BEGIN("genvar initialization");
30✔
4402

4403
   vlog_node_t v = vlog_new(V_FOR_INIT);
15✔
4404

4405
   vlog_node_t ref = vlog_new(V_REF);
15✔
4406
   vlog_set_ident(ref, p_identifier());
15✔
4407
   vlog_set_loc(ref, &state.last_loc);
15✔
4408

4409
   vlog_symtab_lookup(symtab, ref);
15✔
4410

4411
   consume(tEQ);
15✔
4412

4413
   vlog_node_t a = vlog_new(V_BASSIGN);
15✔
4414
   vlog_set_target(a, ref);
15✔
4415
   vlog_set_value(a, p_constant_expression());
15✔
4416
   vlog_set_loc(a, CURRENT_LOC);
15✔
4417

4418
   vlog_add_stmt(v, a);
15✔
4419

4420
   vlog_set_loc(v, CURRENT_LOC);
15✔
4421
   return v;
15✔
4422
}
4423

4424
static vlog_node_t p_genvar_iteration(void)
15✔
4425
{
4426
   // genvar_identifier assignment_operator genvar_expression
4427
   //   | inc_or_dec_operator genvar_identifier
4428
   //   | genvar_identifier inc_or_dec_operator
4429

4430
   BEGIN("genvar iteration");
30✔
4431

4432
   vlog_node_t v = vlog_new(V_FOR_STEP);
15✔
4433

4434
   vlog_node_t prefix = NULL;
15✔
4435
   if (scan(tPLUSPLUS, tMINUSMINUS)) {
15✔
4436
      prefix = vlog_new(V_PREFIX);
1✔
4437
      vlog_set_subkind(prefix, p_inc_or_dec_operator());
1✔
4438
   }
4439

4440
   vlog_node_t ref = vlog_new(V_REF);
15✔
4441
   vlog_set_ident(ref, p_identifier());
15✔
4442
   vlog_set_loc(ref, &state.last_loc);
15✔
4443

4444
   vlog_symtab_lookup(symtab, ref);
15✔
4445

4446
   if (prefix != NULL) {
15✔
4447
      vlog_set_target(prefix, ref);
1✔
4448

4449
      vlog_add_stmt(v, prefix);
1✔
4450
   }
4451
   else if (optional(tEQ)) {
14✔
4452
      vlog_node_t a = vlog_new(V_BASSIGN);
13✔
4453
      vlog_set_target(a, ref);
13✔
4454
      vlog_set_value(a, p_constant_expression());
13✔
4455

4456
      vlog_add_stmt(v, a);
13✔
4457
   }
4458
   else {
4459
      vlog_node_t a = vlog_new(V_POSTFIX);
1✔
4460
      vlog_set_subkind(a, p_inc_or_dec_operator());
1✔
4461
      vlog_set_target(a, ref);
1✔
4462

4463
      vlog_add_stmt(v, a);
1✔
4464
   }
4465

4466
   vlog_set_loc(v, CURRENT_LOC);
15✔
4467
   return v;
15✔
4468
}
4469

4470
static vlog_node_t p_loop_generate_construct(void)
15✔
4471
{
4472
   // for ( genvar_initialization ; genvar_expression ; genvar_iteration )
4473
   //   generate_block
4474

4475
   BEGIN("loop generate construct");
30✔
4476

4477
   consume(tFOR);
15✔
4478
   consume(tLPAREN);
15✔
4479

4480
   vlog_node_t v = vlog_new(V_FOR_GENERATE);
15✔
4481

4482
   vlog_symtab_push(symtab, v);
15✔
4483

4484
   vlog_set_left(v, p_genvar_initialization());
15✔
4485

4486
   consume(tSEMI);
15✔
4487

4488
   vlog_set_value(v, p_constant_expression());
15✔
4489

4490
   consume(tSEMI);
15✔
4491

4492
   vlog_set_right(v, p_genvar_iteration());
15✔
4493

4494
   consume(tRPAREN);
15✔
4495

4496
   vlog_add_stmt(v, p_generate_block());
15✔
4497

4498
   vlog_symtab_pop(symtab);
15✔
4499

4500
   vlog_set_loc(v, CURRENT_LOC);
15✔
4501
   return v;
15✔
4502
}
4503

4504
static void p_module_common_item(vlog_node_t mod)
6,796✔
4505
{
4506
   // module_or_generate_item_declaration
4507
   //   | interface_instantiation | program_instantiation
4508
   //   | assertion_item | bind_directive | continuous_assign
4509
   //   | net_alias | initial_construct | final_construct
4510
   //   | always_construct | loop_generate_construct
4511
   //   | conditional_generate_construct | elaboration_system_task
4512

4513
   BEGIN("module common item");
13,592✔
4514

4515
   switch (peek()) {
6,796✔
4516
   case tALWAYS:
326✔
4517
   case tALWAYSCOMB:
4518
   case tALWAYSFF:
4519
   case tALWAYSLATCH:
4520
      vlog_add_stmt(mod, p_always_construct());
326✔
4521
      break;
326✔
4522
   case tINITIAL:
784✔
4523
      vlog_add_stmt(mod, p_initial_construct());
784✔
4524
      break;
784✔
4525
   case tWIRE:
4,975✔
4526
   case tUWIRE:
4527
   case tSUPPLY0:
4528
   case tSUPPLY1:
4529
   case tTRI:
4530
   case tTRI0:
4531
   case tTRI1:
4532
   case tTRIAND:
4533
   case tTRIOR:
4534
   case tTRIREG:
4535
   case tWAND:
4536
   case tWOR:
4537
   case tINTERCONNECT:
4538
   case tREG:
4539
   case tSTRUCT:
4540
   case tUNION:
4541
   case tTYPEDEF:
4542
   case tENUM:
4543
   case tSVINT:
4544
   case tINTEGER:
4545
   case tSVREAL:
4546
   case tSHORTREAL:
4547
   case tREALTIME:
4548
   case tTIME:
4549
   case tTASK:
4550
   case tFUNCTION:
4551
   case tLOCALPARAM:
4552
   case tPARAMETER:
4553
   case tEVENT:
4554
   case tID:
4555
   case tGENVAR:
4556
   case tVAR:
4557
   case tLOGIC:
4558
   case tBIT:
4559
   case tSHORTINT:
4560
   case tLONGINT:
4561
   case tBYTE:
4562
   case tSTRINGK:
4563
   case tIMPORT:
4564
      p_module_or_generate_item_declaration(mod);
4,975✔
4565
      break;
4,975✔
4566
   case tASSIGN:
660✔
4567
      p_continuous_assign(mod);
660✔
4568
      break;
660✔
4569
   case tFOR:
15✔
4570
      vlog_add_stmt(mod, p_loop_generate_construct());
15✔
4571
      break;
15✔
4572
   case tIF:
35✔
4573
   case tCASE:
4574
      vlog_add_stmt(mod, p_conditional_generate_construct());
35✔
4575
      break;
35✔
4576
   case tFINAL:
1✔
4577
      vlog_add_stmt(mod, p_final_construct());
1✔
4578
      break;
1✔
4579
   default:
×
4580
      one_of(tALWAYS, tALWAYSCOMB, tALWAYSFF, tALWAYSLATCH, tWIRE, tUWIRE,
×
4581
             tSUPPLY0, tSUPPLY1, tTRI, tTRI0, tTRI1, tTRIAND, tTRIOR, tTRIREG,
4582
             tWAND, tWOR, tINTERCONNECT, tREG, tSTRUCT, tUNION, tTYPEDEF, tENUM,
4583
             tSVINT, tINTEGER, tSVREAL, tSHORTREAL, tREALTIME, tTIME, tTASK,
4584
             tFUNCTION, tPARAMETER, tLOCALPARAM, tEVENT, tID, tGENVAR, tVAR,
4585
             tLOGIC, tBIT, tSHORTINT, tLONGINT, tBYTE, tSTRINGK, tIMPORT,
4586
             tASSIGN, tFOR, tIF, tCASE, tFINAL);
4587
      drop_tokens_until(&state, tSEMI);
×
4588
   }
4589
}
6,796✔
4590

4591
static vlog_strength_t p_strength0(void)
58✔
4592
{
4593
   // supply0 | strong0 | pull0 | weak0
4594

4595
   BEGIN("strength0");
116✔
4596

4597
   switch (one_of(tSUPPLY0, tSTRONG0, tPULL0, tWEAK0)) {
58✔
4598
   default:
4599
   case tSUPPLY0: return V_STRENGTH_SUPPLY;
4600
   case tSTRONG0: return V_STRENGTH_STRONG;
4601
   case tPULL0:   return V_STRENGTH_PULL;
4602
   case tWEAK0:   return V_STRENGTH_WEAK;
4603
   }
4604
}
4605

4606
static vlog_strength_t p_strength1(void)
60✔
4607
{
4608
   // supply1 | strong1 | pull1 | weak1
4609

4610
   BEGIN("strength1");
120✔
4611

4612
   switch (one_of(tSUPPLY1, tSTRONG1, tPULL1, tWEAK1)) {
60✔
4613
   default:
4614
   case tSUPPLY1: return V_STRENGTH_SUPPLY;
4615
   case tSTRONG1: return V_STRENGTH_STRONG;
4616
   case tPULL1:   return V_STRENGTH_PULL;
4617
   case tWEAK1:   return V_STRENGTH_WEAK;
4618
   }
4619
}
4620

4621
static vlog_node_t p_pulldown_strength(void)
2✔
4622
{
4623
   // ( strength0 , strength1 ) | ( strength1 , strength0 ) | ( strength0 )
4624

4625
   BEGIN("pulldown strength");
4✔
4626

4627
   consume(tLPAREN);
2✔
4628

4629
   vlog_strength_t s0, s1;
2✔
4630
   switch (peek()) {
2✔
4631
   case tSUPPLY1:
×
4632
   case tSTRONG1:
4633
   case tPULL1:
4634
   case tWEAK1:
4635
      s1 = p_strength1();
×
4636
      consume(tCOMMA);
×
4637
      s0 = p_strength0();
×
4638
      break;
×
4639
   default:
2✔
4640
      s0 = s1 = p_strength0();
2✔
4641
      if (optional(tCOMMA))
2✔
4642
         s1 = p_strength1();
×
4643
      break;
4644
   }
4645

4646
   consume(tRPAREN);
2✔
4647

4648
   vlog_node_t v = vlog_new(V_STRENGTH);
2✔
4649
   vlog_set_subkind(v, MAKE_STRENGTH(s0, s1));
2✔
4650
   vlog_set_loc(v, CURRENT_LOC);
2✔
4651
   return v;
2✔
4652
}
4653

4654
static vlog_node_t p_pullup_strength(void)
7✔
4655
{
4656
   // ( strength0 , strength1 ) | ( strength1 , strength0 ) | ( strength1 )
4657

4658
   BEGIN("pullup strength");
14✔
4659

4660
   consume(tLPAREN);
7✔
4661

4662
   vlog_strength_t s0, s1;
7✔
4663
   switch (peek()) {
7✔
4664
   case tSUPPLY0:
1✔
4665
   case tSTRONG0:
4666
   case tPULL0:
4667
   case tWEAK0:
4668
      s0 = p_strength0();
1✔
4669
      consume(tCOMMA);
1✔
4670
      s1 = p_strength1();
1✔
4671
      break;
1✔
4672
   default:
6✔
4673
      s1 = s0 = p_strength1();
6✔
4674
      if (optional(tCOMMA))
6✔
4675
         s0 = p_strength0();
1✔
4676
      break;
4677
   }
4678

4679
   consume(tRPAREN);
7✔
4680

4681
   vlog_node_t v = vlog_new(V_STRENGTH);
7✔
4682
   vlog_set_subkind(v, MAKE_STRENGTH(s0, s1));
7✔
4683
   vlog_set_loc(v, CURRENT_LOC);
7✔
4684
   return v;
7✔
4685
}
4686

4687
static vlog_node_t p_pull_gate_instance(vlog_gate_kind_t kind, vlog_node_t st)
22✔
4688
{
4689
   // [ name_of_instance ] ( output_terminal )
4690

4691
   BEGIN("pull gate instance");
44✔
4692

4693
   vlog_node_t v = vlog_new(V_GATE_INST);
22✔
4694
   vlog_set_subkind(v, kind);
22✔
4695
   vlog_add_param(v, st);
22✔
4696

4697
   if (peek() == tID) {
22✔
4698
      vlog_set_ident(v, p_identifier());
7✔
4699
      vlog_set_loc(v, &state.last_loc);
7✔
4700
      vlog_symtab_put(symtab, v);
7✔
4701
   }
4702
   else
4703
      vlog_set_ident(v, default_label("gate"));
15✔
4704

4705
   consume(tLPAREN);
22✔
4706

4707
   vlog_symtab_set_implicit(symtab, implicit_kind);
22✔
4708

4709
   vlog_set_target(v, p_net_lvalue());
22✔
4710

4711
   vlog_symtab_set_implicit(symtab, V_NET_NONE);
22✔
4712

4713
   consume(tRPAREN);
22✔
4714

4715
   vlog_set_loc(v, CURRENT_LOC);
22✔
4716
   return v;
22✔
4717
}
4718

4719
static vlog_node_t p_n_terminal_gate_instance(vlog_gate_kind_t kind,
55✔
4720
                                              vlog_node_t st)
4721
{
4722
   // [ name_of_instance ] ( output_terminal , input_terminal
4723
   //     { , input_terminal } )
4724

4725
   BEGIN("N-terminal gate instance");
110✔
4726

4727
   vlog_node_t v = vlog_new(V_GATE_INST);
55✔
4728
   vlog_set_subkind(v, kind);
55✔
4729

4730
   if (peek() == tID) {
55✔
4731
      vlog_set_ident(v, p_identifier());
17✔
4732
      vlog_set_loc(v, &state.last_loc);
17✔
4733
      vlog_symtab_put(symtab, v);
17✔
4734
   }
4735
   else
4736
      vlog_set_ident(v, default_label("gate"));
38✔
4737

4738
   consume(tLPAREN);
55✔
4739

4740
   vlog_symtab_set_implicit(symtab, implicit_kind);
55✔
4741

4742
   vlog_set_target(v, p_net_lvalue());
55✔
4743

4744
   consume(tCOMMA);
55✔
4745

4746
   do {
76✔
4747
      vlog_add_param(v, p_expression());
76✔
4748
   } while (optional(tCOMMA));
76✔
4749

4750
   vlog_symtab_set_implicit(symtab, V_NET_NONE);
55✔
4751

4752
   consume(tRPAREN);
55✔
4753

4754
   vlog_set_loc(v, CURRENT_LOC);
55✔
4755
   return v;
55✔
4756
}
4757

4758
static vlog_node_t p_enable_gate_instance(vlog_gate_kind_t kind)
1✔
4759
{
4760
   // [ name_of_instance ] ( output_terminal , input_terminal ,
4761
   //     enable_terminal )
4762

4763
   BEGIN("enable gate instance");
2✔
4764

4765
   vlog_node_t v = vlog_new(V_GATE_INST);
1✔
4766
   vlog_set_subkind(v, kind);
1✔
4767

4768
   if (peek() == tID) {
1✔
4769
      vlog_set_ident(v, p_identifier());
×
4770
      vlog_set_loc(v, &state.last_loc);
×
4771
      vlog_symtab_put(symtab, v);
×
4772
   }
4773
   else
4774
      vlog_set_ident(v, default_label("gate"));
1✔
4775

4776
   consume(tLPAREN);
1✔
4777

4778
   vlog_symtab_set_implicit(symtab, implicit_kind);
1✔
4779

4780
   vlog_set_target(v, p_net_lvalue());
1✔
4781

4782
   consume(tCOMMA);
1✔
4783

4784
   vlog_add_param(v, p_expression());
1✔
4785

4786
   consume(tCOMMA);
1✔
4787

4788
   vlog_add_param(v, p_expression());
1✔
4789

4790
   vlog_symtab_set_implicit(symtab, V_NET_NONE);
1✔
4791

4792
   consume(tRPAREN);
1✔
4793

4794
   vlog_set_loc(v, CURRENT_LOC);
1✔
4795
   return v;
1✔
4796
}
4797

4798
static vlog_node_t p_pass_switch_instance(vlog_gate_kind_t kind)
1✔
4799
{
4800
   // [ name_of_instance ] ( inout_terminal , inout_terminal )
4801

4802
   BEGIN("pass switch instance");
2✔
4803

4804
   vlog_node_t v = vlog_new(V_GATE_INST);
1✔
4805
   vlog_set_subkind(v, kind);
1✔
4806

4807
   if (peek() == tID) {
1✔
4808
      vlog_set_ident(v, p_identifier());
×
4809
      vlog_set_loc(v, &state.last_loc);
×
4810
      vlog_symtab_put(symtab, v);
×
4811
   }
4812
   else
4813
      vlog_set_ident(v, default_label("gate"));
1✔
4814

4815
   consume(tLPAREN);
1✔
4816

4817
   vlog_symtab_set_implicit(symtab, implicit_kind);
1✔
4818

4819
   vlog_set_target(v, p_net_lvalue());
1✔
4820

4821
   consume(tCOMMA);
1✔
4822

4823
   vlog_add_param(v, p_net_lvalue());
1✔
4824

4825
   vlog_symtab_set_implicit(symtab, V_NET_NONE);
1✔
4826

4827
   consume(tRPAREN);
1✔
4828

4829
   vlog_set_loc(v, CURRENT_LOC);
1✔
4830
   return v;
1✔
4831
}
4832

4833
static vlog_node_t p_pass_enable_switch_instance(vlog_gate_kind_t kind)
1✔
4834
{
4835
   // [ name_of_instance ] ( inout_terminal , inout_terminal ,
4836
   //     enable_terminal )
4837

4838
   BEGIN("pass enable switch instance");
2✔
4839

4840
   vlog_node_t v = vlog_new(V_GATE_INST);
1✔
4841
   vlog_set_subkind(v, kind);
1✔
4842

4843
   if (peek() == tID) {
1✔
4844
      vlog_set_ident(v, p_identifier());
×
4845
      vlog_set_loc(v, &state.last_loc);
×
4846
      vlog_symtab_put(symtab, v);
×
4847
   }
4848
   else
4849
      vlog_set_ident(v, default_label("gate"));
1✔
4850

4851
   consume(tLPAREN);
1✔
4852

4853
   vlog_symtab_set_implicit(symtab, implicit_kind);
1✔
4854

4855
   vlog_set_target(v, p_net_lvalue());
1✔
4856

4857
   consume(tCOMMA);
1✔
4858

4859
   vlog_add_param(v, p_net_lvalue());
1✔
4860

4861
   consume(tCOMMA);
1✔
4862

4863
   vlog_add_param(v, p_expression());
1✔
4864

4865
   vlog_symtab_set_implicit(symtab, V_NET_NONE);
1✔
4866

4867
   consume(tRPAREN);
1✔
4868

4869
   vlog_set_loc(v, CURRENT_LOC);
1✔
4870
   return v;
1✔
4871
}
4872

4873
static void p_gate_instantiation(vlog_node_t mod)
80✔
4874
{
4875
   // cmos_switchtype [ delay3 ] cmos_switch_instance
4876
   //     { , cmos_switch_instance } ;
4877
   //  | enable_gatetype [ drive_strength ] [ delay3 ]
4878
   //     enable_gate_instance { , enable_gate_instance } ;
4879
   //  | mos_switchtype [ delay3 ] mos_switch_instance
4880
   //     { , mos_switch_instance } ;
4881
   //  | n_input_gatetype [ drive_strength ] [ delay2 ] n_input_gate_instance
4882
   //     { , n_input_gate_instance } ;
4883
   //  | n_output_gatetype [ drive_strength ] [ delay2 ] n_output_gate_instance
4884
   //     { , n_output_gate_instance } ;
4885
   //  | pass_en_switchtype [ delay2 ] pass_enable_switch_instance
4886
   //     { , pass_enable_switch_instance } ;
4887
   //  | pass_switchtype pass_switch_instance { , pass_switch_instance } ;
4888
   //  | pulldown [ pulldown_strength ] pull_gate_instance
4889
   //     { , pull_gate_instance } ;
4890
   //  | pullup [ pullup_strength ] pull_gate_instance
4891
   //     { , pull_gate_instance } ;
4892

4893
   BEGIN("gate instantiation");
160✔
4894

4895
   token_t token = one_of(tPULLDOWN, tPULLUP, tAND, tNAND, tOR, tNOR,
80✔
4896
                          tXOR, tXNOR, tNOT, tBUF, tBUFIF0, tBUFIF1,
4897
                          tNOTIF0, tNOTIF1, tTRAN, tRTRAN, tTRANIF0, tTRANIF1,
4898
                          tRTRANIF0, tRTRANIF1);
4899

4900
   switch (token) {
80✔
4901
   case tPULLDOWN:
8✔
4902
      {
4903
         vlog_node_t st;
8✔
4904
         if (peek() == tLPAREN && peek_nth(2) != tID)
8✔
4905
            st = p_pulldown_strength();
2✔
4906
         else {
4907
            st = vlog_new(V_STRENGTH);
6✔
4908
            vlog_set_subkind(st, ST_PULLUP);
6✔
4909
         }
4910

4911
         do {
8✔
4912
            vlog_node_t g = p_pull_gate_instance(V_GATE_PULLDOWN, st);
8✔
4913
            vlog_add_stmt(mod, g);
8✔
4914
         } while (optional(tCOMMA));
8✔
4915
      }
4916
      break;
4917

4918
   case tPULLUP:
14✔
4919
      {
4920
         vlog_node_t st;
14✔
4921
         if (peek() == tLPAREN && peek_nth(2) != tID)
14✔
4922
            st = p_pullup_strength();
7✔
4923
         else {
4924
            st = vlog_new(V_STRENGTH);
7✔
4925
            vlog_set_subkind(st, ST_PULLUP);
7✔
4926
         }
4927

4928
         do {
14✔
4929
            vlog_node_t g = p_pull_gate_instance(V_GATE_PULLUP, st);
14✔
4930
            vlog_add_stmt(mod, g);
14✔
4931
         } while (optional(tCOMMA));
14✔
4932
      }
4933
      break;
4934

4935
   case tAND:
55✔
4936
   case tNAND:
4937
   case tOR:
4938
   case tNOR:
4939
   case tXOR:
4940
   case tXNOR:
4941
   case tNOT:
4942
   case tBUF:
4943
      {
4944
         vlog_node_t st;
55✔
4945
         if (peek() == tLPAREN && peek_nth(2) != tID)
55✔
4946
            st = p_drive_strength();
1✔
4947
         else {
4948
            st = vlog_new(V_STRENGTH);
54✔
4949
            vlog_set_subkind(st, ST_STRONG);
54✔
4950
         }
4951

4952
         const vlog_gate_kind_t kind = get_gate_kind(token);
55✔
4953

4954
         if (peek() == tHASH)
55✔
4955
            p_delay2();
2✔
4956

4957
         do {
55✔
4958
            vlog_add_stmt(mod, p_n_terminal_gate_instance(kind, st));
55✔
4959
         } while (optional(tCOMMA));
55✔
4960
      }
4961
      break;
4962

4963
   case tBUFIF0:
1✔
4964
   case tBUFIF1:
4965
   case tNOTIF0:
4966
   case tNOTIF1:
4967
      {
4968
         vlog_node_t st;
1✔
4969
         if (peek() == tLPAREN && peek_nth(2) != tID)
1✔
4970
            st = p_drive_strength();
1✔
4971
         else {
4972
            st = vlog_new(V_STRENGTH);
×
4973
            vlog_set_subkind(st, ST_STRONG);
×
4974
         }
4975

4976
         if (peek() == tHASH)
1✔
4977
            p_delay3();
×
4978

4979
         const vlog_gate_kind_t kind = get_gate_kind(token);
1✔
4980

4981
         do {
1✔
4982
            vlog_add_stmt(mod, p_enable_gate_instance(kind));
1✔
4983
         } while (optional(tCOMMA));
1✔
4984
      }
4985
      break;
4986

4987
   case tTRAN:
1✔
4988
   case tRTRAN:
4989
      {
4990
         const vlog_gate_kind_t kind = get_gate_kind(token);
1✔
4991

4992
         do {
1✔
4993
            vlog_add_stmt(mod, p_pass_switch_instance(kind));
1✔
4994
         } while (optional(tCOMMA));
1✔
4995
      }
4996
      break;
4997

4998
   case tTRANIF0:
1✔
4999
   case tTRANIF1:
5000
   case tRTRANIF0:
5001
   case tRTRANIF1:
5002
      {
5003
         if (peek() == tHASH)
1✔
5004
            p_delay2();
×
5005

5006
         const vlog_gate_kind_t kind = get_gate_kind(token);
1✔
5007

5008
         do {
1✔
5009
            vlog_add_stmt(mod, p_pass_enable_switch_instance(kind));
1✔
5010
         } while (optional(tCOMMA));
1✔
5011
      }
5012
      break;
5013

5014
   default:
5015
      break;
5016
   }
5017

5018
   consume(tSEMI);
80✔
5019
}
80✔
5020

5021
static vlog_node_t p_module_path_expression(void)
4✔
5022
{
5023
   // module_path_primary
5024
   //   | unary_module_path_operator { attribute_instance } module_path_primary
5025
   //   | module_path_expression binary_module_path_operator
5026
   //      { attribute_instance } module_path_expression
5027
   //   | module_path_conditional_expression
5028

5029
   BEGIN("module path expression");
8✔
5030

5031
   // TODO: sem should check valid subset
5032
   return p_expression();
4✔
5033
}
5034

5035
static void p_path_delay_expression(void)
22✔
5036
{
5037
   // constant_expression
5038
   //   | constant_expression : constant_expression : constant_expression
5039

5040
   BEGIN("path delay expression");
44✔
5041

5042
   (void)p_constant_expression();
22✔
5043
}
22✔
5044

5045
static void p_list_of_path_delay_expressions(void)
18✔
5046
{
5047
   // path_delay_expression { , path_delay_expression }
5048

5049
   BEGIN("list of path delay expressions");
36✔
5050

5051
   do {
22✔
5052
      p_path_delay_expression();
22✔
5053
   } while (optional(tCOMMA));
22✔
5054
}
18✔
5055

5056
static void p_path_delay_value(void)
18✔
5057
{
5058
   // list_of_path_delay_expressions | ( list_of_path_delay_expressions )
5059

5060
   BEGIN("path delay value");
36✔
5061

5062
   if (optional(tLPAREN)) {
18✔
5063
      p_list_of_path_delay_expressions();
4✔
5064
      consume(tRPAREN);
4✔
5065
   }
5066
   else
5067
      p_list_of_path_delay_expressions();
14✔
5068
}
18✔
5069

5070
static vlog_node_t p_specify_terminal_descriptor(void)
76✔
5071
{
5072
   // identifier [ [ constant_range_expression ] ]
5073

5074
   BEGIN("specify terminal descriptor");
152✔
5075

5076
   vlog_node_t v = vlog_new(V_REF);
76✔
5077
   vlog_set_ident(v, p_identifier());
76✔
5078
   vlog_set_loc(v, CURRENT_LOC);
76✔
5079

5080
   if (optional(tLSQUARE)) {
76✔
5081
      (void)p_constant_range_expression();
2✔
5082
      consume(tRSQUARE);
2✔
5083
   }
5084

5085
   return v;
76✔
5086
}
5087

5088
static void p_list_of_path_inputs(vlog_node_t v, vlog_node_t head)
8✔
5089
{
5090
   // specify_input_terminal_descriptor { , specify_input_terminal_descriptor }
5091

5092
   BEGIN_WITH_HEAD("list of path inputs", head);
16✔
5093

5094
   while (optional(tCOMMA))
15✔
5095
      (void)p_specify_terminal_descriptor();
7✔
5096
}
8✔
5097

5098
static void p_list_of_path_outputs(vlog_node_t v)
8✔
5099
{
5100
   // specify_output_terminal_descriptor
5101
   //     { , specify_output_terminal_descriptor }
5102

5103
   BEGIN("list of path outputs");
16✔
5104

5105
   do {
17✔
5106
      (void)p_specify_terminal_descriptor();
17✔
5107
   } while (optional(tCOMMA));
17✔
5108
}
8✔
5109

5110
static void p_polarity_operator(void)
9✔
5111
{
5112
   // + | -
5113

5114
   BEGIN("polarity operator");
18✔
5115

5116
   (void)one_of(tPLUS, tMINUS);
9✔
5117
}
9✔
5118

5119
static vlog_node_t p_parallel_path_description(vlog_node_t head)
8✔
5120
{
5121
   // ( specify_input_terminal_descriptor [ polarity_operator ]
5122
   //     => specify_output_terminal_descriptor )
5123

5124
   EXTEND("parallel path description");
16✔
5125

5126
   if (scan(tPLUS, tMINUS))
8✔
5127
      (void)p_polarity_operator();
3✔
5128

5129
   consume(tASSOC);
8✔
5130

5131
   (void)p_specify_terminal_descriptor();
8✔
5132

5133
   consume(tRPAREN);
8✔
5134
   return NULL;
8✔
5135
}
5136

5137
static vlog_node_t p_full_path_description(vlog_node_t head)
3✔
5138
{
5139
   // ( list_of_path_inputs [ polarity_operator ] *> list_of_path_outputs )
5140

5141
   EXTEND("full path description");
6✔
5142

5143
   p_list_of_path_inputs(NULL, head);
3✔
5144

5145
   if (scan(tPLUS, tMINUS))
3✔
5146
      (void)p_polarity_operator();
3✔
5147

5148
   consume(tTIMESGT);
3✔
5149

5150
   p_list_of_path_outputs(NULL);
3✔
5151

5152
   consume(tRPAREN);
3✔
5153
   return NULL;
3✔
5154
}
5155

5156
static vlog_node_t p_simple_path_declaration(void)
11✔
5157
{
5158
   // parallel_path_description = path_delay_value
5159
   //   | full_path_description = path_delay_value
5160

5161
   BEGIN("simple path declaration");
22✔
5162

5163
   // Parse up to the first terminal descriptor to determine which
5164
   // production to use
5165

5166
   consume(tLPAREN);
11✔
5167

5168
   vlog_node_t head = p_specify_terminal_descriptor();
11✔
5169

5170
   if (scan(tCOMMA, tTIMESGT) || peek_nth(2) == tTIMESGT)
11✔
5171
      (void)p_full_path_description(head);
3✔
5172
   else
5173
      (void)p_parallel_path_description(head);
8✔
5174

5175
   consume(tEQ);
11✔
5176

5177
   (void)p_path_delay_value();
11✔
5178

5179
   return NULL;
11✔
5180
}
5181

5182
static void p_edge_identifier(void)
7✔
5183
{
5184
   // posedge | negedge | edge
5185

5186
   BEGIN("edge identifier");
14✔
5187

5188
   one_of(tPOSEDGE, tNEGEDGE, tEDGE);
7✔
5189
}
7✔
5190

5191
static vlog_node_t p_parallel_edge_sensitive_path_description(vlog_node_t head)
2✔
5192
{
5193
   // ( [ edge_identifier ] specify_input_terminal_descriptor
5194
   //     [ polarity_operator ] => ( specify_output_terminal_descriptor
5195
   //     [ polarity_operator ] : data_source_expression ) )
5196

5197
   EXTEND("parallel edge sensitive path description");
4✔
5198

5199
   if (scan(tPLUS, tMINUS))
2✔
5200
      (void)p_polarity_operator();
×
5201

5202
   consume(tASSOC);
2✔
5203

5204
   consume(tLPAREN);
2✔
5205

5206
   (void)p_specify_terminal_descriptor();
2✔
5207

5208
   if (scan(tPLUS, tMINUS)) {
2✔
5209
      (void)p_polarity_operator();
×
5210
      consume(tCOLON);
×
5211
   }
5212
   else if (scan(tINDEXPOS, tINDEXNEG))
2✔
5213
      consume(peek());  // Lexing ambiguity with +: and -:
1✔
5214
   else
5215
      consume(tCOLON);
1✔
5216

5217
   (void)p_expression();
2✔
5218

5219
   consume(tRPAREN);
2✔
5220
   consume(tRPAREN);
2✔
5221
   return NULL;
2✔
5222
}
5223

5224
static vlog_node_t p_full_edge_sensitive_path_description(vlog_node_t head)
5✔
5225
{
5226
   // ( [ edge_identifier ] list_of_path_inputs [ polarity_operator ] *>
5227
   //     ( list_of_path_outputs [ polarity_operator ]
5228
   //     : data_source_expression ) )
5229

5230
   EXTEND("full edge sensitive path description");
10✔
5231

5232
   p_list_of_path_inputs(NULL, head);
5✔
5233

5234
   if (scan(tPLUS, tMINUS))
5✔
5235
      (void)p_polarity_operator();
3✔
5236

5237
   consume(tTIMESGT);
5✔
5238

5239
   consume(tLPAREN);
5✔
5240

5241
   p_list_of_path_outputs(NULL);
5✔
5242

5243
   if (scan(tPLUS, tMINUS)) {
5✔
5244
      (void)p_polarity_operator();
×
5245
      consume(tCOLON);
×
5246
   }
5247
   else if (scan(tINDEXPOS, tINDEXNEG))
5✔
5248
      consume(peek());  // Lexing ambiguity with +: and -:
2✔
5249
   else
5250
      consume(tCOLON);
3✔
5251

5252
   (void)p_expression();
5✔
5253

5254
   consume(tRPAREN);
5✔
5255
   consume(tRPAREN);
5✔
5256
   return NULL;
5✔
5257
}
5258

5259
static vlog_node_t p_edge_sensitive_path_declaration(void)
7✔
5260
{
5261
   // parallel_edge_sensitive_path_description = path_delay_value
5262
   //   | full_edge_sensitive_path_description = path_delay_value
5263

5264
   BEGIN("edge sensitive path declaration");
14✔
5265

5266
   // Parse up to the first terminal descriptor to determine which
5267
   // production to use
5268

5269
   consume(tLPAREN);
7✔
5270

5271
   if (scan(tEDGE, tPOSEDGE, tNEGEDGE))
7✔
5272
      p_edge_identifier();
7✔
5273

5274
   vlog_node_t head = p_specify_terminal_descriptor();
7✔
5275

5276
   if (scan(tCOMMA, tTIMESGT) || peek_nth(2) == tTIMESGT)
7✔
5277
      (void)p_full_edge_sensitive_path_description(head);
5✔
5278
   else
5279
      (void)p_parallel_edge_sensitive_path_description(head);
2✔
5280

5281
   consume(tEQ);
7✔
5282

5283
   (void)p_path_delay_value();
7✔
5284

5285
   return NULL;
7✔
5286
}
5287

5288
static vlog_node_t p_state_dependent_path_declaration(void)
6✔
5289
{
5290
   // if ( module_path_expression ) simple_path_declaration
5291
   //   | if ( module_path_expression ) edge_sensitive_path_declaration
5292
   //   | ifnone simple_path_declaration
5293

5294
   BEGIN("state dependent path declaration");
12✔
5295

5296
   switch (one_of(tIF, tIFNONE)) {
6✔
5297
   case tIF:
4✔
5298
      consume(tLPAREN);
4✔
5299
      (void)p_module_path_expression();
4✔
5300
      consume(tRPAREN);
4✔
5301
      break;
4✔
5302
   case tIFNONE:
5303
      break;
5304
   }
5305

5306
   if (peek_nth(2) == tID)
6✔
5307
      (void)p_simple_path_declaration();
2✔
5308
   else {
5309
      // This is invalid for ifnone according to the grammar but is
5310
      // accepted by some simulators and seen in the wild
5311
      (void)p_edge_sensitive_path_declaration();
4✔
5312
   }
5313

5314
   return NULL;
6✔
5315
}
5316

5317
static vlog_node_t p_path_declaration(void)
18✔
5318
{
5319
   // simple_path_declaration ;
5320
   //  | edge_sensitive_path_declaration ;
5321
   //  | state_dependent_path_declaration ;
5322

5323
   BEGIN("path declaration");
36✔
5324

5325
   switch (peek()) {
18✔
5326
   case tIF:
6✔
5327
   case tIFNONE:
5328
      (void)p_state_dependent_path_declaration();
6✔
5329
      break;
6✔
5330
   case tLPAREN:
12✔
5331
      switch (peek_nth(2)) {
12✔
5332
      case tEDGE:
3✔
5333
      case tNEGEDGE:
5334
      case tPOSEDGE:
5335
         (void)p_edge_sensitive_path_declaration();
3✔
5336
         break;
3✔
5337
      default:
9✔
5338
         (void)p_simple_path_declaration();
9✔
5339
         break;
9✔
5340
      }
5341
      break;
5342
   default:
×
5343
      one_of(tIF, tIFNONE);
×
5344
   }
5345

5346
   consume(tSEMI);
18✔
5347
   return NULL;
18✔
5348
}
5349

5350
static void p_timing_check_event_control(void)
8✔
5351
{
5352
   // posedge | negedge | edge | edge_control_specifier
5353

5354
   BEGIN("timing check event control");
16✔
5355

5356
   one_of(tPOSEDGE, tNEGEDGE, tEDGE);
8✔
5357
}
8✔
5358

5359
static void p_scalar_timing_check_condition(void)
4✔
5360
{
5361
   //    expression
5362
   // | ~ expression
5363
   // | expression == scalar_constant
5364
   // | expression === scalar_constant
5365
   // | expression != scalar_constant
5366
   // | expression !== scalar_constant
5367

5368
   BEGIN("scalar timing check condition")
8✔
5369

5370
   p_expression();
4✔
5371
}
4✔
5372

5373
static void p_timing_check_condition(void)
4✔
5374
{
5375
   //     scalar_timing_check_condition
5376
   // | ( scalar_timing_check_condition )
5377

5378
   BEGIN("timing check condition");
8✔
5379

5380
   if (optional(tLPAREN)) {
4✔
5381
      p_scalar_timing_check_condition();
1✔
5382
      consume(tRPAREN);
1✔
5383
   }
5384
   else
5385
      p_scalar_timing_check_condition();
3✔
5386
}
4✔
5387

5388
static vlog_node_t p_timing_check_event(void)
20✔
5389
{
5390
   // [ timing_check_event_control ] specify_terminal_descriptor
5391
   //    [ &&& timing_check_condition ]
5392

5393
   BEGIN("timing check event");
40✔
5394

5395
   if (scan(tEDGE, tPOSEDGE, tNEGEDGE))
20✔
5396
      p_timing_check_event_control();
4✔
5397

5398
   (void)p_specify_terminal_descriptor();
20✔
5399

5400
   if (optional(tTRPLAMP))
20✔
5401
      p_timing_check_condition();
4✔
5402

5403
   return NULL;
20✔
5404
}
5405

5406
static vlog_node_t p_controlled_timing_check_event(void)
4✔
5407
{
5408
   // timing_check_event_control specify_terminal_descriptor
5409
   //    [ &&& timing_check_condition ]
5410

5411
   BEGIN("controlled timing check event");
8✔
5412

5413
   p_timing_check_event_control();
4✔
5414

5415
   (void)p_specify_terminal_descriptor();
4✔
5416

5417
   if (optional(tTRPLAMP))
4✔
5418
      p_timing_check_condition();
×
5419

5420
   return NULL;
4✔
5421
}
5422

5423
static vlog_node_t p_setup_or_hold_timing_check(void)
6✔
5424
{
5425
   // $setup ( data_event , reference_event , timing_check_limit
5426
   //   [ , [ notifier ] ] ) ;
5427
   //
5428
   // $hold ( reference_event , data_event , timing_check_limit
5429
   //   [ , [ notifier ] ] ) ;
5430

5431
   BEGIN("setup/hold timing check");
12✔
5432

5433
   one_of(tDLRSETUP, tDLRHOLD);
6✔
5434
   consume(tLPAREN);
6✔
5435

5436
   (void)p_timing_check_event();
6✔
5437

5438
   consume(tCOMMA);
6✔
5439

5440
   (void)p_timing_check_event();
6✔
5441

5442
   consume(tCOMMA);
6✔
5443

5444
   (void)p_expression();
6✔
5445

5446
   if (optional(tCOMMA)) {
6✔
5447
      if (peek() == tID)
4✔
5448
         p_identifier();
2✔
5449
   }
5450

5451
   consume(tRPAREN);
6✔
5452
   consume(tSEMI);
6✔
5453

5454
   return NULL;
6✔
5455
}
5456

5457
static vlog_node_t p_recovery_or_removal_timing_check(void)
2✔
5458
{
5459
   // $recovery ( reference_event , data_event , timing_check_limit
5460
   //   [ , [ notifier ] ] ) ;
5461
   //
5462
   // $removal ( reference_event , data_event , timing_check_limit
5463
   //   [ , [ notifier ] ] ) ;
5464

5465
   BEGIN("recovery/removal timing check");
4✔
5466

5467
   one_of(tDLRRECOVERY, tDLRREMOVAL);
2✔
5468
   consume(tLPAREN);
2✔
5469

5470
   (void)p_timing_check_event();
2✔
5471

5472
   consume(tCOMMA);
2✔
5473

5474
   (void)p_timing_check_event();
2✔
5475

5476
   consume(tCOMMA);
2✔
5477

5478
   (void)p_expression();
2✔
5479

5480
   if (optional(tCOMMA)) {
2✔
5481
      if (peek() == tID)
×
5482
         p_identifier();
×
5483
   }
5484

5485
   consume(tRPAREN);
2✔
5486
   consume(tSEMI);
2✔
5487

5488
   return NULL;
2✔
5489
}
5490

5491
static vlog_node_t p_width_timing_check(void)
1✔
5492
{
5493
   // $width ( controlled_reference_event , timing_check_limit , threshold
5494
   //   [ , [ notifier ] ] ) ;
5495

5496
   BEGIN("width timing check");
2✔
5497

5498
   consume(tDLRWIDTH);
1✔
5499
   consume(tLPAREN);
1✔
5500

5501
   (void)p_controlled_timing_check_event();
1✔
5502

5503
   consume(tCOMMA);
1✔
5504

5505
   (void)p_expression();
1✔
5506

5507
   consume(tCOMMA);
1✔
5508

5509
   (void)p_constant_expression();
1✔
5510

5511
   if (optional(tCOMMA)) {
1✔
5512
      if (peek() == tID)
×
5513
         p_identifier();
×
5514
   }
5515

5516
   consume(tRPAREN);
1✔
5517
   consume(tSEMI);
1✔
5518

5519
   return NULL;
1✔
5520
}
5521

5522
static vlog_node_t p_delayed_data_or_reference(void)
2✔
5523
{
5524
   // terminal_identifier
5525
   //   | terminal_identifier [ constant_mintypmax_expression ]
5526

5527
   BEGIN("delayed data/reference");
4✔
5528

5529
   p_identifier();
2✔
5530

5531
   return NULL;
2✔
5532
}
5533

5534
static vlog_node_t p_period_timing_check(void)
3✔
5535
{
5536
   // $period ( controlled_reference_event , timing_check_limit
5537
   //   [ , [ notifier ] ] ) ;
5538

5539
   BEGIN("period timing check");
6✔
5540

5541
   consume(tDLRPERIOD);
3✔
5542
   consume(tLPAREN);
3✔
5543

5544
   (void)p_controlled_timing_check_event();
3✔
5545

5546
   consume(tCOMMA);
3✔
5547

5548
   (void)p_expression();
3✔
5549

5550
   if (optional(tCOMMA)) {
3✔
5551
      if (peek() == tID)
2✔
5552
         p_identifier();
1✔
5553
   }
5554

5555
   consume(tRPAREN);
3✔
5556
   consume(tSEMI);
3✔
5557

5558
   return NULL;
3✔
5559
}
5560

5561
static vlog_node_t p_setuphold_or_recrem_timing_check(void)
2✔
5562
{
5563
   // $setuphold ( reference_event , data_event , timing_check_limit ,
5564
   //    timing_check_limit [ , [ notifier ] [ , [ timestamp_condition ]
5565
   //    [ , [ timecheck_condition ] [ , [ delayed_reference ]
5566
   //    [ , [ delayed_data ] ] ] ] ] ] ) ;
5567

5568
   BEGIN("setuphold/recrem timing check");
4✔
5569

5570
   one_of(tDLRSETUPHOLD, tDLRRECREM);
2✔
5571
   consume(tLPAREN);
2✔
5572

5573
   (void)p_timing_check_event();
2✔
5574

5575
   consume(tCOMMA);
2✔
5576

5577
   (void)p_timing_check_event();
2✔
5578

5579
   consume(tCOMMA);
2✔
5580

5581
   (void)p_expression();
2✔
5582

5583
   consume(tCOMMA);
2✔
5584

5585
   (void)p_expression();
2✔
5586

5587
   if (optional(tCOMMA)) {
2✔
5588
      if (peek() == tID)
2✔
5589
         p_identifier(); // notifier
2✔
5590

5591
      if (optional(tCOMMA)) {
2✔
5592
         if (not_at_token(tCOMMA, tRPAREN))
2✔
5593
            (void)p_mintypmax_expression();  // timestamp_condition
×
5594

5595
         if (optional(tCOMMA)) {
2✔
5596
            if (not_at_token(tCOMMA, tRPAREN))
2✔
5597
               (void)p_mintypmax_expression();  // timecheck_condition
×
5598

5599
            if (optional(tCOMMA)) {
2✔
5600
               if (not_at_token(tCOMMA, tRPAREN))
2✔
5601
                  p_delayed_data_or_reference();  // delayed_reference
1✔
5602

5603
               if (optional(tCOMMA)) {
2✔
5604
                  if (not_at_token(tCOMMA, tRPAREN))
2✔
5605
                     p_delayed_data_or_reference();  // delayed_data
1✔
5606
               }
5607
            }
5608
         }
5609
      }
5610
   }
5611

5612
   consume(tRPAREN);
2✔
5613
   consume(tSEMI);
2✔
5614

5615
   return NULL;
2✔
5616
}
5617

5618
static vlog_node_t p_system_timing_check(void)
14✔
5619
{
5620
   // $setup_timing_check | $hold_timing_check | $setuphold_timing_check
5621
   //   | $recovery_timing_check | $removal_timing_check | $recrem_timing_check
5622
   //   | $skew_timing_check | $timeskew_timing_check | $fullskew_timing_check
5623
   //   | $period_timing_check | $width_timing_check | $nochange_timing_check
5624

5625
   BEGIN("system timing check");
28✔
5626

5627
   switch (peek()) {
14✔
5628
   case tDLRSETUP:
6✔
5629
   case tDLRHOLD:
5630
      return p_setup_or_hold_timing_check();
6✔
5631
   case tDLRRECOVERY:
2✔
5632
   case tDLRREMOVAL:
5633
      return p_recovery_or_removal_timing_check();
2✔
5634
   case tDLRWIDTH:
1✔
5635
      return p_width_timing_check();
1✔
5636
   case tDLRPERIOD:
3✔
5637
      return p_period_timing_check();
3✔
5638
   case tDLRSETUPHOLD:
2✔
5639
   case tDLRRECREM:
5640
      return p_setuphold_or_recrem_timing_check();
2✔
5641
   default:
×
5642
      should_not_reach_here();
5643
   }
5644
}
5645

5646
static vlog_node_t p_pulse_control_specparam(void)
1✔
5647
{
5648
   // PATHPULSE$ = (reject_limit_value [, error_limit_value])
5649
   //   | PATHPULSE$specify_input_terminal_descriptor
5650
   //       $specify_output_terminal_descriptor =
5651
   //       (reject_limit_value [, error_limit_value])
5652

5653
   BEGIN("pulse control specparam");
2✔
5654

5655
   vlog_node_t v = vlog_new(V_SPECPARAM);
1✔
5656

5657
   consume(tPATHPULSE);
1✔
5658

5659
   consume(tEQ);
1✔
5660
   consume(tLPAREN);
1✔
5661

5662
   vlog_set_value(v, p_constant_mintypmax_expression());
1✔
5663

5664
   if (optional(tCOMMA))
1✔
5665
      (void)p_constant_mintypmax_expression();
1✔
5666

5667
   consume(tRPAREN);
1✔
5668

5669
   vlog_set_loc(v, CURRENT_LOC);
1✔
5670
   return v;
1✔
5671
}
5672

5673
static vlog_node_t p_specparam_assignment(void)
4✔
5674
{
5675
   // specparam_identifier = constant_mintypmax_expression
5676
   //   | pulse_control_specparam
5677

5678
   BEGIN("specparam assignment");
8✔
5679

5680
   if (peek() == tPATHPULSE)
4✔
5681
      return p_pulse_control_specparam();
1✔
5682
   else {
5683
      vlog_node_t v = vlog_new(V_SPECPARAM);
3✔
5684
      vlog_set_ident(v, p_identifier());
3✔
5685

5686
      consume(tEQ);
3✔
5687

5688
      vlog_set_value(v, p_constant_mintypmax_expression());
3✔
5689

5690
      vlog_set_loc(v, CURRENT_LOC);
3✔
5691
      vlog_symtab_put(symtab, v);
3✔
5692
      return v;
3✔
5693
   }
5694
}
5695

5696
static void p_list_of_specparam_assignments(vlog_node_t parent)
4✔
5697
{
5698
   // specparam_assignment { , specparam_assignment }
5699

5700
   BEGIN("list of specparam assignments");
8✔
5701

5702
   do {
4✔
5703
      vlog_add_decl(parent, p_specparam_assignment());
4✔
5704
   } while (optional(tCOMMA));
4✔
5705
}
4✔
5706

5707
static void p_specparam_declaration(vlog_node_t parent)
4✔
5708
{
5709
   // specparam [ packed_dimension ] list_of_specparam_assignments ;
5710

5711
   BEGIN("specparam declaration");
8✔
5712

5713
   consume(tSPECPARAM);
4✔
5714

5715
   if (peek() == tLSQUARE)
4✔
5716
      (void)p_packed_dimension();
1✔
5717

5718
   p_list_of_specparam_assignments(parent);
4✔
5719

5720
   consume(tSEMI);
4✔
5721
}
4✔
5722

5723
static void p_specify_item(vlog_node_t parent)
36✔
5724
{
5725
   // specparam_declaration | pulsestyle_declaration | showcancelled_declaration
5726
   //   | path_declaration | system_timing_check
5727

5728
   BEGIN("specify item");
72✔
5729

5730
   switch (peek()) {
36✔
5731
   case tSPECPARAM:
4✔
5732
      p_specparam_declaration(parent);
4✔
5733
      break;
4✔
5734
   case tLPAREN:
18✔
5735
   case tIF:
5736
   case tIFNONE:
5737
      (void)p_path_declaration();
18✔
5738
      break;
18✔
5739
   case tDLRSETUP:
14✔
5740
   case tDLRHOLD:
5741
   case tDLRRECOVERY:
5742
   case tDLRREMOVAL:
5743
   case tDLRSETUPHOLD:
5744
   case tDLRRECREM:
5745
   case tDLRWIDTH:
5746
   case tDLRPERIOD:
5747
      (void)p_system_timing_check();
14✔
5748
      break;
14✔
5749
   default:
×
5750
      one_of(tSPECPARAM, tLPAREN, tIF, tIFNONE, tDLRSETUP, tDLRHOLD,
×
5751
             tDLRRECOVERY, tDLRREMOVAL, tDLRSETUPHOLD, tDLRRECREM,
5752
             tDLRWIDTH, tDLRPERIOD);
5753
   }
5754
}
36✔
5755

5756
static vlog_node_t p_specify_block(void)
3✔
5757
{
5758
   // specify { specify_item } endspecify
5759

5760
   BEGIN("specify block");
6✔
5761

5762
   consume(tSPECIFY);
3✔
5763

5764
   vlog_node_t v = vlog_new(V_SPECIFY);
3✔
5765
   vlog_set_loc(v, CURRENT_LOC);
3✔
5766

5767
   vlog_symtab_push(symtab, v);
3✔
5768

5769
   while (not_at_token(tENDSPECIFY))
39✔
5770
      p_specify_item(v);
36✔
5771

5772
   vlog_symtab_pop(symtab);
3✔
5773

5774
   consume(tENDSPECIFY);
3✔
5775

5776
   vlog_set_loc(v, CURRENT_LOC);
3✔
5777
   return v;
3✔
5778
}
5779

5780
static vlog_node_t p_ordered_port_connection(void)
247✔
5781
{
5782
   // { attribute_instance } [ expression ]
5783

5784
   BEGIN("ordered port connection");
494✔
5785

5786
   optional_attributes();
247✔
5787

5788
   vlog_node_t v = vlog_new(V_PORT_CONN);
247✔
5789

5790
   if (not_at_token(tCOMMA, tRPAREN))
247✔
5791
      vlog_set_value(v, p_expression());
247✔
5792

5793
   vlog_set_loc(v, CURRENT_LOC);
247✔
5794
   return v;
247✔
5795
}
5796

5797
static vlog_node_t p_named_port_connection(void)
159✔
5798
{
5799
   // { attribute_instance } . port_identifier [ ( [ expression ] ) ]
5800
   //    | { attribute_instance } .*
5801

5802
   BEGIN("named port connection");
318✔
5803

5804
   optional_attributes();
159✔
5805

5806
   vlog_node_t v = vlog_new(V_PORT_CONN);
159✔
5807

5808
   consume(tDOT);
159✔
5809

5810
   vlog_set_ident(v, p_identifier());
159✔
5811

5812
   if (optional(tLPAREN)) {
159✔
5813

5814
      if (peek() != tRPAREN)
159✔
5815
         vlog_set_value(v, p_expression());
157✔
5816

5817
      consume(tRPAREN);
159✔
5818
   }
5819

5820
   vlog_set_loc(v, CURRENT_LOC);
159✔
5821
   return v;
159✔
5822
}
5823

5824
static void p_list_of_port_connections(vlog_node_t inst)
180✔
5825
{
5826
   // ordered_port_connection { , ordered_port_connection }
5827
   //   | named_port_connection { , named_port_connection }
5828

5829
   BEGIN("list of port connections");
360✔
5830

5831
   vlog_symtab_set_implicit(symtab, implicit_kind);
180✔
5832

5833
   do {
406✔
5834
      skip_over_attributes();
406✔
5835

5836
      if (peek() == tDOT)
406✔
5837
         vlog_add_param(inst, p_named_port_connection());
159✔
5838
      else
5839
         vlog_add_param(inst, p_ordered_port_connection());
247✔
5840
   } while (optional(tCOMMA));
406✔
5841

5842
   vlog_symtab_set_implicit(symtab, V_NET_NONE);
180✔
5843
}
180✔
5844

5845
static vlog_node_t p_hierarchical_instance(void)
176✔
5846
{
5847
   // name_of_instance ( [ list_of_port_connections ] )
5848

5849
   BEGIN("hierarchical instance");
352✔
5850

5851
   vlog_node_t v = vlog_new(V_MOD_INST);
176✔
5852
   vlog_set_ident(v, p_identifier());
176✔
5853

5854
   consume(tLPAREN);
176✔
5855

5856
   if (peek() != tRPAREN)
176✔
5857
      p_list_of_port_connections(v);
163✔
5858

5859
   consume(tRPAREN);
176✔
5860

5861
   vlog_set_loc(v, CURRENT_LOC);
176✔
5862
   vlog_symtab_put(symtab, v);
176✔
5863
   return v;
176✔
5864
}
5865

5866
static vlog_node_t p_udp_instance(void)
17✔
5867
{
5868
   // [ name_of_instance ] ( output_terminal , input_terminal
5869
   //   { , input_terminal } )
5870

5871
   BEGIN("udp instance");
34✔
5872

5873
   vlog_node_t v = vlog_new(V_MOD_INST);
17✔
5874
   if (peek() == tID)
17✔
5875
      vlog_set_ident(v, p_identifier());
×
5876
   else
5877
      vlog_set_ident(v, ident_uniq("$unnamed"));
17✔
5878

5879
   consume(tLPAREN);
17✔
5880

5881
   p_list_of_port_connections(v);
17✔
5882

5883
   consume(tRPAREN);
17✔
5884

5885
   vlog_set_loc(v, CURRENT_LOC);
17✔
5886
   return v;
17✔
5887
}
5888

5889
static vlog_node_t p_param_expression(void)
66✔
5890
{
5891
   // mintypmax_expression | data_type | $
5892

5893
   BEGIN("param expression");
132✔
5894

5895
   return p_expression();   // TODO
66✔
5896
}
5897

5898
static vlog_node_t p_named_parameter_assignment(void)
18✔
5899
{
5900
   // . parameter_identifier ( [ param_expression ] )
5901

5902
   BEGIN("named parameter assignment");
36✔
5903

5904
   consume(tDOT);
18✔
5905

5906
   vlog_node_t v = vlog_new(V_PARAM_ASSIGN);
18✔
5907
   vlog_set_ident(v, p_identifier());
18✔
5908

5909
   consume(tLPAREN);
18✔
5910

5911
   if (peek() != tRPAREN)
18✔
5912
      vlog_set_value(v, p_param_expression());
14✔
5913

5914
   consume(tRPAREN);
18✔
5915

5916
   vlog_set_loc(v, CURRENT_LOC);
18✔
5917
   return v;
18✔
5918
}
5919

5920
static vlog_node_t p_ordered_parameter_assignment(void)
52✔
5921
{
5922
   // param_expression
5923

5924
   BEGIN("ordered parameter assignment");
104✔
5925

5926
   vlog_node_t v = vlog_new(V_PARAM_ASSIGN);
52✔
5927
   vlog_set_value(v, p_param_expression());
52✔
5928

5929
   vlog_set_loc(v, CURRENT_LOC);
52✔
5930
   return v;
52✔
5931
}
5932

5933
static void p_list_of_parameter_assignments(vlog_node_t inst)
60✔
5934
{
5935
   // ordered_parameter_assignment { , ordered_parameter_assignment }
5936
   //   | named_parameter_assignment { , named_parameter_assignment }
5937

5938
   BEGIN("list of parameter assignments");
120✔
5939

5940
   do {
70✔
5941
      if (peek() == tDOT)
70✔
5942
         vlog_add_param(inst, p_named_parameter_assignment());
18✔
5943
      else
5944
         vlog_add_param(inst, p_ordered_parameter_assignment());
52✔
5945
   } while (optional(tCOMMA));
70✔
5946
}
60✔
5947

5948
static void p_parameter_value_assignment(vlog_node_t inst)
60✔
5949
{
5950
   // # ( [ list_of_parameter_assignments ] )
5951

5952
   BEGIN("parameter value assignment");
120✔
5953

5954
   consume(tHASH);
60✔
5955
   consume(tLPAREN);
60✔
5956

5957
   if (peek() != tRPAREN)
60✔
5958
      p_list_of_parameter_assignments(inst);
60✔
5959

5960
   consume(tRPAREN);
60✔
5961
}
60✔
5962

5963
static void p_module_or_udp_instantiation(vlog_node_t mod)
187✔
5964
{
5965
   // module_identifier [ parameter_value_assignment ] hierarchical_instance
5966
   //   { , hierarchical_instance } ;
5967
   //
5968
   // udp_identifier [ drive_strength ] [ delay2 ] udp_instance
5969
   //   { , udp_instance } ;
5970

5971
   BEGIN("module instantiation");
374✔
5972

5973
   vlog_node_t v = vlog_new(V_INST_LIST);
187✔
5974
   vlog_set_ident(v, p_identifier());
187✔
5975

5976
   if (peek() == tHASH)
187✔
5977
      p_parameter_value_assignment(v);
60✔
5978

5979
   do {
193✔
5980
      if (peek() == tLPAREN)
193✔
5981
         vlog_add_stmt(v, p_udp_instance());
17✔
5982
      else
5983
         vlog_add_stmt(v, p_hierarchical_instance());
176✔
5984
   } while (optional(tCOMMA));
193✔
5985

5986
   consume(tSEMI);
187✔
5987

5988
   vlog_set_loc(v, CURRENT_LOC);
187✔
5989

5990
   vlog_add_stmt(mod, v);
187✔
5991
}
187✔
5992

5993
static vlog_node_t p_defparam_assignment(void)
3✔
5994
{
5995
   // hierarchical_parameter_identifier = constant_mintypmax_expression
5996

5997
   BEGIN("defparam assignment");
6✔
5998

5999
   vlog_node_t v = vlog_new(V_DEFPARAM);
3✔
6000
   vlog_set_target(v, p_hierarchical_identifier(NULL));
3✔
6001

6002
   consume(tEQ);
3✔
6003

6004
   vlog_set_value(v, p_constant_mintypmax_expression());
3✔
6005

6006
   vlog_set_loc(v, CURRENT_LOC);
3✔
6007
   return v;
3✔
6008
}
6009

6010
static void p_list_of_defparam_assignments(vlog_node_t parent)
3✔
6011
{
6012
   // defparam_assignment { , defparam_assignment }
6013

6014
   BEGIN("list of defparam assignments");
6✔
6015

6016
   do {
3✔
6017
      vlog_add_stmt(parent, p_defparam_assignment());
3✔
6018
   } while (optional(tCOMMA));
3✔
6019
}
3✔
6020

6021
static void p_parameter_override(vlog_node_t parent)
3✔
6022
{
6023
   // defparam list_of_defparam_assignments ;
6024

6025
   BEGIN("parameter override");
6✔
6026

6027
   consume(tDEFPARAM);
3✔
6028

6029
   p_list_of_defparam_assignments(parent);
3✔
6030

6031
   consume(tSEMI);
3✔
6032
}
3✔
6033

6034
static void p_module_or_generate_item(vlog_node_t mod)
7,066✔
6035
{
6036
   // { attribute_instance } parameter_override
6037
   //   | { attribute_instance } gate_instantiation
6038
   //   | { attribute_instance } udp_instantiation
6039
   //   | { attribute_instance } module_instantiation
6040
   //   | { attribute_instance } module_common_item
6041

6042
   BEGIN("module or generate item");
14,132✔
6043

6044
   optional_attributes();
7,066✔
6045

6046
   switch (peek()) {
7,066✔
6047
   case tALWAYS:
6,772✔
6048
   case tALWAYSCOMB:
6049
   case tALWAYSFF:
6050
   case tALWAYSLATCH:
6051
   case tWIRE:
6052
   case tUWIRE:
6053
   case tSUPPLY0:
6054
   case tSUPPLY1:
6055
   case tTRI:
6056
   case tTRI0:
6057
   case tTRI1:
6058
   case tTRIAND:
6059
   case tTRIOR:
6060
   case tTRIREG:
6061
   case tWAND:
6062
   case tWOR:
6063
   case tINTERCONNECT:
6064
   case tREG:
6065
   case tSTRUCT:
6066
   case tUNION:
6067
   case tASSIGN:
6068
   case tINITIAL:
6069
   case tTYPEDEF:
6070
   case tENUM:
6071
   case tSVINT:
6072
   case tINTEGER:
6073
   case tSVREAL:
6074
   case tSHORTREAL:
6075
   case tREALTIME:
6076
   case tTIME:
6077
   case tTASK:
6078
   case tFUNCTION:
6079
   case tLOCALPARAM:
6080
   case tPARAMETER:
6081
   case tIF:
6082
   case tCASE:
6083
   case tFOR:
6084
   case tEVENT:
6085
   case tGENVAR:
6086
   case tVAR:
6087
   case tLOGIC:
6088
   case tBIT:
6089
   case tSHORTINT:
6090
   case tLONGINT:
6091
   case tBYTE:
6092
   case tSTRINGK:
6093
   case tIMPORT:
6094
   case tFINAL:
6095
      p_module_common_item(mod);
6,772✔
6096
      break;
6,772✔
6097
   case tPULLDOWN:
80✔
6098
   case tPULLUP:
6099
   case tAND:
6100
   case tNAND:
6101
   case tOR:
6102
   case tNOR:
6103
   case tXOR:
6104
   case tXNOR:
6105
   case tNOT:
6106
   case tBUF:
6107
   case tBUFIF0:
6108
   case tBUFIF1:
6109
   case tNOTIF0:
6110
   case tNOTIF1:
6111
   case tTRAN:
6112
   case tTRANIF0:
6113
   case tTRANIF1:
6114
   case tRTRAN:
6115
   case tRTRANIF0:
6116
   case tRTRANIF1:
6117
      p_gate_instantiation(mod);
80✔
6118
      break;
80✔
6119
   case tDEFPARAM:
3✔
6120
      p_parameter_override(mod);
3✔
6121
      break;
3✔
6122
   case tID:
211✔
6123
      {
6124
         vlog_node_t ref = peek_reference();
211✔
6125
         if (ref == NULL)
211✔
6126
            p_module_or_udp_instantiation(mod);
187✔
6127
         else
6128
            p_module_common_item(mod);
24✔
6129
      }
6130
      break;
6131
   default:
×
6132
      expect(tALWAYS, tALWAYSCOMB, tALWAYSFF, tALWAYSLATCH, tWIRE, tUWIRE,
×
6133
             tSUPPLY0, tSUPPLY1, tTRI,  tTRI0, tTRI1, tTRIAND, tTRIOR, tTRIREG,
6134
             tWAND, tWOR, tINTERCONNECT, tREG, tSTRUCT, tUNION, tASSIGN,
6135
             tINITIAL, tTYPEDEF, tENUM, tSVINT, tINTEGER, tSVREAL, tSHORTREAL,
6136
             tREALTIME, tTIME, tTASK, tFUNCTION, tLOCALPARAM, tPARAMETER, tIF,
6137
             tFOR, tEVENT, tGENVAR, tVAR, tLOGIC, tBIT, tSHORTINT, tLONGINT,
6138
             tBYTE, tSTRINGK, tIMPORT, tFINAL, tPULLDOWN, tPULLUP, tID, tAND,
6139
             tNAND, tOR, tNOR, tXOR, tXNOR, tNOT, tBUF, tBUFIF0, tBUFIF1,
6140
             tNOTIF0, tNOTIF1, tDEFPARAM, tID);
6141
      drop_tokens_until(&state, tSEMI);
×
6142
   }
6143
}
7,066✔
6144

6145
static void p_generate_region(vlog_node_t mod)
20✔
6146
{
6147
   // generate { generate_item } endgenerate
6148

6149
   BEGIN("generate region");
40✔
6150

6151
   // Has no real meaning in System Verilog
6152

6153
   // TODO: generate regions do not nest so check mod is V_MODULE
6154

6155
   consume(tGENERATE);
20✔
6156

6157
   if (optional(tBEGIN)) {
20✔
6158
      // This is non-standard but seen in some legacy code
6159
      consume(tCOLON);
1✔
6160

6161
      vlog_node_t b = vlog_new(V_BLOCK);
1✔
6162
      vlog_set_ident(b, p_identifier());
1✔
6163

6164
      while (not_at_token(tEND))
1✔
6165
         p_generate_item(b);
×
6166

6167
      consume(tEND);
1✔
6168

6169
      vlog_set_loc(b, CURRENT_LOC);
1✔
6170
      vlog_add_stmt(mod, b);
1✔
6171
   }
6172
   else {
6173
      while (not_at_token(tENDGENERATE))
38✔
6174
         p_generate_item(mod);
19✔
6175
   }
6176

6177
   consume(tENDGENERATE);
20✔
6178
}
20✔
6179

6180
static void p_non_port_module_item(vlog_node_t mod)
6,957✔
6181
{
6182
   // generate_region | module_or_generate_item | specify_block
6183
   //   | { attribute_instance } specparam_declaration | program_declaration
6184
   //   | module_declaration | interface_declaration | timeunits_declaration
6185

6186
   BEGIN("non-port module item");
13,914✔
6187

6188
   switch (peek()) {
6,957✔
6189
   case tALWAYS:
6,932✔
6190
   case tALWAYSCOMB:
6191
   case tALWAYSFF:
6192
   case tALWAYSLATCH:
6193
   case tWIRE:
6194
   case tUWIRE:
6195
   case tSUPPLY0:
6196
   case tSUPPLY1:
6197
   case tTRI:
6198
   case tTRI0:
6199
   case tTRI1:
6200
   case tTRIAND:
6201
   case tTRIOR:
6202
   case tTRIREG:
6203
   case tWAND:
6204
   case tWOR:
6205
   case tINTERCONNECT:
6206
   case tREG:
6207
   case tSTRUCT:
6208
   case tUNION:
6209
   case tASSIGN:
6210
   case tINITIAL:
6211
   case tPULLDOWN:
6212
   case tPULLUP:
6213
   case tID:
6214
   case tATTRBEGIN:
6215
   case tAND:
6216
   case tNAND:
6217
   case tOR:
6218
   case tNOR:
6219
   case tXOR:
6220
   case tXNOR:
6221
   case tNOT:
6222
   case tBUF:
6223
   case tBUFIF0:
6224
   case tBUFIF1:
6225
   case tNOTIF0:
6226
   case tNOTIF1:
6227
   case tTRAN:
6228
   case tTRANIF0:
6229
   case tTRANIF1:
6230
   case tRTRAN:
6231
   case tRTRANIF0:
6232
   case tRTRANIF1:
6233
   case tTYPEDEF:
6234
   case tENUM:
6235
   case tSVINT:
6236
   case tINTEGER:
6237
   case tSVREAL:
6238
   case tSHORTREAL:
6239
   case tREALTIME:
6240
   case tTIME:
6241
   case tTASK:
6242
   case tFUNCTION:
6243
   case tLOCALPARAM:
6244
   case tPARAMETER:
6245
   case tEVENT:
6246
   case tIF:
6247
   case tFOR:
6248
   case tGENVAR:
6249
   case tVAR:
6250
   case tLOGIC:
6251
   case tBIT:
6252
   case tSHORTINT:
6253
   case tLONGINT:
6254
   case tBYTE:
6255
   case tSTRINGK:
6256
   case tIMPORT:
6257
   case tDEFPARAM:
6258
   case tFINAL:
6259
      p_module_or_generate_item(mod);
6,932✔
6260
      break;
6,932✔
6261
   case tSPECIFY:
3✔
6262
      vlog_add_stmt(mod, p_specify_block());
3✔
6263
      break;
3✔
6264
   case tGENERATE:
20✔
6265
      p_generate_region(mod);
20✔
6266
      break;
20✔
6267
   default:
2✔
6268
      one_of(tALWAYS, tALWAYSCOMB, tALWAYSFF, tALWAYSLATCH, tWIRE, tUWIRE,
2✔
6269
             tSUPPLY0, tSUPPLY1, tTRI, tTRI0, tTRI1, tTRIAND, tTRIOR, tTRIREG,
6270
             tWAND, tWOR, tINTERCONNECT, tREG, tSTRUCT, tUNION, tASSIGN,
6271
             tPULLDOWN, tPULLUP, tID, tATTRBEGIN, tAND, tNAND, tOR, tNOR, tXOR,
6272
             tXNOR, tNOT, tBUF, tBUFIF0, tBUFIF1, tNOTIF0, tNOTIF1, tTYPEDEF,
6273
             tENUM, tSVINT, tINTEGER, tSVREAL, tSHORTREAL, tREALTIME, tTIME,
6274
             tTASK, tFUNCTION, tLOCALPARAM, tPARAMETER, tEVENT, tIF, tFOR,
6275
             tGENVAR, tVAR, tLOGIC, tBIT, tSHORTINT, tLONGINT, tBYTE, tSTRINGK,
6276
             tIMPORT, tDEFPARAM, tFINAL, tSPECIFY, tGENERATE);
6277
      drop_tokens_until(&state, tSEMI);
2✔
6278
   }
6279
}
6,957✔
6280

6281
static void p_module_item(vlog_node_t mod)
7,389✔
6282
{
6283
   // port_declaration ; | non_port_module_item
6284

6285
   BEGIN("module item");
14,778✔
6286

6287
   skip_over_attributes();
7,389✔
6288

6289
   if (scan(tINOUT, tINPUT, tOUTPUT)) {
7,389✔
6290
      p_port_declaration(mod);
432✔
6291
      consume(tSEMI);
432✔
6292
   }
6293
   else
6294
      p_non_port_module_item(mod);
6,957✔
6295
}
7,389✔
6296

6297
static void p_ansi_port_declaration(vlog_node_t mod, v_port_kind_t *kind,
155✔
6298
                                    vlog_node_t *dt)
6299
{
6300
   // [ net_port_header | interface_port_header ] port_identifier
6301
   //     { unpacked_dimension } [ = constant_expression ]
6302
   // | [ variable_port_header ] port_identifier { variable_dimension }
6303
   //     [ = constant_expression ]
6304
   // | [ port_direction ] . port_identifier ( [ expression ] )
6305

6306
   BEGIN("ANSI port declaration");
310✔
6307

6308
   if (peek() != tID)
155✔
6309
      p_net_port_header(kind, dt);
133✔
6310
   else if (*dt == NULL)
22✔
6311
      *dt = implicit_type();
×
6312

6313
   ident_t id, ext;
155✔
6314
   p_external_identifier(&id, &ext);
155✔
6315

6316
   vlog_node_t v = vlog_new(V_PORT_DECL);
155✔
6317
   vlog_set_subkind(v, *kind);
155✔
6318
   vlog_set_ident(v, id);
155✔
6319
   vlog_set_ident2(v, ext);
155✔
6320
   vlog_set_type(v, *dt);
155✔
6321
   vlog_set_loc(v, &state.last_loc);
155✔
6322

6323
   if (optional(tEQ))
155✔
6324
      vlog_set_value(v, p_constant_expression());
9✔
6325

6326
   vlog_add_decl(mod, v);
155✔
6327
   vlog_symtab_put(symtab, v);
155✔
6328

6329
   vlog_node_t ref = vlog_new(V_REF);
155✔
6330
   vlog_set_loc(ref, CURRENT_LOC);
155✔
6331
   vlog_set_ident(ref, id);
155✔
6332
   vlog_set_ref(ref, v);
155✔
6333

6334
   vlog_add_port(mod, ref);
155✔
6335
}
155✔
6336

6337
static void p_list_of_port_declarations(vlog_node_t mod)
146✔
6338
{
6339
   // ( [ { attribute_instance } ansi_port_declaration
6340
   //   { , { attribute_instance } ansi_port_declaration } ] )
6341

6342
   BEGIN("list of port declarations");
292✔
6343

6344
   consume(tLPAREN);
146✔
6345

6346
   if (peek() != tRPAREN) {
146✔
6347
      v_port_kind_t kind = V_PORT_INPUT;
62✔
6348
      vlog_node_t dt = NULL;
62✔
6349
      do {
155✔
6350
         optional_attributes();
155✔
6351
         p_ansi_port_declaration(mod, &kind, &dt);
155✔
6352
      } while (optional(tCOMMA));
155✔
6353
   }
6354

6355
   consume(tRPAREN);
146✔
6356
}
146✔
6357

6358
static void p_parameter_port_declaration(vlog_node_t mod)
53✔
6359
{
6360
   // parameter_declaration
6361
   //    | local_parameter_declaration
6362
   //    | data_type list_of_param_assignments
6363
   //    | type list_of_type_assignments
6364

6365
   BEGIN("parameter port declaration");
106✔
6366

6367
   switch (peek()) {
53✔
6368
   case tPARAMETER:
47✔
6369
      p_parameter_declaration(mod);
47✔
6370
      break;
47✔
6371
   case tLOCALPARAM:
5✔
6372
      p_local_parameter_declaration(mod);
5✔
6373
      break;
5✔
6374
   default:
1✔
6375
      // TODO: Add parsing of "type" declarations example #(type T = bit)
6376
      {
6377
         vlog_node_t datatype = p_data_type();
1✔
6378
         p_list_of_param_assignments(mod, datatype, V_PARAM_DECL);
1✔
6379
      }
6380
      break;
1✔
6381
   }
6382
}
53✔
6383

6384
static void p_parameter_port_list(vlog_node_t mod)
27✔
6385
{
6386
   // # ( list_of_param_assignments { , parameter_port_declaration } )
6387
   //    | # ( parameter_port_declaration { , parameter_port_declaration } )
6388
   //    | # ( )
6389

6390
   BEGIN("parameter port list");
54✔
6391

6392
   consume(tHASH);
27✔
6393
   consume(tLPAREN);
27✔
6394

6395
   if (peek() != tRPAREN) {
27✔
6396
      do {
54✔
6397
         if (peek() == tID)
54✔
6398
            p_list_of_param_assignments(mod, implicit_type(), V_PARAM_DECL);
1✔
6399
         else
6400
            p_parameter_port_declaration(mod);
53✔
6401
      } while(optional(tCOMMA));
54✔
6402
   }
6403

6404
   consume(tRPAREN);
27✔
6405
}
27✔
6406

6407
static void p_module_ansi_header(vlog_node_t mod)
787✔
6408
{
6409
   // { attribute_instance } module_keyword [ lifetime ] module_identifier
6410
   //    { package_import_declaration } [ parameter_port_list ]
6411
   ///   [ list_of_port_declarations ] ;
6412

6413
   EXTEND("module ANSI header");
1,574✔
6414

6415
   if (peek() == tLPAREN)
787✔
6416
      p_list_of_port_declarations(mod);
146✔
6417

6418
   consume(tSEMI);
787✔
6419

6420
   vlog_set_loc(mod, CURRENT_LOC);
787✔
6421
}
787✔
6422

6423
static vlog_node_t p_port_reference(void)
458✔
6424
{
6425
   // port_identifier constant_select
6426

6427
   BEGIN("port reference");
916✔
6428

6429
   vlog_node_t v = vlog_new(V_REF);
458✔
6430
   vlog_set_ident(v, p_identifier());
458✔
6431
   vlog_set_loc(v, CURRENT_LOC);
458✔
6432
   return v;
458✔
6433
}
6434

6435
static vlog_node_t p_port_expression(void)
458✔
6436
{
6437
   // port_reference | { port_reference { , port_reference } }
6438

6439
   BEGIN("port expression");
916✔
6440

6441
   return p_port_reference();
458✔
6442
}
6443

6444
static vlog_node_t p_port(void)
458✔
6445
{
6446
   // [ port_expression ] | . port_identifier ( [ port_expression ] )
6447

6448
   BEGIN("port");
916✔
6449

6450
   return p_port_expression();
458✔
6451
}
6452

6453
static void p_list_of_ports(vlog_node_t mod)
152✔
6454
{
6455
   // ( port { , port } )
6456

6457
   BEGIN("list of ports");
304✔
6458

6459
   consume(tLPAREN);
152✔
6460

6461
   do {
458✔
6462
      vlog_add_port(mod, p_port());
458✔
6463
   } while (optional(tCOMMA));
458✔
6464

6465
   consume(tRPAREN);
152✔
6466
}
152✔
6467

6468
static void p_module_nonansi_header(vlog_node_t mod)
152✔
6469
{
6470
   // { attribute_instance } module_keyword [ lifetime ] module_identifier
6471
   //    { package_import_declaration } [ parameter_port_list ] list_of_ports ;
6472

6473
   EXTEND("module non-ANSI header");
304✔
6474

6475
   p_list_of_ports(mod);
152✔
6476

6477
   consume(tSEMI);
152✔
6478

6479
   vlog_set_loc(mod, CURRENT_LOC);
152✔
6480
}
152✔
6481

6482
static vlog_node_t p_module_declaration(void)
939✔
6483
{
6484
   // module_nonansi_header [ timeunits_declaration ] { module_item }
6485
   //      endmodule [ : module_identifier ]
6486
   //   | module_ansi_header [ timeunits_declaration ] { non_port_module_item }
6487
   //      endmodule [ : module_identifier ]
6488
   //   | { attribute_instance } module_keyword [ lifetime ] module_identifier
6489
   //      ( .* ) ; [ timeunits_declaration ] { module_item } endmodule
6490
   //      [ : module_identifier ]
6491
   //   | extern module_nonansi_header
6492
   //   | extern module_ansi_header
6493

6494
   BEGIN("module declaration");
1,878✔
6495

6496
   vlog_node_t mod = vlog_new(V_MODULE);
939✔
6497

6498
   optional_attributes();
939✔
6499

6500
   consume(tMODULE);
939✔
6501

6502
   ident_t id, ext;
939✔
6503
   p_external_identifier(&id, &ext);
939✔
6504
   vlog_set_ident2(mod, id);
939✔
6505

6506
   vlog_set_loc(mod, &state.last_loc);
939✔
6507

6508
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
939✔
6509
   vlog_set_ident(mod, qual);
939✔
6510

6511
   vlog_symtab_push(symtab, mod);
939✔
6512

6513
   while (peek() == tIMPORT)
939✔
6514
      p_package_import_declaration(mod);
×
6515

6516
   if (peek() == tHASH) {
939✔
6517
      p_parameter_port_list(mod);
27✔
6518
      param_kind = V_LOCALPARAM;
27✔
6519
   }
6520

6521
   if (peek() == tLPAREN && peek_nth(2) == tID)
939✔
6522
      p_module_nonansi_header(mod);
152✔
6523
   else
6524
      p_module_ansi_header(mod);
787✔
6525

6526
   while (not_at_token(tENDMODULE))
8,328✔
6527
      p_module_item(mod);
7,389✔
6528

6529
   consume(tENDMODULE);
939✔
6530

6531
   if (optional(tCOLON)) {
939✔
6532
      ident_t name = p_identifier();
2✔
6533
      if (id != name)
2✔
6534
         error_at(&state.last_loc, "'%s' does not match module name '%s'",
1✔
6535
                  istr(name), istr(id));
6536
   }
6537

6538
   vlog_symtab_pop(symtab);
939✔
6539
   return mod;
939✔
6540
}
6541

6542
static void p_udp_port_list(vlog_node_t udp)
26✔
6543
{
6544
   // output_port_identifier , input_port_identifier { , input_port_identifier }
6545

6546
   BEGIN("UDP port list");
52✔
6547

6548
   vlog_node_t oref = vlog_new(V_REF);
26✔
6549
   vlog_set_ident(oref, p_identifier());
26✔
6550
   vlog_set_loc(oref, &state.last_loc);
26✔
6551

6552
   vlog_add_port(udp, oref);
26✔
6553

6554
   consume(tCOMMA);
26✔
6555

6556
   vlog_node_t iref = vlog_new(V_REF);
26✔
6557
   vlog_set_ident(iref, p_identifier());
26✔
6558
   vlog_set_loc(iref, &state.last_loc);
26✔
6559

6560
   vlog_add_port(udp, iref);
26✔
6561

6562
   while (optional(tCOMMA)) {
54✔
6563
      vlog_node_t iref = vlog_new(V_REF);
28✔
6564
      vlog_set_ident(iref, p_identifier());
28✔
6565
      vlog_set_loc(iref, &state.last_loc);
28✔
6566

6567
      vlog_add_port(udp, iref);
28✔
6568
   }
6569
}
26✔
6570

6571
static vlog_node_t p_udp_nonansi_declaration(void)
26✔
6572
{
6573
   // { attribute_instance } primitive udp_identifier ( udp_port_list ) ;
6574

6575
   BEGIN("UDP non-ANSI declaration");
52✔
6576

6577
   vlog_node_t udp = vlog_new(V_PRIMITIVE);
26✔
6578

6579
   consume(tPRIMITIVE);
26✔
6580

6581
   ident_t id, ext;
26✔
6582
   p_external_identifier(&id, &ext);
26✔
6583
   vlog_set_ident2(udp, id);
26✔
6584

6585
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
26✔
6586
   vlog_set_ident(udp, qual);
26✔
6587

6588
   consume(tLPAREN);
26✔
6589

6590
   p_udp_port_list(udp);
26✔
6591

6592
   consume(tRPAREN);
26✔
6593
   consume(tSEMI);
26✔
6594

6595
   vlog_set_loc(udp, CURRENT_LOC);
26✔
6596
   return udp;
26✔
6597
}
6598

6599
static void p_list_of_udp_port_identifiers(vlog_node_t udp, v_port_kind_t kind)
27✔
6600
{
6601
   // port_identifier { , port_identifier }
6602

6603
   BEGIN("list of UDP port identifiers");
54✔
6604

6605
   do {
54✔
6606
      ident_t id, ext;
54✔
6607
      p_external_identifier(&id, &ext);
54✔
6608

6609
      vlog_node_t p = vlog_new(V_PORT_DECL);
54✔
6610
      vlog_set_subkind(p, kind);
54✔
6611
      vlog_set_ident(p, id);
54✔
6612
      vlog_set_ident2(p, ext);
54✔
6613
      vlog_set_type(p, implicit_type());
54✔
6614
      vlog_set_loc(p, &state.last_loc);
54✔
6615

6616
      vlog_add_decl(udp, p);
54✔
6617
      vlog_symtab_put(symtab, p);
54✔
6618
   } while (optional(tCOMMA));
54✔
6619
}
27✔
6620

6621
static void p_udp_output_declaration(vlog_node_t udp, bool *has_reg)
27✔
6622
{
6623
   // { attribute_instance } output port_identifier
6624
   //    | { attribute_instance } output reg port_identifier
6625
   //         [ = constant_expression ]
6626

6627
   BEGIN("UDP output declaration");
54✔
6628

6629
   consume(tOUTPUT);
27✔
6630

6631
   const bool isreg = optional(tREG);
27✔
6632

6633
   ident_t id, ext;
27✔
6634
   p_external_identifier(&id, &ext);
27✔
6635

6636
   vlog_node_t v = vlog_new(V_PORT_DECL);
27✔
6637
   vlog_set_subkind(v, V_PORT_OUTPUT);
27✔
6638
   vlog_set_ident(v, id);
27✔
6639
   vlog_set_ident2(v, ext);
27✔
6640
   vlog_set_loc(v, &state.last_loc);
27✔
6641

6642
   if (isreg) {
27✔
6643
      vlog_set_type(v, logic_type());
2✔
6644
      *has_reg = true;
2✔
6645
   }
6646
   else
6647
      vlog_set_type(v, implicit_type());
25✔
6648

6649
   vlog_add_decl(udp, v);
27✔
6650
   vlog_symtab_put(symtab, v);
27✔
6651
}
27✔
6652

6653
static void p_udp_input_declaration(vlog_node_t udp)
27✔
6654
{
6655
   // { attribute_instance } input list_of_udp_port_identifiers
6656

6657
   BEGIN("UDP input declaration");
54✔
6658

6659
   consume(tINPUT);
27✔
6660

6661
   p_list_of_udp_port_identifiers(udp, V_PORT_INPUT);
27✔
6662
}
27✔
6663

6664
static vlog_node_t p_udp_reg_declaration(void)
13✔
6665
{
6666
   // { attribute_instance } reg variable_identifier
6667

6668
   BEGIN("UDP reg declaration");
26✔
6669

6670
   consume(tREG);
13✔
6671

6672
   ident_t id = p_identifier();
13✔
6673

6674
   vlog_node_t reg = vlog_new(V_VAR_DECL);
13✔
6675
   vlog_set_loc(reg, &state.last_loc);
13✔
6676
   vlog_set_ident(reg, id);
13✔
6677
   vlog_set_type(reg, logic_type());
13✔
6678

6679
   return reg;
13✔
6680
}
6681

6682
static void p_udp_port_declaration(vlog_node_t udp, bool *has_reg)
65✔
6683
{
6684
   // udp_output_declaration ; | udp_input_declaration ; | udp_reg_declaration ;
6685

6686
   BEGIN("UDP port declaration");
130✔
6687

6688
   switch (peek()) {
65✔
6689
   case tOUTPUT:
26✔
6690
      p_udp_output_declaration(udp, has_reg);
26✔
6691
      break;
26✔
6692
   case tINPUT:
26✔
6693
      p_udp_input_declaration(udp);
26✔
6694
      break;
26✔
6695
   case tREG:
13✔
6696
      {
6697
         vlog_node_t v = p_udp_reg_declaration();
13✔
6698
         vlog_add_decl(udp, v);
13✔
6699
         vlog_symtab_put(symtab, v);
13✔
6700
         *has_reg = true;
13✔
6701
      }
6702
      break;
13✔
6703
   default:
×
6704
      one_of(tOUTPUT, tINPUT, tREG);
×
6705
      break;
×
6706
   }
6707

6708
   consume(tSEMI);
65✔
6709
}
65✔
6710

6711
static void p_udp_declaration_port_list(vlog_node_t udp, bool *has_reg)
1✔
6712
{
6713
   // udp_output_declaration , udp_input_declaration { , udp_input_declaration }
6714

6715
   BEGIN("UDP declaration port list");
2✔
6716

6717
   p_udp_output_declaration(udp, has_reg);
1✔
6718

6719
   consume(tCOMMA);
1✔
6720

6721
   do {
1✔
6722
      p_udp_input_declaration(udp);
1✔
6723
   } while (optional(tCOMMA));
1✔
6724

6725
   const int ndecls = vlog_decls(udp);
1✔
6726
   for (int i = 0; i < ndecls; i++) {
3✔
6727
      vlog_node_t p = vlog_decl(udp, i);
2✔
6728
      if (vlog_kind(p) != V_PORT_DECL)
2✔
6729
         continue;
×
6730

6731
      vlog_node_t ref = vlog_new(V_REF);
2✔
6732
      vlog_set_loc(ref, vlog_loc(p));
2✔
6733
      vlog_set_ident(ref, vlog_ident(p));
2✔
6734
      vlog_set_ref(ref, p);
2✔
6735

6736
      vlog_add_port(udp, ref);
2✔
6737
   }
6738
}
1✔
6739

6740
static vlog_node_t p_output_symbol(void)
105✔
6741
{
6742
   // 0 | 1 | x | X
6743

6744
   BEGIN("output symbol");
210✔
6745

6746
   vlog_node_t v = vlog_new(V_UDP_LEVEL);
105✔
6747
   vlog_set_subkind(v, V_UDP_SYMBOL_OUTPUT);
105✔
6748

6749
   if (consume(tUDPLEVEL)) {
105✔
6750
      switch (state.last_lval.i64) {
105✔
6751
      case '0':
105✔
6752
      case '1':
6753
      case 'x':
6754
      case 'X':
6755
         vlog_set_ival(v, state.last_lval.i64);
105✔
6756
         break;
105✔
6757
      default:
×
6758
         parse_error(&state.last_loc, "'%c' is not a valid output symbol",
×
6759
                     (char)state.last_lval.i64);
6760
         break;
6761
      }
6762
   }
6763

6764
   vlog_set_loc(v, CURRENT_LOC);
105✔
6765
   return v;
105✔
6766
}
6767

6768
static vlog_node_t p_level_symbol(void)
437✔
6769
{
6770
   // 0 | 1 | x | X | ? | b | B
6771

6772
   BEGIN("level symbol");
874✔
6773

6774
   consume(tUDPLEVEL);
437✔
6775

6776
   vlog_node_t v = vlog_new(V_UDP_LEVEL);
437✔
6777
   vlog_set_subkind(v, V_UDP_SYMBOL_INPUT);
437✔
6778
   vlog_set_ival(v, state.last_lval.i64);
437✔
6779

6780
   vlog_set_loc(v, CURRENT_LOC);
437✔
6781
   return v;
437✔
6782
}
6783

6784
static vlog_node_t p_next_state(void)
101✔
6785
{
6786
   // output_symbol | -
6787

6788
   BEGIN("next state");
202✔
6789

6790
   switch (peek()) {
101✔
6791
   case tMINUS:
35✔
6792
      consume(tMINUS);
35✔
6793
      break;
35✔
6794
   case tUDPLEVEL:
66✔
6795
      return p_output_symbol();
66✔
6796
   default:
×
6797
      one_of(tUDPLEVEL, tMINUS);
×
6798
   }
6799

6800
   vlog_node_t v = vlog_new(V_UDP_LEVEL);
35✔
6801
   vlog_set_subkind(v, V_UDP_SYMBOL_OUTPUT);
35✔
6802
   vlog_set_ival(v, '-');
35✔
6803

6804
   vlog_set_loc(v, CURRENT_LOC);
35✔
6805
   return v;
35✔
6806
}
6807

6808
static vlog_node_t p_edge_symbol(void)
28✔
6809
{
6810
   // r | R | f | F | p | P | n | N | *
6811

6812
   BEGIN("edge symbol");
56✔
6813

6814
   consume(tUDPEDGE);
28✔
6815

6816
   char left, right;
28✔
6817
   switch (state.last_lval.i64) {
28✔
6818
   case 'r': case 'R': left = '0'; right = '1'; break;
6819
   case 'f': case 'F': left = '1'; right = '0'; break;
×
6820
   case 'p': case 'P': left = '?'; right = '1'; break;
8✔
6821
   case 'n': case 'N': left = '?'; right = '0'; break;
4✔
6822
   case '*':           left = '?'; right = '?'; break;
13✔
6823
   default: should_not_reach_here();
6824
   }
6825

6826
   vlog_node_t lsym = vlog_new(V_UDP_LEVEL);
28✔
6827
   vlog_set_ival(lsym, left);
28✔
6828

6829
   vlog_node_t rsym = vlog_new(V_UDP_LEVEL);
28✔
6830
   vlog_set_ival(rsym, right);
28✔
6831

6832
   vlog_node_t v = vlog_new(V_UDP_EDGE);
28✔
6833
   vlog_set_subkind(v, V_UDP_SYMBOL_INPUT);
28✔
6834
   vlog_set_left(v, lsym);
28✔
6835
   vlog_set_right(v, rsym);
28✔
6836

6837
   vlog_set_loc(v, CURRENT_LOC);
28✔
6838
   return v;
28✔
6839
}
6840

6841
static void p_level_input_list(vlog_node_t entry)
39✔
6842
{
6843
   // level_symbol { level_symbol }
6844

6845
   BEGIN("level input list");
78✔
6846

6847
   do {
90✔
6848
      vlog_add_param(entry, p_level_symbol());
90✔
6849
   } while (not_at_token(tCOLON));
90✔
6850
}
39✔
6851

6852
static vlog_node_t p_edge_indicator(void)
101✔
6853
{
6854
   // ( level_symbol level_symbol ) | edge_symbol
6855

6856
   BEGIN("edge indicator");
202✔
6857

6858
   switch (peek()) {
101✔
6859
   case tUDPEDGE:
28✔
6860
      return p_edge_symbol();
28✔
6861
   case tLPAREN:
73✔
6862
      {
6863
         consume(tLPAREN);
73✔
6864

6865
         vlog_node_t v = vlog_new(V_UDP_EDGE);
73✔
6866
         vlog_set_left(v, p_level_symbol());
73✔
6867
         vlog_set_right(v, p_level_symbol());
73✔
6868

6869
         consume(tRPAREN);
73✔
6870

6871
         vlog_set_loc(v, CURRENT_LOC);
73✔
6872
         return v;
73✔
6873
      }
6874
      break;
×
6875
   default:
×
6876
      should_not_reach_here();
6877
   }
6878
}
6879

6880
static void p_seq_input_list(vlog_node_t entry)
101✔
6881
{
6882
   // level_input_list | edge_input_list
6883

6884
   BEGIN("sequential input list");
202✔
6885

6886
   bool have_edge = false;
101✔
6887
   do {
201✔
6888
      switch (peek()) {
201✔
6889
      case tUDPEDGE:
101✔
6890
      case tLPAREN:
6891
         vlog_add_param(entry, p_edge_indicator());
101✔
6892
         if (have_edge)
101✔
6893
            parse_error(&state.last_loc, "a sequential input list may have at "
1✔
6894
                        "most one edge indicator");
6895
         have_edge = true;
6896
         break;
6897

6898
      case tUDPLEVEL:
100✔
6899
         vlog_add_param(entry, p_level_symbol());
100✔
6900
         break;
100✔
6901

6902
      default:
×
6903
         one_of(tUDPEDGE, tUDPIND, tUDPLEVEL);
×
6904
         break;
×
6905
      }
6906
   } while (not_at_token(tCOLON));
201✔
6907
}
101✔
6908

6909
static vlog_node_t p_combinational_entry(void)
39✔
6910
{
6911
   // level_input_list : output_symbol ;
6912

6913
   BEGIN("combinational entry");
78✔
6914

6915
   vlog_node_t v = vlog_new(V_UDP_ENTRY);
39✔
6916
   p_level_input_list(v);
39✔
6917

6918
   consume(tCOLON);
39✔
6919

6920
   vlog_add_param(v, p_output_symbol());
39✔
6921

6922
   consume(tSEMI);
39✔
6923

6924
   vlog_set_loc(v, CURRENT_LOC);
39✔
6925
   return v;
39✔
6926
}
6927

6928
static vlog_node_t p_combinational_body(void)
12✔
6929
{
6930
   // table combinational_entry { combinational_entry } endtable
6931

6932
   BEGIN("combinational UDP body");
24✔
6933

6934
   consume(tTABLE);
12✔
6935

6936
   scan_as_udp();
12✔
6937

6938
   vlog_node_t v = vlog_new(V_UDP_TABLE);
12✔
6939
   vlog_set_subkind(v, V_UDP_COMB);
12✔
6940
   vlog_set_ident(v, ident_new("combinational"));
12✔
6941

6942
   do {
39✔
6943
      vlog_add_param(v, p_combinational_entry());
39✔
6944
   } while (not_at_token(tENDTABLE));
39✔
6945

6946
   scan_as_verilog();
12✔
6947

6948
   consume(tENDTABLE);
12✔
6949

6950
   vlog_set_loc(v, CURRENT_LOC);
12✔
6951
   return v;
12✔
6952
}
6953

6954
static vlog_node_t p_sequential_entry(void)
101✔
6955
{
6956
   // seq_input_list : current_state : next_state ;
6957

6958
   BEGIN("sequential entry");
202✔
6959

6960
   vlog_node_t v = vlog_new(V_UDP_ENTRY);
101✔
6961
   p_seq_input_list(v);
101✔
6962

6963
   consume(tCOLON);
101✔
6964

6965
   vlog_add_param(v, p_level_symbol());
101✔
6966

6967
   consume(tCOLON);
101✔
6968

6969
   vlog_add_param(v, p_next_state());
101✔
6970

6971
   consume(tSEMI);
101✔
6972

6973
   vlog_set_loc(v, CURRENT_LOC);
101✔
6974
   return v;
101✔
6975
}
6976

6977
static vlog_node_t p_udp_initial_statement(void)
6✔
6978
{
6979
   // initial output_port_identifier = init_val ;
6980

6981
   BEGIN("UDP initial statement");
12✔
6982

6983
   consume(tINITIAL);
6✔
6984

6985
   vlog_node_t ref = vlog_new(V_REF);
6✔
6986
   vlog_set_ident(ref, p_identifier());
6✔
6987
   vlog_set_loc(ref, &state.last_loc);
6✔
6988

6989
   vlog_symtab_lookup(symtab, ref);
6✔
6990

6991
   consume(tEQ);
6✔
6992

6993
   vlog_node_t v = vlog_new(V_BASSIGN);
6✔
6994
   vlog_set_target(v, ref);
6✔
6995
   vlog_set_value(v, p_integral_number());
6✔
6996

6997
   consume(tSEMI);
6✔
6998

6999
   vlog_set_loc(v, CURRENT_LOC);
6✔
7000
   return v;
6✔
7001
}
7002

7003
static vlog_node_t p_sequential_body(void)
15✔
7004
{
7005
   // [ udp_initial_statement ] table sequential_entry
7006
   //     { sequential_entry } endtable
7007

7008
   BEGIN("sequential UDP body");
30✔
7009

7010
   vlog_node_t v = vlog_new(V_UDP_TABLE);
15✔
7011
   vlog_set_subkind(v, V_UDP_SEQ);
15✔
7012
   vlog_set_ident(v, ident_new("sequential"));
15✔
7013

7014
   if (peek() == tINITIAL)
15✔
7015
      vlog_add_stmt(v, p_udp_initial_statement());
6✔
7016

7017
   consume(tTABLE);
15✔
7018

7019
   scan_as_udp();
15✔
7020

7021
   do {
101✔
7022
      vlog_add_param(v, p_sequential_entry());
101✔
7023
   } while (not_at_token(tENDTABLE));
101✔
7024

7025
   scan_as_verilog();
15✔
7026

7027
   consume(tENDTABLE);
15✔
7028

7029
   vlog_set_loc(v, CURRENT_LOC);
15✔
7030
   return v;
15✔
7031
}
7032

7033
static vlog_node_t p_udp_body(bool has_reg)
27✔
7034
{
7035
   // combinational_body | sequential_body
7036

7037
   BEGIN("UDP body");
54✔
7038

7039
   if (has_reg)
27✔
7040
      return p_sequential_body();
15✔
7041
   else
7042
      return p_combinational_body();
12✔
7043
}
7044

7045
static vlog_node_t p_udp_ansi_declaration(bool *has_reg)
1✔
7046
{
7047
   // { attribute_instance } primitive udp_identifier
7048
   //    ( udp_declaration_port_list ) ;
7049

7050
   BEGIN("UDP ANSI declaration");
2✔
7051

7052
   optional_attributes();
1✔
7053

7054
   vlog_node_t udp = vlog_new(V_PRIMITIVE);
1✔
7055

7056
   consume(tPRIMITIVE);
1✔
7057

7058
   ident_t id, ext;
1✔
7059
   p_external_identifier(&id, &ext);
1✔
7060
   vlog_set_ident2(udp, id);
1✔
7061

7062
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
1✔
7063
   vlog_set_ident(udp, qual);
1✔
7064

7065
   vlog_symtab_push(symtab, udp);
1✔
7066

7067
   consume(tLPAREN);
1✔
7068

7069
   p_udp_declaration_port_list(udp, has_reg);
1✔
7070

7071
   consume(tRPAREN);
1✔
7072
   consume(tSEMI);
1✔
7073

7074
   vlog_set_loc(udp, CURRENT_LOC);
1✔
7075
   return udp;
1✔
7076
}
7077

7078
static vlog_node_t p_udp_declaration(void)
27✔
7079
{
7080
   // udp_nonansi_declaration udp_port_declaration { udp_port_declaration }
7081
   //        udp_body endprimitive [ : udp_identifier ]
7082
   //   | udp_ansi_declaration udp_body endprimitive [ : udp_identifier ]
7083
   //   | extern udp_nonansi_declaration
7084
   //   | extern udp_ansi_declaration
7085
   //   | { attribute_instance } primitive udp_identifier ( .* ) ;
7086
   //        { udp_port_declaration } udp_body endprimitive [ : udp_identifier ]
7087

7088
   BEGIN("UDP declaration");
54✔
7089

7090
   bool has_reg = false;
27✔
7091
   vlog_node_t udp;
27✔
7092
   if (peek_nth(4) == tID) {
27✔
7093
      udp = p_udp_nonansi_declaration();
26✔
7094

7095
      vlog_symtab_push(symtab, udp);
26✔
7096

7097
      do {
65✔
7098
         p_udp_port_declaration(udp, &has_reg);
65✔
7099
      } while (not_at_token(tTABLE, tINITIAL));
65✔
7100

7101
      const int nports = vlog_ports(udp);
26✔
7102
      for (int i = 0; i < nports; i++)
106✔
7103
         vlog_symtab_lookup(symtab, vlog_port(udp, i));
80✔
7104
   }
7105
   else
7106
      udp = p_udp_ansi_declaration(&has_reg);
1✔
7107

7108
   vlog_add_stmt(udp, p_udp_body(has_reg));
27✔
7109

7110
   vlog_symtab_pop(symtab);
27✔
7111

7112
   consume(tENDPRIMITIVE);
27✔
7113

7114
   return udp;
27✔
7115
}
7116

7117
static void p_package_item(vlog_node_t parent)
24✔
7118
{
7119
   // package_or_generate_item_declaration | anonymous_program
7120
   //   | package_export_declaration | timeunits_declaration
7121

7122
   BEGIN("package item");
48✔
7123

7124
   p_package_or_generate_item_declaration(parent);
24✔
7125
}
24✔
7126

7127
static vlog_node_t p_package_declaration(void)
5✔
7128
{
7129
   // { attribute_instance } package [ lifetime ] package_identifier ;
7130
   //    [ timeunits_declaration ] { { attribute_instance } package_item }
7131
   // endpackage [ : package_identifier ]
7132

7133
   BEGIN("package declaration");
10✔
7134

7135
   consume(tPACKAGE);
5✔
7136

7137
   param_kind = V_LOCALPARAM;
5✔
7138

7139
   if (scan(tSTATIC, tAUTOMATIC))
5✔
7140
      p_lifetime();
×
7141

7142
   vlog_node_t v = vlog_new(V_PACKAGE);
5✔
7143

7144
   ident_t id, ext;
5✔
7145
   p_external_identifier(&id, &ext);
5✔
7146
   vlog_set_ident2(v, id);
5✔
7147

7148
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
5✔
7149
   vlog_set_ident(v, qual);
5✔
7150

7151
   consume(tSEMI);
5✔
7152

7153
   vlog_symtab_push(symtab, v);
5✔
7154

7155
   while (not_at_token(tENDPACKAGE)) {
16✔
7156
      optional_attributes();
11✔
7157
      p_package_item(v);
11✔
7158
   }
7159

7160
   vlog_symtab_pop(symtab);
5✔
7161

7162
   consume(tENDPACKAGE);
5✔
7163

7164
   if (optional(tCOLON)) {
5✔
7165
      ident_t name = p_identifier();
2✔
7166
      if (id != name)
2✔
7167
         error_at(&state.last_loc, "'%s' does not match package name '%s'",
1✔
7168
                  istr(name), istr(id));
7169
   }
7170

7171
   vlog_set_loc(v, CURRENT_LOC);
5✔
7172
   return v;
5✔
7173
}
7174

7175
static vlog_node_t p_program_nonansi_header(void)
11✔
7176
{
7177
   // { attribute_instance } program [ lifetime ] program_identifier
7178
   //    { package_import_declaration } [ parameter_port_list ] list_of_ports ;
7179

7180
   BEGIN("program non-ANSI header");
22✔
7181

7182
   optional_attributes();
11✔
7183

7184
   vlog_node_t v = vlog_new(V_PROGRAM);
11✔
7185

7186
   consume(tPROGRAM);
11✔
7187

7188
   ident_t id, ext;
11✔
7189
   p_external_identifier(&id, &ext);
11✔
7190
   vlog_set_ident2(v, id);
11✔
7191

7192
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
11✔
7193
   vlog_set_ident(v, qual);
11✔
7194

7195
   consume(tSEMI);
11✔
7196

7197
   vlog_set_loc(v, CURRENT_LOC);
11✔
7198
   return v;
11✔
7199
}
7200

7201
static void p_non_port_program_item(vlog_node_t parent)
38✔
7202
{
7203
   // { attribute_instance } continuous_assign
7204
   //   | { attribute_instance } module_or_generate_item_declaration
7205
   //   | { attribute_instance } initial_construct
7206
   //   | { attribute_instance } final_construct
7207
   //   | { attribute_instance } concurrent_assertion_item
7208
   //   | timeunits_declaration
7209
   //   | program_generate_item
7210

7211
   BEGIN("non-port program item");
76✔
7212

7213
   optional_attributes();
38✔
7214

7215
   switch (peek()) {
38✔
7216
   case tINITIAL:
11✔
7217
      vlog_add_stmt(parent, p_initial_construct());
11✔
7218
      break;
11✔
7219
   default:
27✔
7220
      p_module_or_generate_item_declaration(parent);
27✔
7221
      break;
27✔
7222
   }
7223
}
38✔
7224

7225
static vlog_node_t p_program_declaration(void)
11✔
7226
{
7227
   // program_nonansi_header [ timeunits_declaration ] { program_item }
7228
   //       endprogram [ : program_identifier ]
7229
   //   | program_ansi_header [ timeunits_declaration ]
7230
   //       { non_port_program_item }
7231
   //   | { attribute_instance } program program_identifier ( .* ) ;
7232
   //       [ timeunits_declaration ] { program_item } endprogram
7233
   //       [ : program_identifier ]
7234
   //   | extern program_nonansi_header
7235
   //   | extern program_ansi_header
7236

7237
   BEGIN("program declaration");
22✔
7238

7239
   vlog_node_t v = p_program_nonansi_header();
11✔
7240

7241
   while (not_at_token(tENDPROGRAM))
49✔
7242
      p_non_port_program_item(v);
38✔
7243

7244
   consume(tENDPROGRAM);
11✔
7245

7246
   if (optional(tCOLON)) {
11✔
7247
      ident_t name = p_identifier();
1✔
7248
      if (name != vlog_ident2(v))
1✔
7249
         parse_error(&state.last_loc, "'%s' does not match program name '%s'",
1✔
7250
                     istr(name), istr(vlog_ident2(v)));
7251
   }
7252

7253
   vlog_set_loc(v, CURRENT_LOC);
11✔
7254
   return v;
11✔
7255
}
7256

7257
static vlog_node_t p_description(void)
990✔
7258
{
7259
   // module_declaration | udp_declaration | interface_declaration
7260
   //   | program_declaration | package_declaration
7261
   //   | { attribute_instance } package_item
7262
   //   | { attribute_instance } bind_directive
7263
   //   | config_declaration
7264

7265
   BEGIN("description");
1,980✔
7266

7267
   skip_over_attributes();
990✔
7268

7269
   switch (peek()) {
990✔
7270
   case tMODULE:
939✔
7271
      return p_module_declaration();
939✔
7272
   case tPRIMITIVE:
27✔
7273
      return p_udp_declaration();
27✔
7274
   case tPACKAGE:
5✔
7275
      return p_package_declaration();
5✔
7276
   case tPROGRAM:
11✔
7277
      return p_program_declaration();
11✔
7278
   case tCLASS:
8✔
7279
   case tTYPEDEF:
7280
   case tIMPORT:
7281
      {
7282
         vlog_node_t v = vlog_new(V_NAMESPACE);
8✔
7283

7284
         char hash[SHA_HEX_LEN];
8✔
7285
         get_hex_hash(loc_file_str(&state.last_loc), hash);
8✔
7286

7287
         ident_t name = ident_sprintf("%s$%d", hash, next_namespace++);
8✔
7288
         vlog_set_ident(v, ident_prefix(lib_name(lib_work()), name, '.'));
8✔
7289

7290
         do {
13✔
7291
            p_package_item(v);
13✔
7292
         } while (scan(tCLASS, tTYPEDEF, tIMPORT));
13✔
7293

7294
         vlog_set_loc(v, CURRENT_LOC);
8✔
7295
         return v;
8✔
7296
      }
7297
   default:
×
7298
      expect(tPRIMITIVE, tMODULE, tPACKAGE, tPROGRAM, tCLASS, tTYPEDEF,
×
7299
             tIMPORT);
7300
      return NULL;
×
7301
   }
7302
}
7303

7304
static void p_timescale_compiler_directive(void)
21✔
7305
{
7306
   // `timescale time_unit / time_precision
7307

7308
   BEGIN("timescale compiler directive");
42✔
7309

7310
   consume(tTIMESCALE);
21✔
7311

7312
   uint64_t unit_value = 1;
21✔
7313
   if (consume(tUNSNUM))
21✔
7314
      unit_value = atoll(state.last_lval.str);
20✔
7315

7316
   const char *unit_name = "fs";
21✔
7317
   if (consume(tID))
21✔
7318
      unit_name = istr(state.last_lval.ident);
21✔
7319

7320
   consume(tOVER);
21✔
7321

7322
   uint64_t prec_value = 1;
21✔
7323
   if (consume(tUNSNUM))
21✔
7324
      prec_value = atoll(state.last_lval.str);
20✔
7325

7326
   const char *prec_name = "fs";
21✔
7327
   if (consume(tID))
21✔
7328
      prec_name = istr(state.last_lval.ident);
20✔
7329

7330
   set_timescale(unit_value, unit_name, prec_value, prec_name, CURRENT_LOC);
21✔
7331
}
21✔
7332

7333
static void p_defaultnettype_compiler_directive(void)
12✔
7334
{
7335
   // `default_nettype wire | tri | tri0 | tri1 | wand | triand | wor
7336
   //    | trior | trireg | uwire | none
7337

7338
   BEGIN("default_nettype directive");
24✔
7339

7340
   consume(tDEFNETTYPE);
12✔
7341

7342
   switch (one_of(tWIRE, tTRI, tTRI0, tTRI1, tWAND, tTRIAND, tWOR, tTRIOR,
12✔
7343
                  tTRIREG, tUWIRE, tNONE)) {
7344
   case tWIRE: implicit_kind = V_NET_WIRE; break;
1✔
7345
   case tNONE: implicit_kind = V_NET_NONE; break;
1✔
7346
   }
7347
}
12✔
7348

7349
static void p_unconnected_drive_directive(void)
2✔
7350
{
7351
   // `unconnected_drive pull0 | pull1
7352

7353
   BEGIN("unconnected_drive directive");
4✔
7354

7355
   consume(tUNCTDRIVE);
2✔
7356

7357
   // TODO set default drive for unconnected nets
7358
   one_of(tPULL0, tPULL1);
2✔
7359
}
2✔
7360

7361
static void p_nounconnected_drive_directive(void)
1✔
7362
{
7363
   // `nounconnected_drive
7364

7365
   BEGIN("nounconnected_drive directive");
2✔
7366

7367
   consume(tNOUNCTDRIVE);
1✔
7368

7369
   // TODO reset default drive for unconnected nets
7370
}
1✔
7371

7372
static void p_keywords_directive(void)
8✔
7373
{
7374
   // `begin_keywords "version_specifier"
7375

7376
   BEGIN("keywords directive");
16✔
7377

7378
   consume(tBEGINKEYWORDS);
8✔
7379

7380
   if (consume(tSTRING)) {
8✔
7381
      vlog_version_t vers;
7✔
7382
      if (parse_verilog_version(tb_get(state.last_lval.text), &vers))
7✔
7383
         push_keywords(vers);
6✔
7384
      else
7385
         error_at(&state.last_loc, "\"%s\" is not a recognised Verilog or "
1✔
7386
                  "System Verilog version", tb_get(state.last_lval.text));
7387

7388
      tb_free(state.last_lval.text);
7✔
7389
   }
7390
}
8✔
7391

7392
static void p_endkeywords_directive(void)
7✔
7393
{
7394
   // `end_keywords
7395

7396
   BEGIN("endkeywords directive");
14✔
7397

7398
   consume(tENDKEYWORDS);
7✔
7399

7400
   if (!pop_keywords())
7✔
7401
      error_at(&state.last_loc, "`end_keywords directive without matching "
1✔
7402
               "`begin_keywords");
7403
}
7✔
7404

7405
static void p_resetall_directive(void)
1✔
7406
{
7407
   // `resetall
7408

7409
   BEGIN("resetall directive");
2✔
7410

7411
   consume(tRESETALL);
1✔
7412

7413
   implicit_kind = V_NET_WIRE;
1✔
7414
}
1✔
7415

7416
static void p_directive_list(void)
1,798✔
7417
{
7418
   BEGIN("directive list");
3,596✔
7419

7420
   for (;;) {
1,850✔
7421
      switch (peek()) {
1,850✔
7422
      case tDEFNETTYPE:
12✔
7423
         p_defaultnettype_compiler_directive();
12✔
7424
         break;
12✔
7425
      case tTIMESCALE:
21✔
7426
         p_timescale_compiler_directive();
21✔
7427
         break;
21✔
7428
      case tUNCTDRIVE:
2✔
7429
         p_unconnected_drive_directive();
2✔
7430
         break;
2✔
7431
      case tNOUNCTDRIVE:
1✔
7432
         p_nounconnected_drive_directive();
1✔
7433
         break;
1✔
7434
      case tBEGINKEYWORDS:
8✔
7435
         p_keywords_directive();
8✔
7436
         break;
8✔
7437
      case tENDKEYWORDS:
7✔
7438
         p_endkeywords_directive();
7✔
7439
         break;
7✔
7440
      case tRESETALL:
1✔
7441
         p_resetall_directive();
1✔
7442
         break;
1✔
7443
      default:
7444
         return;
1,798✔
7445
      }
7446
   }
7447
}
7448

7449
static vlog_node_t end_of_file(void)
808✔
7450
{
7451
   vlog_symtab_pop(symtab);
808✔
7452
   vlog_symtab_free(symtab);
808✔
7453
   symtab = NULL;
808✔
7454
   return NULL;
808✔
7455
}
7456

7457
static vlog_node_t p_source_text(void)
990✔
7458
{
7459
   // [ timeunits_declaration ] { description }
7460

7461
   BEGIN("source text");
1,980✔
7462

7463
   for (;;) {
990✔
7464
      if (peek() == tEOF) {
990✔
7465
         discard_global_arena();
×
7466
         return end_of_file();
×
7467
      }
7468

7469
      vlog_node_t v = p_description();
990✔
7470
      if (v == NULL || is_top_level(v))
990✔
7471
         return v;
990✔
7472
   }
7473
}
7474

7475
vlog_node_t vlog_parse(void)
1,798✔
7476
{
7477
   state.n_correct = RECOVER_THRESH;
1,798✔
7478
   param_kind = V_PARAM_DECL;
1,798✔
7479

7480
   for (int i = 0; i < ARRAY_LEN(atom_types); i++)
19,778✔
7481
      atom_types[i] = NULL;
17,980✔
7482

7483
   scan_as_verilog();
1,798✔
7484

7485
   if (symtab == NULL) {
1,798✔
7486
      symtab = vlog_symtab_new();
810✔
7487
      vlog_symtab_push(symtab, NULL);   // Compilation unit scope
810✔
7488
      vlog_symtab_poison(symtab, error_marker());
810✔
7489
   }
7490

7491
   p_directive_list();
1,798✔
7492

7493
   if (peek() == tEOF)
1,798✔
7494
      return end_of_file();
808✔
7495

7496
   make_new_arena();
990✔
7497

7498
   return p_source_text();
990✔
7499
}
7500

7501
void reset_verilog_parser(void)
1,586✔
7502
{
7503
   state.n_correct = RECOVER_THRESH;
1,586✔
7504
   state.tokenq_head = state.tokenq_tail = 0;
1,586✔
7505
   state.lex_fn = processed_yylex;
1,586✔
7506
   state.error_fn = vlog_parse_error_cb;
1,586✔
7507

7508
   implicit_kind = V_NET_WIRE;
1,586✔
7509
   last_attr = NULL;
1,586✔
7510
   next_namespace = 1;
1,586✔
7511

7512
   if (symtab != NULL) {
1,586✔
7513
      vlog_symtab_free(symtab);
×
7514
      symtab = NULL;
×
7515
   }
7516
}
1,586✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc