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

nickg / nvc / 13999718329

21 Mar 2025 08:54AM UTC coverage: 92.295% (-0.01%) from 92.305%
13999718329

push

github

nickg
Implement close2Proc for TCL >= 9

68329 of 74033 relevant lines covered (92.3%)

423277.39 hits per line

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

95.45
/src/vlog/vlog-parse.c
1
//
2
//  Copyright (C) 2024  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 "scan.h"
24
#include "vlog/vlog-node.h"
25
#include "vlog/vlog-phase.h"
26

27
#include <ctype.h>
28
#include <string.h>
29
#include <stdlib.h>
30
#include <assert.h>
31

32
#define RECOVER_THRESH 5
33
#define TRACE_PARSE    0
34
#define TRACE_RECOVERY 0
35
#define TOKENQ_SIZE    8
36

37
typedef struct {
38
   token_t  token;
39
   yylval_t lval;
40
   loc_t    loc;
41
} tokenq_t;
42

43
typedef struct {
44
   loc_t       start_loc;
45
   loc_t       last_loc;
46
   const char *hint_str;
47
   int         n_correct;
48
   tokenq_t    tokenq[TOKENQ_SIZE];
49
   int         tokenq_head;
50
   int         tokenq_tail;
51
   yylval_t    last_lval;
52
   token_t     opt_hist[8];
53
   int         nopt_hist;
54
#if TRACE_PARSE
55
   int         depth;
56
#endif
57
} parse_state_t;
58

59
typedef struct {
60
   const char *old_hint;
61
   loc_t       old_start_loc;
62
} rule_state_t;
63

64
static parse_state_t state;
65

66
extern loc_t yylloc;
67

68
#define scan(...) _scan(1, __VA_ARGS__, -1)
69
#define expect(...) _expect(1, __VA_ARGS__, -1)
70
#define one_of(...) _one_of(1, __VA_ARGS__, -1)
71
#define not_at_token(...) ((peek() != tEOF) && !_scan(1, __VA_ARGS__, -1))
72
#define peek() peek_nth(1)
73

74
#define parse_error(loc, ...) do {              \
75
      if (state.n_correct >= RECOVER_THRESH)    \
76
         error_at((loc), __VA_ARGS__);          \
77
   } while (0)
78

79
#if TRACE_PARSE
80
static void _push_state(const rule_state_t *s);
81
#else
82
#define _push_state(s)
83
#endif
84

85
#define EXTEND(s)                                                      \
86
   __attribute__((cleanup(_pop_state), unused))                        \
87
   const rule_state_t _state = { state.hint_str, state.start_loc };    \
88
   state.hint_str = s;                                                 \
89
   _push_state(&_state);
90

91
#define BEGIN_WITH_HEAD(s, t)                            \
92
   EXTEND(s);                                            \
93
   state.start_loc = (t) ? *vlog_loc(t) : LOC_INVALID;   \
94

95
#define BEGIN(s)  BEGIN_WITH_HEAD(s, NULL)
96

97
#define CURRENT_LOC _diff_loc(&state.start_loc, &state.last_loc)
98

99
static vlog_node_t p_statement_or_null(void);
100
static vlog_node_t p_expression(void);
101
static vlog_node_t p_constant_expression(void);
102
static vlog_node_t p_data_type(void);
103
static void p_list_of_variable_decl_assignments(vlog_node_t parent,
104
                                                vlog_node_t datatype);
105
static vlog_node_t p_variable_lvalue(void);
106
static vlog_node_t p_bit_select(ident_t id);
107

108
static inline void _pop_state(const rule_state_t *r)
22,714✔
109
{
110
#if TRACE_PARSE
111
   printf("%*s<-- %s\n", state.depth--, "", state.hint_str);
112
#endif
113

114
   state.hint_str = r->old_hint;
22,714✔
115

116
   if (r->old_start_loc.first_line != LINE_INVALID)
22,714✔
117
      state.start_loc = r->old_start_loc;
8,598✔
118
}
22,714✔
119

120
#if TRACE_PARSE
121
static inline void _push_state(const rule_state_t *r)
122
{
123
   printf("%*s--> %s\n", state.depth++, "", state.hint_str);
124
}
125
#endif
126

127
static token_t peek_nth(int n)
36,162✔
128
{
129
   while (((state.tokenq_head - state.tokenq_tail) & (TOKENQ_SIZE - 1)) < n) {
46,124✔
130
      const token_t token = processed_yylex();
9,962✔
131

132
      int next = (state.tokenq_head + 1) & (TOKENQ_SIZE - 1);
9,962✔
133
      assert(next != state.tokenq_tail);
9,962✔
134

135
      extern yylval_t yylval;
9,962✔
136

137
      state.tokenq[state.tokenq_head].token = token;
9,962✔
138
      state.tokenq[state.tokenq_head].lval  = yylval;
9,962✔
139
      state.tokenq[state.tokenq_head].loc   = yylloc;
9,962✔
140

141
      state.tokenq_head = next;
9,962✔
142
   }
143

144
   const int pos = (state.tokenq_tail + n - 1) & (TOKENQ_SIZE - 1);
36,162✔
145
   return state.tokenq[pos].token;
36,162✔
146
}
147

148
static void drop_token(void)
9,865✔
149
{
150
   assert(state.tokenq_head != state.tokenq_tail);
9,865✔
151

152
   if (state.start_loc.first_line == LINE_INVALID)
9,865✔
153
      state.start_loc = state.tokenq[state.tokenq_tail].loc;
5,343✔
154

155
   state.last_lval = state.tokenq[state.tokenq_tail].lval;
9,865✔
156
   state.last_loc  = state.tokenq[state.tokenq_tail].loc;
9,865✔
157

158
   state.tokenq_tail = (state.tokenq_tail + 1) & (TOKENQ_SIZE - 1);
9,865✔
159

160
   state.nopt_hist = 0;
9,865✔
161
}
9,865✔
162

163
static void drop_tokens_until(token_t tok)
2✔
164
{
165
   token_t next = tEOF;
2✔
166
   do {
7✔
167
      free_token(tok, &state.last_lval);
7✔
168
      next = peek();
7✔
169
      drop_token();
7✔
170
   } while ((tok != next) && (next != tEOF));
7✔
171

172
#if TRACE_RECOVERY
173
   if (peek() != tEOF)
174
      fmt_loc(stdout, &(tokenq[tokenq_tail].loc));
175
#endif
176
}
2✔
177

178
static void _vexpect(va_list ap)
8✔
179
{
180
   if (state.n_correct >= RECOVER_THRESH) {
8✔
181
      diag_t *d = diag_new(DIAG_ERROR, &(state.tokenq[state.tokenq_tail].loc));
3✔
182
      diag_printf(d, "unexpected $yellow$%s$$ while parsing %s, expecting ",
3✔
183
                  token_str(peek()), state.hint_str);
184

185
      bool first = true;
3✔
186
      for (int i = 0; i < state.nopt_hist; i++) {
3✔
187
         diag_printf(d, "%s$yellow$%s$$", i == 0 ? "one of " : ", ",
×
188
                     token_str(state.opt_hist[i]));
189
         first = false;
×
190
      }
191

192
      int tok = va_arg(ap, int);
3✔
193
      while (tok != -1) {
31✔
194
         const int tmp = tok;
28✔
195
         tok = va_arg(ap, int);
28✔
196

197
         if (first && (tok != -1))
28✔
198
            diag_printf(d, "one of ");
2✔
199
         else if (!first)
26✔
200
            diag_printf(d, (tok == -1) ? " or " : ", ");
48✔
201

202
         diag_printf(d, "$yellow$%s$$", token_str(tmp));
28✔
203

204
         first = false;
28✔
205
      }
206

207
      diag_hint(d, &(state.tokenq[state.tokenq_tail].loc),
3✔
208
                "this token was unexpected");
209
      diag_emit(d);
3✔
210
   }
211

212
   state.n_correct = 0;
8✔
213

214
   drop_token();
8✔
215
}
8✔
216

217
static void _expect(int dummy, ...)
4✔
218
{
219
   va_list ap;
4✔
220
   va_start(ap, dummy);
4✔
221
   _vexpect(ap);
4✔
222
   va_end(ap);
4✔
223
}
4✔
224

225
static bool consume(token_t tok)
9,854✔
226
{
227
   const token_t got = peek();
9,854✔
228
   if (tok != got) {
9,854✔
229
      expect(tok);
4✔
230
      return false;
4✔
231
   }
232
   else {
233
      state.n_correct++;
9,850✔
234
      drop_token();
9,850✔
235
      return true;
9,850✔
236
   }
237
}
238

239
static bool optional(token_t tok)
4,254✔
240
{
241
   if (peek() == tok) {
4,254✔
242
      consume(tok);
1,066✔
243
      return true;
1,066✔
244
   }
245
   else {
246
      if (state.nopt_hist < ARRAY_LEN(state.opt_hist))
3,188✔
247
         state.opt_hist[state.nopt_hist++] = tok;
3,188✔
248
      return false;
3,188✔
249
   }
250
}
251

252
static bool _scan(int dummy, ...)
2,893✔
253
{
254
   va_list ap;
2,893✔
255
   va_start(ap, dummy);
2,893✔
256

257
   token_t p = peek();
2,893✔
258
   bool found = false;
2,893✔
259

260
   while (!found) {
2,893✔
261
      const int tok = va_arg(ap, token_t);
8,042✔
262
      if (tok == -1)
8,042✔
263
         break;
264
      else if (p == tok)
5,802✔
265
         found = true;
266
   }
267

268
   va_end(ap);
2,893✔
269
   return found;
2,893✔
270
}
271

272
static int _one_of(int dummy, ...)
573✔
273
{
274
   va_list ap;
573✔
275
   va_start(ap, dummy);
573✔
276

277
   token_t p = peek();
573✔
278
   bool found = false;
573✔
279

280
   while (!found) {
573✔
281
      const int tok = va_arg(ap, token_t);
2,411✔
282
      if (tok == -1)
2,411✔
283
         break;
284
      else if (p == tok)
2,407✔
285
         found = true;
286
   }
287

288
   va_end(ap);
573✔
289

290
   if (found) {
573✔
291
      consume(p);
569✔
292
      return p;
569✔
293
   }
294
   else {
295
      va_start(ap, dummy);
4✔
296
      _vexpect(ap);
4✔
297
      va_end(ap);
4✔
298

299
      return -1;
4✔
300
   }
301
}
302

303
static const loc_t *_diff_loc(const loc_t *start, const loc_t *end)
6,004✔
304
{
305
   static loc_t result;
6,004✔
306

307
   result = get_loc(start->first_line,
6,004✔
308
                    start->first_column,
6,004✔
309
                    end->first_line + end->line_delta,
6,004✔
310
                    end->first_column + end->column_delta,
6,004✔
311
                    start->file_ref);
6,004✔
312
   return &result;
6,004✔
313
}
314

315
static void set_timescale(const char *unit_value, const char *unit_name,
9✔
316
                          const char *prec_value, const char *prec_name,
317
                          const loc_t *loc)
318
{
319
   // See IEEE 1800-2017 section 22.7 for rules
320

321
   struct {
9✔
322
      const char *value;
323
      const char *name;
324
      int64_t     parsed;
325
   } args[] = {
9✔
326
      { unit_value, unit_name },
327
      { prec_value, prec_name },
328
   };
329

330
   for (int i = 0; i < ARRAY_LEN(args); i++) {
27✔
331
      static const struct {
332
         const char *name;
333
         int64_t value;
334
      } valid_units[] = {
335
         { "s", INT64_C(60000000000000) },
336
         { "ms", 1000000000000 },
337
         { "us", 1000000000 },
338
         { "ns", 1000000 },
339
         { "ps", 1000 },
340
         { "fs", 1 },
341
      };
342

343
      bool name_valid = false;
85✔
344
      for (int j = 0; j < ARRAY_LEN(valid_units); j++) {
85✔
345
         if (strcmp(valid_units[j].name, args[i].name) == 0) {
84✔
346
            args[i].parsed = valid_units[j].value;
17✔
347
            name_valid = true;
17✔
348
            break;
17✔
349
         }
350
      }
351

352
      if (!name_valid)
17✔
353
         error_at(loc, "invalid time unit name '%s'", args[i].name);
1✔
354

355
      const int scale = atoi(args[i].value);
18✔
356
      if (scale != 1 && scale != 10 && scale != 100) {
18✔
357
         diag_t *d = diag_new(DIAG_ERROR, loc);
1✔
358
         diag_printf(d, "invalid order of magnitude in `timescale directive");
1✔
359
         diag_hint(d, NULL, "the valid values are 1, 10, and 100");
1✔
360
         diag_emit(d);
1✔
361
      }
362

363
      args[i].parsed *= scale;
18✔
364
   }
365

366
   // TODO: do something with parsed scale/precision
367
}
9✔
368

369
static ident_t error_marker(void)
2✔
370
{
371
   return well_known(W_ERROR);
2✔
372
}
373

374
static vlog_node_t dummy_expression(void)
×
375
{
376
   vlog_node_t v = vlog_new(V_NUMBER);
×
377
   vlog_set_number(v, number_new("1'b0"));
×
378
   return v;
×
379
}
380

381
static vlog_node_t logic_type(void)
79✔
382
{
383
   vlog_node_t v = vlog_new(V_DATA_TYPE);
79✔
384
   vlog_set_subkind(v, DT_LOGIC);
79✔
385
   return v;
79✔
386
}
387

388
static ident_t p_identifier(void)
1,507✔
389
{
390
   if (consume(tID)) {
1,507✔
391
      ident_t id = ident_new(state.last_lval.str);
1,506✔
392
      free(state.last_lval.str);
1,506✔
393
      return id;
1,506✔
394
   }
395
   else
396
      return error_marker();
1✔
397
}
398

399
static void p_external_identifier(ident_t *id, ident_t *ext)
302✔
400
{
401
   if (consume(tID)) {
302✔
402
      *id = ident_new(state.last_lval.str);
302✔
403
      for (char *p = state.last_lval.str; *p; p++)
1,427✔
404
         *p = toupper_iso88591(*p);
1,125✔
405
      *ext = ident_new(state.last_lval.str);
302✔
406
      free(state.last_lval.str);
302✔
407
   }
408
   else
409
      *id = *ext = error_marker();
×
410
}
302✔
411

412
static ident_t p_system_tf_identifier(void)
430✔
413
{
414
   if (consume(tSYSTASK)) {
430✔
415
      ident_t id = ident_new(state.last_lval.str);
430✔
416
      free(state.last_lval.str);
430✔
417
      return id;
430✔
418
   }
419
   else
420
      return error_marker();
×
421
}
422

423
static void p_attr_spec(void)
6✔
424
{
425
   // attr_name [ = constant_expression ]
426

427
   BEGIN("attribute specification");
12✔
428

429
   (void)p_identifier();
6✔
430

431
   if (optional(tEQ))
6✔
432
      (void)p_constant_expression();
×
433
}
6✔
434

435
static void p_attribute_instance(void)
6✔
436
{
437
   // (* attr_spec { , attr_spec } *)
438

439
   BEGIN("attribute instance");
12✔
440

441
   consume(tATTRBEGIN);
6✔
442

443
   do {
6✔
444
      p_attr_spec();
6✔
445
   } while (optional(tCOMMA));
6✔
446

447
   consume(tATTREND);
6✔
448
}
6✔
449

450
static vlog_node_t p_unsigned_number(void)
699✔
451
{
452
   // decimal_digit { _ | decimal_digit }
453

454
   BEGIN("unsigned number");
699✔
455

456
   consume(tUNSIGNED);
699✔
457

458
   vlog_node_t v = vlog_new(V_NUMBER);
699✔
459
   vlog_set_loc(v, CURRENT_LOC);
699✔
460
   vlog_set_number(v, number_new(state.last_lval.str));
699✔
461
   free(state.last_lval.str);
699✔
462
   return v;
699✔
463
}
464

465
static vlog_node_t p_integral_number(void)
572✔
466
{
467
   // decimal_number | octal_number | binary_number | hex_number
468

469
   BEGIN("integral number");
1,144✔
470

471
   if (peek() == tUNSIGNED)
572✔
472
      return p_unsigned_number();
516✔
473
   else {
474
      consume(tNUMBER);
56✔
475

476
      vlog_node_t v = vlog_new(V_NUMBER);
56✔
477
      vlog_set_loc(v, CURRENT_LOC);
56✔
478
      vlog_set_number(v, number_new(state.last_lval.str));
56✔
479
      free(state.last_lval.str);
56✔
480
      return v;
56✔
481
   }
482
}
483

484
static vlog_node_t p_real_number(void)
6✔
485
{
486
   // fixed_point_number
487
   //   | unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number
488

489
   BEGIN("real number");
6✔
490

491
   consume(tREAL);
6✔
492

493
   vlog_node_t v = vlog_new(V_REAL);
6✔
494
   vlog_set_dval(v, state.last_lval.real);
6✔
495
   vlog_set_loc(v, CURRENT_LOC);
6✔
496
   return v;
6✔
497
}
498

499
static vlog_node_t p_number(void)
574✔
500
{
501
   // integral_number | real_number
502

503
   BEGIN("number");
1,148✔
504

505
   if (peek() == tREAL)
574✔
506
      return p_real_number();
6✔
507
   else
508
      return p_integral_number();
568✔
509
}
510

511
static vlog_node_t p_string_literal(void)
298✔
512
{
513
   // " { Any_ASCII_Characters } "
514

515
   BEGIN("string literal");
298✔
516

517
   consume(tSTRING);
298✔
518

519
   vlog_node_t v = vlog_new(V_STRING);
298✔
520
   vlog_set_loc(v, CURRENT_LOC);
298✔
521

522
   state.last_lval.str[strlen(state.last_lval.str) - 1] = '\0';
298✔
523
   vlog_set_text(v, state.last_lval.str + 1);
298✔
524
   free(state.last_lval.str);
298✔
525

526
   return v;
298✔
527
}
528

529
static vlog_node_t p_primary_literal(void)
872✔
530
{
531
   // number | time_literal | unbased_unsized_literal | string_literal
532

533
   BEGIN("primary literal");
1,744✔
534

535
   switch (peek()) {
872✔
536
   case tNUMBER:
574✔
537
   case tUNSIGNED:
538
   case tREAL:
539
      return p_number();
574✔
540
   case tSTRING:
298✔
541
      return p_string_literal();
298✔
542
   default:
×
543
      one_of(tNUMBER, tUNSIGNED, tREAL, tSTRING);
×
544
      return dummy_expression();
×
545
   }
546
}
547

548
static vlog_node_t p_constant_bit_select(ident_t id)
184✔
549
{
550
   // { [ constant_expression ] }
551

552
   EXTEND("constant bit select");
368✔
553

554
   // Checked for constant-ness later
555
   return p_bit_select(id);
184✔
556
}
557

558
static vlog_node_t p_constant_select(ident_t id)
184✔
559
{
560
   // [ { . member_identifier constant_bit_select } . member_identifier ]
561
   //    constant_bit_select [ [ constant_part_select_range ] ]
562

563
   EXTEND("constant select");
368✔
564

565
   return p_constant_bit_select(id);
184✔
566
}
567

568
static vlog_node_t p_constant_expression(void)
123✔
569
{
570
   // constant_primary | unary_operator { attribute_instance } constant_primary
571
   //   | constant_expression binary_operator { attribute_instance }
572
   //       constant_expression
573
   //   | constant_expression ? { attribute_instance }
574
   //       constant_expression : constant_expression
575

576
   BEGIN("constant expression");
246✔
577

578
   // Checked for constant-ness later
579
   return p_expression();
123✔
580
}
581

582
static void p_constant_range(vlog_node_t *left, vlog_node_t *right)
60✔
583
{
584
   // constant_expression : constant_expression
585

586
   BEGIN("constant range");
60✔
587

588
   *left = p_constant_expression();
60✔
589

590
   consume(tCOLON);
60✔
591

592
   *right = p_constant_expression();
60✔
593
}
60✔
594

595
static vlog_node_t p_packed_dimension(void)
57✔
596
{
597
   // [ constant_range ] | unsized_dimension
598

599
   BEGIN("packed dimension");
57✔
600

601
   consume(tLSQUARE);
57✔
602

603
   vlog_node_t left, right;
57✔
604
   p_constant_range(&left, &right);
57✔
605

606
   consume(tRSQUARE);
57✔
607

608
   vlog_node_t v = vlog_new(V_DIMENSION);
57✔
609
   vlog_set_subkind(v, V_DIM_PACKED);
57✔
610
   vlog_set_left(v, left);
57✔
611
   vlog_set_right(v, right);
57✔
612
   vlog_set_loc(v, CURRENT_LOC);
57✔
613

614
   return v;
57✔
615
}
616

617
static vlog_node_t p_unpacked_dimension(void)
3✔
618
{
619
   // [ constant_range ] | [ constant_expression ]
620

621
   BEGIN("unpacked dimension");
3✔
622

623
   consume(tLSQUARE);
3✔
624

625
   vlog_node_t left, right;
3✔
626
   p_constant_range(&left, &right);
3✔
627

628
   consume(tRSQUARE);
3✔
629

630
   vlog_node_t v = vlog_new(V_DIMENSION);
3✔
631
   vlog_set_subkind(v, V_DIM_UNPACKED);
3✔
632
   vlog_set_left(v, left);
3✔
633
   vlog_set_right(v, right);
3✔
634
   vlog_set_loc(v, CURRENT_LOC);
3✔
635

636
   return v;
3✔
637
}
638

639
static vlog_node_t p_data_type_or_void(void)
9✔
640
{
641
   // data_type | void
642

643
   BEGIN("data type or void");
18✔
644

645
   if (optional(tVOID))
9✔
646
      return NULL;
647
   else
648
      return p_data_type();
9✔
649
}
650

651
static void p_struct_union_member(vlog_node_t v)
9✔
652
{
653
   // { attribute_instance } [ random_qualifier ] data_type_or_void
654
   //    list_of_variable_decl_assignments ;
655

656
   BEGIN("struct or union member");
18✔
657

658
   while (peek() == tATTRBEGIN)
9✔
659
      p_attribute_instance();
×
660

661
   vlog_node_t dt = p_data_type_or_void();
9✔
662
   p_list_of_variable_decl_assignments(v, dt);
9✔
663

664
   consume(tSEMI);
9✔
665
}
9✔
666

667
static void p_enum_name_declaration(vlog_node_t parent)
4✔
668
{
669
   // enum_identifier [ [ integral_number [ : integral_number ] ] ]
670
   //   [ = constant_expression ]
671

672
   BEGIN("enum name declaration");
8✔
673

674
   vlog_node_t v = vlog_new(V_ENUM_NAME);
4✔
675
   vlog_set_ident(v, p_identifier());
4✔
676
   vlog_set_type(v, parent);
4✔
677

678
   vlog_add_decl(parent, v);
4✔
679
}
4✔
680

681
static vlog_node_t p_integer_atom_type(void)
14✔
682
{
683
   // byte | shortint | int | longint | integer | time
684

685
   BEGIN("integer atom type");
14✔
686

687
   data_type_t dt = DT_BYTE;
14✔
688
   switch (one_of(tBYTE, tSHORTINT, tSVINT, tLONGINT, tINTEGER, tTIME)) {
14✔
689
   case tBYTE:     dt = DT_BYTE; break;
690
   case tSHORTINT: dt = DT_SHORTINT; break;
691
   case tSVINT:    dt = DT_INT; break;
692
   case tLONGINT:  dt = DT_LONGINT; break;
693
   case tINTEGER:  dt = DT_INTEGER; break;
694
   case tTIME:     dt = DT_TIME; break;
695
   }
696

697
   vlog_node_t v = vlog_new(V_DATA_TYPE);
14✔
698
   vlog_set_subkind(v, dt);
14✔
699
   vlog_set_loc(v, &state.last_loc);
14✔
700
   return v;
14✔
701
}
702

703
static vlog_node_t p_integer_vector_type(void)
126✔
704
{
705
   //  bit | logic | reg
706

707
   BEGIN("integer vector type");
126✔
708

709
   data_type_t dt = DT_LOGIC;
126✔
710
   switch (one_of(tBIT, tLOGIC, tREG)) {
126✔
711
   case tBIT:    dt = DT_BIT; break;
3✔
712
   case tLOGIC:
713
   case tREG:    dt = DT_LOGIC; break;
714
   }
715

716
   vlog_node_t v = vlog_new(V_DATA_TYPE);
126✔
717
   vlog_set_subkind(v, dt);
126✔
718
   vlog_set_loc(v, &state.last_loc);
126✔
719
   return v;
126✔
720
}
721

722
static vlog_node_t p_non_integer_type(void)
5✔
723
{
724
   // shortreal | real | realtime
725

726
   BEGIN("non-integer type");
5✔
727

728
   data_type_t dt = DT_REAL;
5✔
729
   switch (one_of(tSVREAL, tSHORTREAL, tREALTIME)) {
5✔
730
   case tSVREAL:    dt = DT_REAL; break;
731
   case tSHORTREAL: dt = DT_SHORTREAL; break;
1✔
732
   case tREALTIME:  dt = DT_REALTIME; break;
1✔
733
   }
734

735
   vlog_node_t v = vlog_new(V_DATA_TYPE);
5✔
736
   vlog_set_subkind(v, dt);
5✔
737
   vlog_set_loc(v, &state.last_loc);
5✔
738
   return v;
5✔
739
}
740

741
static vlog_node_t p_struct_union(void)
5✔
742
{
743
   // struct | union [ tagged ]
744

745
   BEGIN("struct or union");
10✔
746

747
   switch (one_of(tSTRUCT, tUNION)) {
5✔
748
   case tUNION:
2✔
749
      {
750
         vlog_node_t v = vlog_new(V_UNION_DECL);
2✔
751
         optional(tTAGGED);
2✔
752
         return v;
2✔
753
      }
754
   case tSTRUCT:
3✔
755
   default:
756
      return vlog_new(V_STRUCT_DECL);
3✔
757
   }
758
}
759

760
static vlog_node_t p_data_type(void)
152✔
761
{
762
   // integer_vector_type [ signing ] { packed_dimension }
763
   //   | integer_atom_type [ signing ] | non_integer_type
764
   //   | struct_union [ packed [ signing ] ]
765
   //       { struct_union_member { struct_union_member } } { packed_dimension }
766
   //   | enum [ enum_base_type ] { enum_name_declaration
767
   //       { , enum_name_declaration } } { packed_dimension }
768
   //   | string | chandle
769
   //   | virtual [ interface ] interface_identifier
770
   //       [ parameter_value_assignment ] [ . modport_identifier ]
771
   //   | [ class_scope | package_scope ] type_identifier { packed_dimension }
772
   //   | class_type | event | ps_covergroup_identifier | type_reference
773

774
   BEGIN("data type");
304✔
775

776
   switch (peek()) {
152✔
777
   case tBIT:
126✔
778
   case tLOGIC:
779
   case tREG:
780
      {
781
         vlog_node_t v = p_integer_vector_type();
126✔
782

783
         while (peek() == tLSQUARE)
152✔
784
            vlog_add_range(v, p_packed_dimension());
26✔
785

786
         return v;
787
      }
788

789
   case tBYTE:
14✔
790
   case tSHORTINT:
791
   case tSVINT:
792
   case tLONGINT:
793
   case tINTEGER:
794
   case tTIME:
795
      return p_integer_atom_type();
14✔
796

797
   case tSVREAL:
5✔
798
   case tREALTIME:
799
   case tSHORTREAL:
800
      return p_non_integer_type();
5✔
801

802
   case tSTRUCT:
5✔
803
   case tUNION:
804
      {
805
         vlog_node_t v = p_struct_union();
5✔
806

807
         (void)optional(tPACKED);
5✔
808

809
         consume(tLBRACE);
5✔
810

811
         do {
9✔
812
            p_struct_union_member(v);
9✔
813
         } while (not_at_token(tRBRACE));
9✔
814

815
         consume(tRBRACE);
5✔
816

817
         if (peek() == tLSQUARE)
5✔
818
            vlog_add_range(v, p_packed_dimension());
×
819

820
         vlog_set_loc(v, CURRENT_LOC);
5✔
821
         return v;
5✔
822
      }
823

824
   case tENUM:
2✔
825
      {
826
         consume(tENUM);
2✔
827

828
         vlog_node_t v = vlog_new(V_ENUM_DECL);
2✔
829

830
         consume(tLBRACE);
2✔
831

832
         do {
4✔
833
            p_enum_name_declaration(v);
4✔
834
         } while (optional(tCOMMA));
4✔
835

836
         consume(tRBRACE);
2✔
837

838
         while (peek() == tLSQUARE)
3✔
839
            vlog_add_range(v, p_packed_dimension());
1✔
840

841
         vlog_set_loc(v, CURRENT_LOC);
2✔
842
         return v;
2✔
843
      }
844

845
   default:
×
846
      one_of(tBIT, tLOGIC, tREG, tBYTE, tSHORTINT, tSVINT, tLONGINT, tINTEGER,
×
847
             tTIME, tSVREAL, tREALTIME, tSHORTREAL, tSTRUCT, tUNION, tENUM);
848
      return logic_type();
×
849
   }
850
}
851

852
static vlog_node_t p_implicit_data_type(void)
167✔
853
{
854
   // [ signing ] { packed_dimension }
855

856
   BEGIN("implicit data type");
167✔
857

858
   vlog_node_t v = vlog_new(V_DATA_TYPE);
167✔
859
   vlog_set_subkind(v, DT_LOGIC);
167✔
860

861
   while (peek() == tLSQUARE)
197✔
862
      vlog_add_range(v, p_packed_dimension());
30✔
863

864
   vlog_set_loc(v, CURRENT_LOC);
167✔
865
   return v;
167✔
866
}
867

868
static vlog_node_t p_data_type_or_implicit(void)
301✔
869
{
870
   // data_type | implicit_data_type
871

872
   BEGIN("data type or implicit");
602✔
873

874
   if (scan(tREG, tSTRUCT, tUNION, tENUM, tSVINT, tINTEGER, tSVREAL,
301✔
875
            tSHORTREAL, tREALTIME, tLOGIC, tBIT))
876
      return p_data_type();
135✔
877
   else
878
      return p_implicit_data_type();
166✔
879
}
880

881
static vlog_node_t p_net_port_type(void)
90✔
882
{
883
   // [ net_type ] data_type_or_implicit | net_type_identifier
884
   //   | interconnect implicit_data_type
885

886
   BEGIN("net port type");
180✔
887

888
   return p_data_type_or_implicit();
90✔
889
}
890

891
static vlog_node_t p_var_data_type(void)
3✔
892
{
893
   // data_type | var data_type_or_implicit
894

895
   BEGIN("var data type");
6✔
896

897
   return p_data_type();
3✔
898
}
899

900
static vlog_node_t p_variable_port_type(void)
3✔
901
{
902
   // var_data_type
903

904
   BEGIN("variable port type");
6✔
905

906
   return p_var_data_type();
3✔
907
}
908

909
static void p_list_of_port_identifiers(vlog_node_t mod, v_port_kind_t kind,
57✔
910
                                       bool isreg, vlog_node_t datatype)
911
{
912
   // port_identifier { unpacked_dimension }
913
   //    { , port_identifier { unpacked_dimension } }
914

915
   BEGIN("list of port identifiers");
114✔
916

917
   do {
65✔
918
      ident_t id, ext;
65✔
919
      p_external_identifier(&id, &ext);
65✔
920

921
      vlog_node_t v = vlog_new(V_PORT_DECL);
65✔
922
      vlog_set_subkind(v, kind);
65✔
923
      vlog_set_ident(v, id);
65✔
924
      vlog_set_ident2(v, ext);
65✔
925
      vlog_set_type(v, datatype);
65✔
926
      vlog_set_loc(v, &state.last_loc);
65✔
927

928
      vlog_add_decl(mod, v);
65✔
929

930
      if (isreg) {
65✔
931
         vlog_node_t reg = vlog_new(V_VAR_DECL);
3✔
932
         vlog_set_loc(reg, vlog_loc(v));
3✔
933
         vlog_set_ident(reg, id);
3✔
934
         vlog_set_type(reg, datatype);
3✔
935

936
         vlog_add_decl(mod, reg);
3✔
937
      }
938

939
      vlog_node_t ref = vlog_new(V_REF);
65✔
940
      vlog_set_loc(ref, CURRENT_LOC);
65✔
941
      vlog_set_ident(ref, id);
65✔
942
      vlog_set_ref(ref, v);
65✔
943

944
      vlog_add_port(mod, ref);
65✔
945
   } while (optional(tCOMMA));
65✔
946
}
57✔
947

948
static void p_inout_declaration(vlog_node_t mod)
1✔
949
{
950
   // inout net_port_type list_of_port_identifiers
951

952
   BEGIN("inout declaration");
2✔
953

954
   consume(tINOUT);
1✔
955

956
   vlog_node_t dt = p_net_port_type();
1✔
957
   p_list_of_port_identifiers(mod, V_PORT_INOUT, false, dt);
1✔
958
}
1✔
959

960
static void p_input_declaration(vlog_node_t mod)
33✔
961
{
962
   // input net_port_type list_of_port_identifiers
963
   //   | input variable_port_type list_of_variable_identifiers
964

965
   BEGIN("input declaration");
66✔
966

967
   consume(tINPUT);
33✔
968

969
   bool isreg = false;
33✔
970
   vlog_node_t dt;
33✔
971
   switch (peek()) {
33✔
972
   case tREG:
×
973
      dt = p_variable_port_type();
×
974
      isreg = true;
×
975
      break;
×
976
   default:
33✔
977
      dt = p_net_port_type();
33✔
978
      break;
33✔
979
   }
980

981
   p_list_of_port_identifiers(mod, V_PORT_INPUT, isreg, dt);
33✔
982
}
33✔
983

984
static void p_output_declaration(vlog_node_t mod)
23✔
985
{
986
   // output net_port_type list_of_port_identifiers
987
   //   | output variable_port_type list_of_variable_port_identifiers
988

989
   BEGIN("output declaration");
46✔
990

991
   consume(tOUTPUT);
23✔
992

993
   bool isreg = false;
23✔
994
   vlog_node_t dt;
23✔
995
   switch (peek()) {
23✔
996
   case tREG:
3✔
997
      dt = p_variable_port_type();
3✔
998
      isreg = true;
3✔
999
      break;
3✔
1000
   default:
20✔
1001
      dt = p_net_port_type();
20✔
1002
      break;
20✔
1003
   }
1004

1005
   p_list_of_port_identifiers(mod, V_PORT_OUTPUT, isreg, dt);
23✔
1006
}
23✔
1007

1008
static void p_port_declaration(vlog_node_t mod)
57✔
1009
{
1010
   // { attribute_instance } inout_declaration
1011
   //   | { attribute_instance } input_declaration
1012
   //   | { attribute_instance } output_declaration
1013
   //   | { attribute_instance } ref_declaration
1014
   //   | { attribute_instance } interface_port_declaration
1015

1016
   BEGIN("port declaration");
114✔
1017

1018
   switch (peek()) {
57✔
1019
   case tINOUT: p_inout_declaration(mod); break;
1✔
1020
   case tINPUT: p_input_declaration(mod); break;
33✔
1021
   case tOUTPUT: p_output_declaration(mod); break;
23✔
1022
   default: should_not_reach_here();
1023
   }
1024
}
57✔
1025

1026
static vlog_node_t p_net_port_header(v_port_kind_t *kind, bool *isreg)
36✔
1027
{
1028
   // [ port_direction ] net_port_type
1029

1030
   BEGIN("net port header");
72✔
1031

1032
   if (optional(tINPUT)) {
36✔
1033
      *kind = V_PORT_INPUT;
21✔
1034
      *isreg = (peek() == tREG);
21✔
1035
   }
1036
   else if (optional(tINOUT)) {
15✔
1037
      *kind = V_PORT_INOUT;
×
1038
      *isreg = false;
×
1039
   }
1040
   else if (optional(tOUTPUT)) {
15✔
1041
      *kind = V_PORT_OUTPUT;
15✔
1042
      *isreg = (peek() == tREG);
15✔
1043
   }
1044

1045
   return p_net_port_type();
36✔
1046
}
1047

1048
static vlog_node_t p_bit_select(ident_t id)
1,117✔
1049
{
1050
   // { [ expression ] }
1051

1052
   EXTEND("bit select");
2,234✔
1053

1054
   if (peek() == tLSQUARE) {
1,117✔
1055
      vlog_node_t v = vlog_new(V_BIT_SELECT);
13✔
1056
      vlog_set_ident(v, id);
13✔
1057

1058
      while (optional(tLSQUARE)) {
26✔
1059
         vlog_add_param(v, p_expression());
13✔
1060
         consume(tRSQUARE);
13✔
1061
      }
1062

1063
      vlog_set_loc(v, CURRENT_LOC);
13✔
1064
      return v;
13✔
1065
   }
1066
   else {
1067
      vlog_node_t v = vlog_new(V_REF);
1,104✔
1068
      vlog_set_ident(v, id);
1,104✔
1069
      vlog_set_loc(v, CURRENT_LOC);
1,104✔
1070
      return v;
1,104✔
1071
   }
1072
}
1073

1074

1075
static vlog_node_t p_select(ident_t id)
933✔
1076
{
1077
   // [ { . member_identifier bit_select } . member_identifier ]
1078
   //    bit_select [ [ part_select_range ] ]
1079

1080
   EXTEND("select");
1,866✔
1081

1082
   return p_bit_select(id);
933✔
1083
}
1084

1085
static void p_list_of_arguments(vlog_node_t call)
298✔
1086
{
1087
   // [ expression ] { , [ expression ] } { , . identifier ( [ expression ] ) }
1088
   //    | . identifier ( [ expression ] ) { , . identifier ( [ expression ] ) }
1089

1090
   BEGIN("list of arguments");
596✔
1091

1092
   do {
575✔
1093
      if (peek() == tCOMMA) {
575✔
1094
         vlog_node_t v = vlog_new(V_EMPTY);
9✔
1095
         vlog_set_loc(v, &state.last_loc);
9✔
1096
         vlog_add_param(call, v);
9✔
1097
      }
1098
      else
1099
         vlog_add_param(call, p_expression());
566✔
1100
   } while (optional(tCOMMA));
575✔
1101
}
298✔
1102

1103
static vlog_node_t p_system_tf_call(vlog_kind_t kind)
430✔
1104
{
1105
   // system_tf_identifier [ ( list_of_arguments ) ]
1106

1107
   BEGIN("system task or function call");
430✔
1108

1109
   vlog_node_t v = vlog_new(kind);
430✔
1110
   vlog_set_ident(v, p_system_tf_identifier());
430✔
1111

1112
   if (optional(tLPAREN)) {
430✔
1113
      p_list_of_arguments(v);
298✔
1114
      consume(tRPAREN);
298✔
1115
   }
1116

1117
   vlog_set_loc(v, CURRENT_LOC);
430✔
1118
   return v;
430✔
1119
}
1120

1121
static vlog_node_t p_subroutine_call(vlog_kind_t kind)
430✔
1122
{
1123
   // tf_call | system_tf_call | method_call | [ std:: ] randomize_call
1124

1125
   BEGIN("subroutine call");
860✔
1126

1127
   return p_system_tf_call(kind);
430✔
1128
}
1129

1130
static vlog_node_t p_mintypmax_expression(void)
12✔
1131
{
1132
   // expression | expression : expression : expression
1133

1134
   BEGIN("mintypmax expression");
24✔
1135

1136
   return p_expression();
12✔
1137
}
1138

1139
static vlog_node_t p_concatenation(vlog_node_t head)
8✔
1140
{
1141
   // { expression { , expression } }
1142

1143
   BEGIN_WITH_HEAD("concatenation", head);
8✔
1144

1145
   if (head == NULL) {
8✔
1146
      consume(tLBRACE);
2✔
1147
      head = p_expression();
2✔
1148
   }
1149

1150
   vlog_node_t v = vlog_new(V_CONCAT);
8✔
1151
   vlog_add_param(v, head);
8✔
1152

1153
   while (optional(tCOMMA))
14✔
1154
      vlog_add_param(v, p_expression());
6✔
1155

1156
   consume(tRBRACE);
8✔
1157

1158
   vlog_set_loc(v, CURRENT_LOC);
8✔
1159
   return v;
8✔
1160
}
1161

1162
static vlog_node_t p_multiple_concatenation(vlog_node_t head)
2✔
1163
{
1164
   // { expression concatenation }
1165

1166
   BEGIN_WITH_HEAD("multiple concatenation", head);
2✔
1167

1168
   vlog_node_t v = p_concatenation(NULL);
2✔
1169
   vlog_set_value(v, head);
2✔
1170

1171
   consume(tRBRACE);
2✔
1172

1173
   vlog_set_loc(v, CURRENT_LOC);
2✔
1174
   return v;
2✔
1175
}
1176

1177
static vlog_node_t p_primary(void)
1,568✔
1178
{
1179
   // primary_literal | empty_queue
1180
   // | [ class_qualifier | package_scope ] hierarchical_identifier select
1181
   // | concatenation [ [ range_expression ] ]
1182
   // | multiple_concatenation [ [ range_expression ] ]
1183
   // | function_subroutine_call
1184
   // | let_expression | ( mintypmax_expression ) | cast
1185
   // | assignment_pattern_expression | streaming_concatenation
1186
   // | sequence_method_call | this | $ | null
1187

1188
   BEGIN("primary");
3,136✔
1189

1190
   switch (peek()) {
1,568✔
1191
   case tID:
645✔
1192
      return p_select(p_identifier());
645✔
1193
   case tSTRING:
872✔
1194
   case tNUMBER:
1195
   case tUNSIGNED:
1196
   case tREAL:
1197
      return p_primary_literal();
872✔
1198
   case tSYSTASK:
40✔
1199
      return p_subroutine_call(V_SYS_FCALL);
40✔
1200
   case tLPAREN:
3✔
1201
      {
1202
         consume(tLPAREN);
3✔
1203
         vlog_node_t expr = p_mintypmax_expression();
3✔
1204
         consume(tRPAREN);
3✔
1205
         return expr;
3✔
1206
      }
1207
   case tLBRACE:
8✔
1208
      {
1209
         consume(tLBRACE);
8✔
1210

1211
         vlog_node_t head = p_expression();
8✔
1212
         if (peek() == tLBRACE)
8✔
1213
            return p_multiple_concatenation(head);
2✔
1214
         else
1215
            return p_concatenation(head);
6✔
1216
      }
1217
   default:
×
1218
      one_of(tID, tSTRING, tNUMBER, tUNSIGNED, tREAL, tSYSTASK, tLPAREN,
×
1219
             tLBRACE);
1220
      return p_select(error_marker());
×
1221
   }
1222
}
1223

1224
static vlog_binary_t p_binary_operator(void)
217✔
1225
{
1226
   // + | - | * | / | % | == | != | === | !== | ==? | !=? | && | ||
1227
   //  | ** | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | <<
1228
   //  | >>> | <<< | -> | <->
1229

1230
   BEGIN("binary operator");
434✔
1231

1232
   switch (one_of(tBAR, tPLUS, tAMP, tCASEEQ, tCASENEQ, tLOGOR,
217✔
1233
                  tLOGEQ, tLOGNEQ, tDBLAMP, tSHIFTLL, tSHIFTRL,
1234
                  tSHIFTLA, tSHIFTRA, tLT, tGT, tLE, tGE, tMINUS,
1235
                  tTIMES, tOVER, tPERCENT)) {
1236
   case tBAR:     return V_BINARY_OR;
1237
   case tAMP:     return V_BINARY_AND;
18✔
1238
   case tCASEEQ:  return V_BINARY_CASE_EQ;
14✔
1239
   case tCASENEQ: return V_BINARY_CASE_NEQ;
87✔
1240
   case tLOGEQ:   return V_BINARY_LOG_EQ;
9✔
1241
   case tLOGNEQ:  return V_BINARY_LOG_NEQ;
×
1242
   case tLOGOR:   return V_BINARY_LOG_OR;
17✔
1243
   case tDBLAMP:  return V_BINARY_LOG_AND;
4✔
1244
   case tSHIFTLL: return V_BINARY_SHIFT_LL;
1✔
1245
   case tSHIFTRL: return V_BINARY_SHIFT_RL;
1✔
1246
   case tSHIFTLA: return V_BINARY_SHIFT_LA;
1✔
1247
   case tSHIFTRA: return V_BINARY_SHIFT_RA;
1✔
1248
   case tLT:      return V_BINARY_LT;
7✔
1249
   case tGT:      return V_BINARY_GT;
7✔
1250
   case tLE:      return V_BINARY_LEQ;
6✔
1251
   case tGE:      return V_BINARY_GEQ;
6✔
1252
   case tMINUS:   return V_BINARY_MINUS;
4✔
1253
   case tTIMES:   return V_BINARY_TIMES;
2✔
1254
   case tOVER:    return V_BINARY_DIVIDE;
1✔
1255
   case tPERCENT: return V_BINARY_MOD;
1✔
1256
   case tPLUS:
17✔
1257
   default:       return V_BINARY_PLUS;
17✔
1258
   }
1259
}
1260

1261
static vlog_unary_t p_unary_operator(void)
47✔
1262
{
1263
   // + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
1264

1265
   BEGIN("unary operator");
94✔
1266

1267
   switch (one_of(tMINUS, tPLUS, tTILDE, tBANG, tAMP, tBAR, tCARET)) {
47✔
1268
   case tMINUS: return V_UNARY_NEG;
1269
   case tTILDE: return V_UNARY_BITNEG;
21✔
1270
   case tBANG: return V_UNARY_NOT;
18✔
1271
   case tAMP: return V_UNARY_AND;
1✔
1272
   case tBAR: return V_UNARY_OR;
1✔
1273
   case tCARET: return V_UNARY_XOR;
1✔
1274
   case tPLUS:
1✔
1275
   default: return V_UNARY_IDENTITY;
1✔
1276
   }
1277
}
1278

1279
static vlog_incdec_t p_inc_or_dec_operator(void)
2✔
1280
{
1281
   // ++ | --
1282

1283
   BEGIN("inc or dec operator");
4✔
1284

1285
   switch (one_of(tPLUSPLUS, tMINUSMINUS)) {
2✔
1286
   case tMINUSMINUS: return V_INCDEC_MINUS;
1287
   case tPLUSPLUS:
1✔
1288
   default: return V_INCDEC_PLUS;
1✔
1289
   }
1290
}
1291

1292
static vlog_node_t p_inc_or_dec_expression(vlog_node_t head)
2✔
1293
{
1294
   // inc_or_dec_operator { attribute_instance } variable_lvalue
1295
   //   | variable_lvalue { attribute_instance } inc_or_dec_operator
1296

1297
   BEGIN_WITH_HEAD("inc or dec expression", head);
2✔
1298

1299
   vlog_node_t v = vlog_new(head ? V_POSTFIX : V_PREFIX);
3✔
1300
   vlog_set_subkind(v, p_inc_or_dec_operator());
2✔
1301
   vlog_set_target(v, head ?: p_variable_lvalue());
2✔
1302

1303
   vlog_set_loc(v, CURRENT_LOC);
2✔
1304
   return v;
2✔
1305
}
1306

1307
static vlog_node_t p_nonbinary_expression(void)
1,569✔
1308
{
1309
   // primary | unary_operator { attribute_instance } primary
1310
   //   | inc_or_dec_expression | ( operator_assignment )
1311
   //   | conditional_expression | inside_expression | tagged_union_expression
1312

1313
   switch (peek()) {
1,569✔
1314
   case tID:
1,521✔
1315
   case tSTRING:
1316
   case tNUMBER:
1317
   case tUNSIGNED:
1318
   case tREAL:
1319
   case tSYSTASK:
1320
   case tLPAREN:
1321
   case tLBRACE:
1322
      return p_primary();
1,521✔
1323
   case tMINUS:
47✔
1324
   case tPLUS:
1325
   case tTILDE:
1326
   case tBANG:
1327
   case tAMP:
1328
   case tBAR:
1329
   case tCARET:
1330
      {
1331
         vlog_node_t v = vlog_new(V_UNARY);
47✔
1332
         vlog_set_subkind(v, p_unary_operator());
47✔
1333
         vlog_set_value(v, p_primary());
47✔
1334
         vlog_set_loc(v, CURRENT_LOC);
47✔
1335
         return v;
47✔
1336
      }
1337
   case tPLUSPLUS:
×
1338
   case tMINUSMINUS:
1339
      return p_inc_or_dec_expression(NULL);
×
1340
   default:
1✔
1341
      one_of(tID, tSTRING, tNUMBER, tUNSIGNED, tREAL, tSYSTASK, tLPAREN,
1✔
1342
             tLBRACE, tMINUS, tTILDE, tBANG, tAMP, tBAR, tCARET, tPLUSPLUS,
1343
             tMINUSMINUS);
1344
      return p_select(error_marker());
1✔
1345
   }
1346
}
1347

1348
static vlog_node_t p_conditional_expression(vlog_node_t head)
2✔
1349
{
1350
   // cond_predicate ? { attribute_instance } expression : expression
1351

1352
   BEGIN("conditional expression");
2✔
1353

1354
   vlog_node_t v = vlog_new(V_COND_EXPR);
2✔
1355
   vlog_set_value(v, head);
2✔
1356

1357
   consume(tQUESTION);
2✔
1358

1359
   while (peek() == tATTRBEGIN)
2✔
1360
      p_attribute_instance();
×
1361

1362
   vlog_set_left(v, p_expression());
2✔
1363

1364
   consume(tCOLON);
2✔
1365

1366
   vlog_set_right(v, p_expression());
2✔
1367

1368
   vlog_set_loc(v, CURRENT_LOC);
2✔
1369
   return v;
2✔
1370
}
1371

1372
static bool peek_binary_operator(int *prec)
1,838✔
1373
{
1374
   // See LRM 1800-2017 section 11.3.2 for operator precedence table
1375

1376
   switch (peek()) {
1,838✔
1377
   case tTIMES:
7✔
1378
   case tOVER:
1379
   case tPERCENT:  *prec = 11; return true;
7✔
1380
   case tPLUS:
25✔
1381
   case tMINUS:    *prec = 10; return true;
25✔
1382
   case tSHIFTLL:
4✔
1383
   case tSHIFTRL:
1384
   case tSHIFTLA:
1385
   case tSHIFTRA:  *prec = 9;  return true;
4✔
1386
   case tLT:
26✔
1387
   case tGT:
1388
   case tLE:
1389
   case tGE:       *prec = 8;  return true;
26✔
1390
   case tCASEEQ:
131✔
1391
   case tCASENEQ:
1392
   case tLOGEQ:
1393
   case tLOGNEQ:   *prec = 7;  return true;
131✔
1394
   case tAMP:      *prec = 6;  return true;
19✔
1395
   case tBAR:      *prec = 4;  return true;
14✔
1396
   case tDBLAMP:   *prec = 3;  return true;
7✔
1397
   case tLOGOR:    *prec = 2;  return true;
33✔
1398
   case tQUESTION: *prec = 1;  return true;
2✔
1399
   default:
1400
      return false;
1401
   }
1402
}
1403

1404
static vlog_node_t p_binary_expression(vlog_node_t lhs, int min_prec)
1,377✔
1405
{
1406
   // Precedence climbing method, see
1407
   //    https://en.wikipedia.org/wiki/Operator-precedence_parser
1408

1409
   int prec1;
1,377✔
1410
   while (peek_binary_operator(&prec1) && prec1 >= min_prec) {
1,596✔
1411
      if (peek() == tQUESTION)
219✔
1412
         lhs = p_conditional_expression(lhs);
2✔
1413
      else {
1414
         vlog_node_t v = vlog_new(V_BINARY);
217✔
1415
         vlog_set_subkind(v, p_binary_operator());
217✔
1416
         vlog_set_left(v, lhs);
217✔
1417

1418
         vlog_node_t rhs = p_nonbinary_expression();
217✔
1419

1420
         int prec2;
217✔
1421
         while (peek_binary_operator(&prec2) && prec2 > prec1)
242✔
1422
            rhs = p_binary_expression(rhs, prec1 + (prec2 > prec1));
25✔
1423

1424
         vlog_set_right(v, rhs);
217✔
1425
         vlog_set_loc(v, CURRENT_LOC);
217✔
1426
         lhs = v;
217✔
1427
      }
1428
   }
1429

1430
   return lhs;
1,377✔
1431
}
1432

1433
static vlog_node_t p_expression(void)
1,352✔
1434
{
1435
   // primary | unary_operator { attribute_instance } primary
1436
   //   | inc_or_dec_expression | ( operator_assignment )
1437
   //   | expression binary_operator { attribute_instance } expression
1438
   //   | conditional_expression | inside_expression | tagged_union_expression
1439

1440
   BEGIN("expression");
2,704✔
1441

1442
   vlog_node_t head = p_nonbinary_expression();
1,352✔
1443
   return p_binary_expression(head, 0);
1,352✔
1444
}
1445

1446
static void p_event_expression(vlog_node_t ctrl)
71✔
1447
{
1448
   // [ edge_identifier ] expression [ iff expression ]
1449
   //   | sequence_instance [ iff expression ]
1450
   //   | event_expression or event_expression
1451
   //   | event_expression , event_expression
1452
   //   | ( event_expression )
1453

1454
   BEGIN("event expression");
142✔
1455

1456
   do {
91✔
1457
      if (optional(tLPAREN)) {
91✔
1458
         p_event_expression(ctrl);
1✔
1459
         consume(tRPAREN);
1✔
1460
      }
1461
      else {
1462
         vlog_node_t v = vlog_new(V_EVENT);
90✔
1463

1464
         if (optional(tPOSEDGE))
90✔
1465
            vlog_set_subkind(v, V_EVENT_POSEDGE);
23✔
1466
         else if (optional(tNEGEDGE))
67✔
1467
            vlog_set_subkind(v, V_EVENT_NEGEDGE);
3✔
1468
         else
1469
            vlog_set_subkind(v, V_EVENT_LEVEL);
64✔
1470

1471
         vlog_set_value(v, p_expression());
90✔
1472
         vlog_set_loc(v, CURRENT_LOC);
90✔
1473

1474
         vlog_add_param(ctrl, v);
90✔
1475
      }
1476
   } while (optional(tOR) || optional(tCOMMA));
91✔
1477
}
71✔
1478

1479
static vlog_node_t p_cond_predicate(void)
126✔
1480
{
1481
   // expression_or_cond_pattern { &&& expression_or_cond_pattern }
1482

1483
   BEGIN("cond predicate");
252✔
1484

1485
   return p_expression();
126✔
1486
}
1487

1488
static vlog_node_t p_event_control(void)
70✔
1489
{
1490
   // @ hierarchical_event_identifier | @ ( event_expression )
1491
   //    | @* | @ (*) | @ ps_or_hierarchical_sequence_identifier
1492

1493
   BEGIN("event control");
70✔
1494

1495
   consume(tAT);
70✔
1496
   consume(tLPAREN);
70✔
1497

1498
   vlog_node_t v = vlog_new(V_EVENT_CONTROL);
70✔
1499

1500
   p_event_expression(v);
70✔
1501

1502
   consume(tRPAREN);
70✔
1503

1504
   vlog_set_loc(v, CURRENT_LOC);
70✔
1505
   return v;
70✔
1506
}
1507

1508
static vlog_node_t p_delay_value(void)
183✔
1509
{
1510
   // unsigned_number | real_number | ps_identifier | time_literal | 1step
1511

1512
   BEGIN("delay value");
366✔
1513

1514
   return p_unsigned_number();
183✔
1515
}
1516

1517
static vlog_node_t p_delay_control(void)
183✔
1518
{
1519
   // # delay_value | # ( mintypmax_expression )
1520

1521
   BEGIN("delay control");
183✔
1522

1523
   consume(tHASH);
183✔
1524

1525
   vlog_node_t v = vlog_new(V_DELAY_CONTROL);
183✔
1526
   vlog_set_value(v, p_delay_value());
183✔
1527
   vlog_set_loc(v, CURRENT_LOC);
183✔
1528
   return v;
183✔
1529
}
1530

1531
static vlog_node_t p_delay_or_event_control(void)
38✔
1532
{
1533
   // delay_control | event_control | repeat ( expression ) event_control
1534

1535
   BEGIN("delay or event control");
76✔
1536

1537
   return p_delay_control();
38✔
1538
}
1539

1540
static vlog_node_t p_variable_lvalue(void)
287✔
1541
{
1542
   // [ implicit_class_handle . | package_scope ]
1543
   //      hierarchical_variable_identifier select
1544
   //   | { variable_lvalue { , variable_lvalue } }
1545
   //   | [ assignment_pattern_expression_type ]
1546
   //      assignment_pattern_variable_lvalue
1547
   //   | streaming_concatenation
1548

1549
   BEGIN("variable lvalue");
287✔
1550

1551
   ident_t id = p_identifier();
287✔
1552
   vlog_node_t v = p_select(id);
287✔
1553

1554
   vlog_set_loc(v, CURRENT_LOC);
287✔
1555
   return v;
287✔
1556
}
1557

1558
static vlog_node_t p_net_lvalue(void)
123✔
1559
{
1560
   // ps_or_hierarchical_net_identifier constant_select
1561
   //   | { net_lvalue { , net_lvalue } }
1562
   //   | [ assignment_pattern_expression_type ] assignment_pattern_net_lvalue
1563

1564
   BEGIN("net lvalue");
246✔
1565

1566
   if (optional(tLBRACE)) {
123✔
1567
      vlog_node_t v = vlog_new(V_CONCAT);
3✔
1568

1569
      do {
6✔
1570
         vlog_add_param(v, p_net_lvalue());
6✔
1571
      } while (optional(tCOMMA));
6✔
1572

1573
      consume(tRBRACE);
3✔
1574

1575
      vlog_set_loc(v, CURRENT_LOC);
3✔
1576
      return v;
3✔
1577
   }
1578
   else {
1579
      ident_t id = p_identifier();
120✔
1580
      vlog_node_t v = p_constant_select(id);
120✔
1581

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

1587
static vlog_node_t p_operator_assignment(vlog_node_t lhs)
177✔
1588
{
1589
   // variable_lvalue assignment_operator expression
1590

1591
   BEGIN_WITH_HEAD("operator assignment", lhs);
177✔
1592

1593
   consume(tEQ);
177✔
1594

1595
   vlog_node_t v = vlog_new(V_BASSIGN);
177✔
1596
   vlog_set_target(v, lhs);
177✔
1597

1598
   vlog_set_value(v, p_expression());
177✔
1599

1600
   vlog_set_loc(v, CURRENT_LOC);
177✔
1601
   return v;
177✔
1602
}
1603

1604
static vlog_node_t p_blocking_assignment(vlog_node_t lhs)
201✔
1605
{
1606
   // variable_lvalue = delay_or_event_control expression
1607
   //   | nonrange_variable_lvalue = dynamic_array_new
1608
   //   | [ implicit_class_handle . | class_scope | package_scope ]
1609
   //         hierarchical_variable_identifier select != class_new
1610
   //   | operator_assignment
1611

1612
   BEGIN_WITH_HEAD("blocking assignment", lhs);
402✔
1613

1614
   switch (peek_nth(2)) {
201✔
1615
   case tHASH:
25✔
1616
   case tAT:
1617
      {
1618
         consume(tEQ);
25✔
1619

1620
         vlog_node_t v = vlog_new(V_BASSIGN);
25✔
1621
         vlog_set_target(v, lhs);
25✔
1622
         vlog_set_delay(v, p_delay_or_event_control());
25✔
1623
         vlog_set_value(v, p_expression());
25✔
1624

1625
         vlog_set_loc(v, CURRENT_LOC);
25✔
1626
         return v;
25✔
1627
      }
1628
   default:
176✔
1629
      return p_operator_assignment(lhs);
176✔
1630
   }
1631
}
1632

1633
static vlog_node_t p_nonblocking_assignment(vlog_node_t lhs)
82✔
1634
{
1635
   // variable_lvalue <= [ delay_or_event_control ] expression
1636

1637
   BEGIN_WITH_HEAD("non-blocking assignment", lhs);
82✔
1638

1639
   consume(tLE);
82✔
1640

1641
   vlog_node_t v = vlog_new(V_NBASSIGN);
82✔
1642
   vlog_set_target(v, lhs);
82✔
1643

1644
   if (scan(tHASH, tAT))
82✔
1645
      vlog_set_delay(v, p_delay_or_event_control());
13✔
1646

1647
   vlog_set_value(v, p_expression());
82✔
1648

1649
   vlog_set_loc(v, CURRENT_LOC);
82✔
1650
   return v;
82✔
1651
}
1652

1653
static vlog_node_t p_procedural_timing_control(void)
215✔
1654
{
1655
   // delay_control | event_control | cycle_delay
1656

1657
   BEGIN("procedural timing control");
430✔
1658

1659
   switch (peek()) {
215✔
1660
   case tAT:
70✔
1661
      return p_event_control();
70✔
1662
   case tHASH:
145✔
1663
      return p_delay_control();
145✔
1664
   default:
×
1665
      should_not_reach_here();
1666
   }
1667
}
1668

1669
static vlog_node_t p_procedural_timing_control_statement(void)
215✔
1670
{
1671
   // procedural_timing_control statement_or_null
1672

1673
   BEGIN("procedural timing control statement");
215✔
1674

1675
   vlog_node_t v = vlog_new(V_TIMING);
215✔
1676
   vlog_set_value(v, p_procedural_timing_control());
215✔
1677

1678
   vlog_node_t s = p_statement_or_null();
215✔
1679
   if (s != NULL)
215✔
1680
      vlog_add_stmt(v, s);
134✔
1681

1682
   vlog_set_loc(v, CURRENT_LOC);
215✔
1683
   return v;
215✔
1684
}
1685

1686
static vlog_node_t p_seq_block(void)
186✔
1687
{
1688
   // begin [ : block_identifier ] { block_item_declaration }
1689
   //   { statement_or_null } end [ : block_identifier ]
1690

1691
   BEGIN("sequential block");
186✔
1692

1693
   consume(tBEGIN);
186✔
1694

1695
   vlog_node_t v = vlog_new(V_SEQ_BLOCK);
186✔
1696

1697
   if (optional(tCOLON))
186✔
1698
      vlog_set_ident(v, p_identifier());
1✔
1699

1700
   while (not_at_token(tEND)) {
946✔
1701
      vlog_node_t s = p_statement_or_null();
760✔
1702
      if (s != NULL)
760✔
1703
         vlog_add_stmt(v, s);
760✔
1704
   }
1705

1706
   consume(tEND);
186✔
1707

1708
   vlog_set_loc(v, CURRENT_LOC);
186✔
1709
   return v;
186✔
1710
}
1711

1712
static vlog_node_t p_subroutine_call_statement(void)
390✔
1713
{
1714
   // subroutine_call ; | void ' ( function_subroutine_call ) ;
1715

1716
   BEGIN("subroutine call statement");
390✔
1717

1718
   vlog_node_t v = p_subroutine_call(V_SYS_TCALL);
390✔
1719

1720
   consume(tSEMI);
390✔
1721

1722
   vlog_set_loc(v, CURRENT_LOC);
390✔
1723
   return v;
390✔
1724
}
1725

1726
static vlog_node_t p_conditional_statement(void)
122✔
1727
{
1728
   // [ unique_priority ] if ( cond_predicate ) statement_or_null
1729
   //     { else if ( cond_predicate ) statement_or_null }
1730
   //     [ else statement_or_null ]
1731

1732
   BEGIN("conditional statement");
122✔
1733

1734
   vlog_node_t v = vlog_new(V_IF);
122✔
1735

1736
   consume(tIF);
122✔
1737
   consume(tLPAREN);
122✔
1738

1739
   vlog_node_t c0 = vlog_new(V_COND);
122✔
1740
   vlog_set_value(c0, p_cond_predicate());
122✔
1741
   vlog_add_cond(v, c0);
122✔
1742

1743
   consume(tRPAREN);
122✔
1744

1745
   vlog_node_t s0 = p_statement_or_null();
122✔
1746
   if (s0 != NULL)
122✔
1747
      vlog_add_stmt(c0, s0);
117✔
1748

1749
   bool stop = false;
1750
   while (!stop && optional(tELSE)) {
163✔
1751
      vlog_node_t c = vlog_new(V_COND);
41✔
1752
      vlog_add_cond(v, c);
41✔
1753

1754
      if (optional(tIF)) {
41✔
1755
         consume(tLPAREN);
4✔
1756
         vlog_set_value(c, p_cond_predicate());
4✔
1757
         consume(tRPAREN);
4✔
1758
      }
1759
      else
1760
         stop = true;
1761

1762
      vlog_node_t s = p_statement_or_null();
41✔
1763
      if (s != NULL)
41✔
1764
         vlog_add_stmt(c, s);
40✔
1765
   }
1766

1767
   vlog_set_loc(v, CURRENT_LOC);
122✔
1768
   return v;
122✔
1769
}
1770

1771
static vlog_node_t p_variable_assignment(vlog_kind_t kind)
1✔
1772
{
1773
   // variable_lvalue = expression
1774

1775
   BEGIN("variable assignment");
1✔
1776

1777
   vlog_node_t v = vlog_new(kind);
1✔
1778
   vlog_set_target(v, p_variable_lvalue());
1✔
1779

1780
   consume(tEQ);
1✔
1781

1782
   vlog_set_value(v, p_expression());
1✔
1783

1784
   vlog_set_loc(v, CURRENT_LOC);
1✔
1785
   return v;
1✔
1786
}
1787

1788
static void p_list_of_variable_assignments(vlog_node_t parent)
1✔
1789
{
1790
   // variable_assignment { , variable_assignment }
1791

1792
   BEGIN("list of variable assignments");
2✔
1793

1794
   do {
1✔
1795
      vlog_node_t v = p_variable_assignment(V_BASSIGN);
1✔
1796
      vlog_add_stmt(parent, v);
1✔
1797
   } while (optional(tCOMMA));
1✔
1798
}
1✔
1799

1800
static void p_for_variable_declaration(vlog_node_t parent)
2✔
1801
{
1802
   // [ var ] data_type variable_identifier = expression
1803
   //   { , variable_identifier = expression }
1804

1805
   BEGIN("for variable declaration");
4✔
1806

1807
   optional(tVAR);
2✔
1808

1809
   vlog_node_t dt = p_data_type();
2✔
1810

1811
   do {
2✔
1812
      vlog_node_t v = vlog_new(V_VAR_DECL);
2✔
1813
      vlog_set_ident(v, p_identifier());
2✔
1814
      vlog_set_type(v, dt);
2✔
1815

1816
      consume(tEQ);
2✔
1817

1818
      vlog_set_value(v, p_expression());
2✔
1819

1820
      vlog_set_loc(v, CURRENT_LOC);
2✔
1821
      vlog_add_decl(parent, v);
2✔
1822
   } while (optional(tCOMMA));
2✔
1823
}
2✔
1824

1825
static vlog_node_t p_for_initialization(void)
3✔
1826
{
1827
   // list_of_variable_assignments
1828
   //   | for_variable_declaration { , for_variable_declaration }
1829

1830
   BEGIN("for initialization");
3✔
1831

1832
   vlog_node_t v = vlog_new(V_FOR_INIT);
3✔
1833

1834
   if (scan(tREG, tSTRUCT, tUNION, tENUM, tSVINT, tINTEGER, tSVREAL,
3✔
1835
            tSHORTREAL, tREALTIME, tLOGIC, tVAR)) {
1836
      do {
2✔
1837
         p_for_variable_declaration(v);
2✔
1838
      } while (optional(tCOMMA));
2✔
1839
   }
1840
   else
1841
      p_list_of_variable_assignments(v);
1✔
1842

1843
   vlog_set_loc(v, CURRENT_LOC);
3✔
1844
   return v;
3✔
1845
}
1846

1847
static vlog_node_t p_for_step(void)
3✔
1848
{
1849
   // operator_assignment | inc_or_dec_expression | function_subroutine_call
1850

1851
   BEGIN("for step");
3✔
1852

1853
   vlog_node_t v = vlog_new(V_FOR_STEP);
3✔
1854

1855
   switch (peek()) {
3✔
1856
   case tPLUSPLUS:
1✔
1857
   case tMINUSMINUS:
1858
      vlog_add_stmt(v, p_inc_or_dec_expression(NULL));
1✔
1859
      break;
1✔
1860
   default:
2✔
1861
      {
1862
         vlog_node_t head = p_variable_lvalue();
2✔
1863

1864
         switch (peek()) {
2✔
1865
         case tPLUSPLUS:
1✔
1866
         case tMINUSMINUS:
1867
            vlog_add_stmt(v, p_inc_or_dec_expression(head));
1✔
1868
            break;
1✔
1869
         default:
1✔
1870
            vlog_add_stmt(v, p_operator_assignment(head));
1✔
1871
            break;
1✔
1872
         }
1873
      }
1874
      break;
1875
   }
1876

1877
   vlog_set_loc(v, CURRENT_LOC);
3✔
1878
   return v;
3✔
1879
}
1880

1881
static vlog_node_t p_loop_statement(void)
13✔
1882
{
1883
   // forever statement_or_null
1884
   //   | repeat ( expression ) statement_or_null
1885
   //   | while ( expression ) statement_or_null
1886
   //   | for ( [ for_initialization ] ; [ expression ] ; [ for_step ] )
1887
   //       statement_or_null
1888
   //   | do statement_or_null while ( expression ) ;
1889
   //   | foreach ( ps_or_hierarchical_array_identifier [ loop_variables ] )
1890
   //       statement
1891

1892
   BEGIN("loop statement");
26✔
1893

1894
   switch (one_of(tFOREVER, tWHILE, tREPEAT, tDO, tFOR)) {
13✔
1895
   case tFOREVER:
3✔
1896
      {
1897
         vlog_node_t v = vlog_new(V_FOREVER);
3✔
1898

1899
         vlog_node_t s = p_statement_or_null();
3✔
1900
         if (s != NULL)
3✔
1901
            vlog_add_stmt(v, s);
3✔
1902

1903
         vlog_set_loc(v, CURRENT_LOC);
3✔
1904
         return v;
3✔
1905
      }
1906

1907
   case tWHILE:
2✔
1908
      {
1909
         vlog_node_t v = vlog_new(V_WHILE);
2✔
1910

1911
         consume(tLPAREN);
2✔
1912
         vlog_set_value(v, p_expression());
2✔
1913
         consume(tRPAREN);
2✔
1914

1915
         vlog_node_t s = p_statement_or_null();
2✔
1916
         if (s != NULL)
2✔
1917
            vlog_add_stmt(v, s);
×
1918

1919
         vlog_set_loc(v, CURRENT_LOC);
2✔
1920
         return v;
2✔
1921
      }
1922

1923
   case tREPEAT:
2✔
1924
      {
1925
         vlog_node_t v = vlog_new(V_REPEAT);
2✔
1926

1927
         consume(tLPAREN);
2✔
1928
         vlog_set_value(v, p_expression());
2✔
1929
         consume(tRPAREN);
2✔
1930

1931
         vlog_node_t s = p_statement_or_null();
2✔
1932
         if (s != NULL)
2✔
1933
            vlog_add_stmt(v, s);
2✔
1934

1935
         vlog_set_loc(v, CURRENT_LOC);
2✔
1936
         return v;
2✔
1937
      }
1938

1939
   case tDO:
2✔
1940
      {
1941
         vlog_node_t v = vlog_new(V_DO_WHILE);
2✔
1942

1943
         vlog_node_t s = p_statement_or_null();
2✔
1944
         if (s != NULL)
2✔
1945
            vlog_add_stmt(v, s);
2✔
1946

1947
         consume(tWHILE);
2✔
1948

1949
         consume(tLPAREN);
2✔
1950
         vlog_set_value(v, p_expression());
2✔
1951
         consume(tRPAREN);
2✔
1952
         consume(tSEMI);
2✔
1953

1954
         vlog_set_loc(v, CURRENT_LOC);
2✔
1955
         return v;
2✔
1956
      }
1957

1958
   case tFOR:
4✔
1959
      {
1960
         vlog_node_t v = vlog_new(V_FOR_LOOP);
4✔
1961

1962
         consume(tLPAREN);
4✔
1963

1964
         if (not_at_token(tSEMI))
4✔
1965
            vlog_set_left(v, p_for_initialization());
3✔
1966
         else
1967
            vlog_set_left(v, vlog_new(V_FOR_INIT));
1✔
1968

1969
         consume(tSEMI);
4✔
1970

1971
         if (not_at_token(tSEMI))
4✔
1972
            vlog_set_value(v, p_expression());
2✔
1973

1974
         consume(tSEMI);
4✔
1975

1976
         if (not_at_token(tRPAREN))
4✔
1977
            vlog_set_right(v, p_for_step());
3✔
1978
         else
1979
            vlog_set_right(v, vlog_new(V_FOR_STEP));
1✔
1980

1981
         consume(tRPAREN);
4✔
1982

1983
         vlog_node_t s = p_statement_or_null();
4✔
1984
         if (s != NULL)
4✔
1985
            vlog_add_stmt(v, s);
1✔
1986

1987
         vlog_set_loc(v, CURRENT_LOC);
4✔
1988
         return v;
4✔
1989
      }
1990

1991
   default:
×
1992
      should_not_reach_here();
1993
   }
1994
}
1995

1996
static vlog_node_t p_wait_statement(void)
1✔
1997
{
1998
   // wait ( expression ) statement_or_null
1999
   //   | wait fork ;
2000
   //   | wait_order ( hierarchical_identifier { , hierarchical_identifier } )
2001
   //       action_block
2002

2003
   BEGIN("wait statement");
1✔
2004

2005
   consume(tWAIT);
1✔
2006

2007
   vlog_node_t v = vlog_new(V_WAIT);
1✔
2008

2009
   consume(tLPAREN);
1✔
2010

2011
   vlog_set_value(v, p_expression());
1✔
2012

2013
   consume(tRPAREN);
1✔
2014

2015
   vlog_node_t s = p_statement_or_null();
1✔
2016
   if (s != NULL)
1✔
2017
      vlog_add_stmt(v, s);
1✔
2018

2019
   vlog_set_loc(v, CURRENT_LOC);
1✔
2020
   return v;
1✔
2021
}
2022

2023
static vlog_node_t p_statement_item(void)
1,210✔
2024
{
2025
   // blocking_assignment ; | nonblocking_assignment ;
2026
   //   | procedural_continuous_assignment ; | case_statement
2027
   //   | conditional_statement | inc_or_dec_expression ;
2028
   //   | subroutine_call_statement | disable_statement
2029
   //   | event_trigger | loop_statement | jump_statement
2030
   //   | par_block | procedural_timing_control_statement
2031
   //   | seq_block | wait_statement | procedural_assertion_statement
2032
   //   | clocking_drive ; | randsequence_statement | randcase_statement
2033
   //   | expect_property_statement
2034

2035
   BEGIN("statement item");
2,420✔
2036

2037
   switch (peek()) {
1,210✔
2038
   case tID:
283✔
2039
      {
2040
         vlog_node_t lhs = p_variable_lvalue(), v = NULL;
283✔
2041

2042
         if (peek() == tLE)
283✔
2043
            v = p_nonblocking_assignment(lhs);
82✔
2044
         else
2045
            v = p_blocking_assignment(lhs);
201✔
2046

2047
         consume(tSEMI);
283✔
2048
         return v;
283✔
2049
      }
2050
   case tAT:
215✔
2051
   case tHASH:
2052
      return p_procedural_timing_control_statement();
215✔
2053
   case tBEGIN:
186✔
2054
      return p_seq_block();
186✔
2055
   case tSYSTASK:
390✔
2056
      return p_subroutine_call_statement();
390✔
2057
   case tIF:
122✔
2058
      return p_conditional_statement();
122✔
2059
   case tFOREVER:
13✔
2060
   case tWHILE:
2061
   case tREPEAT:
2062
   case tDO:
2063
   case tFOR:
2064
      return p_loop_statement();
13✔
2065
   case tWAIT:
1✔
2066
      return p_wait_statement();
1✔
2067
   default:
×
2068
      one_of(tID, tAT, tHASH, tBEGIN, tSYSTASK, tIF, tFOREVER, tWHILE, tREPEAT,
×
2069
             tDO, tFOR, tWAIT);
2070
      drop_tokens_until(tSEMI);
×
2071
      return NULL;
×
2072
   }
2073
}
2074

2075
static vlog_node_t p_statement(void)
1,210✔
2076
{
2077
   // [ block_identifier : ] { attribute_instance } statement_item
2078

2079
   BEGIN("statement");
2,420✔
2080

2081
   while (peek() == tATTRBEGIN)
1,210✔
2082
      p_attribute_instance();
×
2083

2084
   vlog_node_t s = p_statement_item();
1,210✔
2085
   if (s == NULL)
1,210✔
2086
      return vlog_new(V_SEQ_BLOCK);
×
2087

2088
   return s;
2089
}
2090

2091
static vlog_node_t p_statement_or_null(void)
1,229✔
2092
{
2093
   // statement | { attribute_instance } ;
2094

2095
   BEGIN("statement or null");
2,458✔
2096

2097
   if (optional(tSEMI))
1,229✔
2098
      return NULL;
2099
   else
2100
      return p_statement();
1,137✔
2101
}
2102

2103
static vlog_node_t p_always_construct(void)
73✔
2104
{
2105
   // always_keyword statement
2106

2107
   BEGIN("always construct");
73✔
2108

2109
   consume(tALWAYS);
73✔
2110

2111
   vlog_node_t v = vlog_new(V_ALWAYS);
73✔
2112
   vlog_set_ident(v, ident_uniq("__always#line%d", yylloc.first_line));
73✔
2113
   vlog_add_stmt(v, p_statement());
73✔
2114

2115
   vlog_set_loc(v, CURRENT_LOC);
73✔
2116
   return v;
73✔
2117
}
2118

2119
static vlog_node_t p_initial_construct(void)
74✔
2120
{
2121
   // initial statement_or_null
2122

2123
   BEGIN("initial construct");
74✔
2124

2125
   consume(tINITIAL);
74✔
2126

2127
   vlog_node_t v = vlog_new(V_INITIAL);
74✔
2128
   vlog_set_ident(v, ident_uniq("__initial#line%d", yylloc.first_line));
74✔
2129

2130
   vlog_node_t s = p_statement_or_null();
74✔
2131
   if (s != NULL)
74✔
2132
      vlog_add_stmt(v, s);
74✔
2133

2134
   vlog_set_loc(v, CURRENT_LOC);
74✔
2135
   return v;
74✔
2136
}
2137

2138
static vlog_node_t p_net_assignment(void)
51✔
2139
{
2140
   // net_lvalue = expression
2141

2142
   BEGIN("net assignment");
51✔
2143

2144
   vlog_node_t v = vlog_new(V_ASSIGN);
51✔
2145
   vlog_set_target(v, p_net_lvalue());
51✔
2146
   vlog_set_ident(v, ident_uniq("__assign#line%d", state.last_loc.first_line));
51✔
2147

2148
   consume(tEQ);
51✔
2149

2150
   vlog_set_value(v, p_expression());
51✔
2151

2152
   vlog_set_loc(v, CURRENT_LOC);
51✔
2153
   return v;
51✔
2154
}
2155

2156
static void p_list_of_net_assignments(vlog_node_t mod)
51✔
2157
{
2158
   // net_assignment { , net_assignment }
2159

2160
   BEGIN("list of net assignments");
102✔
2161

2162
   do {
51✔
2163
      vlog_add_stmt(mod, p_net_assignment());
51✔
2164
   } while (optional(tCOMMA));
51✔
2165
}
51✔
2166

2167
static void p_continuous_assign(vlog_node_t mod)
51✔
2168
{
2169
   // assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;
2170
   //   | assign [ delay_control ] list_of_variable_assignments ;
2171

2172
   BEGIN("continuous assignment");
102✔
2173

2174
   consume(tASSIGN);
51✔
2175

2176
   p_list_of_net_assignments(mod);
51✔
2177

2178
   consume(tSEMI);
51✔
2179
}
51✔
2180

2181
static vlog_net_kind_t p_net_type(void)
80✔
2182
{
2183
   // supply0 | supply1 | tri | triand | trior | trireg | tri0
2184
   //   | tri1 | uwire | wire | wand | wor
2185

2186
   BEGIN("net type");
160✔
2187

2188
   switch (one_of(tWIRE, tSUPPLY0, tSUPPLY1)) {
80✔
2189
   case tSUPPLY0: return V_NET_SUPPLY0;
2190
   case tSUPPLY1: return V_NET_SUPPLY1;
3✔
2191
   case tWIRE:
71✔
2192
   default: return V_NET_WIRE;
71✔
2193
   }
2194
}
2195

2196
static vlog_node_t p_net_decl_assignment(vlog_net_kind_t kind,
98✔
2197
                                         vlog_node_t datatype)
2198
{
2199
   // net_identifier { unpacked_dimension } [ = expression ]
2200

2201
   BEGIN("net declaration assignment");
98✔
2202

2203
   vlog_node_t v = vlog_new(V_NET_DECL);
98✔
2204
   vlog_set_subkind(v, kind);
98✔
2205
   vlog_set_type(v, datatype);
98✔
2206
   vlog_set_ident(v, p_identifier());
98✔
2207

2208
   while (peek() == tLSQUARE)
99✔
2209
      vlog_add_range(v, p_unpacked_dimension());
1✔
2210

2211
   if (optional(tEQ))
98✔
2212
      vlog_set_value(v, p_expression());
10✔
2213

2214
   vlog_set_loc(v, CURRENT_LOC);
98✔
2215
   return v;
98✔
2216
}
2217

2218
static void p_list_of_net_decl_assignments(vlog_node_t mod,
80✔
2219
                                           vlog_net_kind_t kind,
2220
                                           vlog_node_t datatype)
2221
{
2222
   // net_decl_assignment { , net_decl_assignment }
2223

2224
   BEGIN("list of net declaration assignments");
160✔
2225

2226
   do {
98✔
2227
      vlog_node_t v = p_net_decl_assignment(kind, datatype);
98✔
2228
      vlog_add_decl(mod, v);
98✔
2229
   } while (optional(tCOMMA));
98✔
2230
}
80✔
2231

2232
static void p_net_declaration(vlog_node_t mod)
80✔
2233
{
2234
   // net_type [ drive_strength | charge_strength ] [ vectored | scalared ]
2235
   //     data_type_or_implicit [ delay3 ] list_of_net_decl_assignments ;
2236
   //  | net_type_identifier [ delay_control ] list_of_net_decl_assignments ;
2237
   //  | interconnect implicit_data_type [ # delay_value ] net_identifier
2238
   //     { unpacked_dimension } [ , net_identifier { unpacked_dimension } ] ;
2239

2240
   BEGIN("net declaration");
160✔
2241

2242
   const vlog_net_kind_t kind = p_net_type();
80✔
2243

2244
   vlog_node_t dt = p_data_type_or_implicit();
80✔
2245
   p_list_of_net_decl_assignments(mod, kind, dt);
80✔
2246

2247
   consume(tSEMI);
80✔
2248
}
80✔
2249

2250
static vlog_node_t p_variable_dimension(void)
2✔
2251
{
2252
   // unsized_dimension | unpacked_dimension | associative_dimension
2253
   //   | queue_dimension
2254

2255
   BEGIN("variable dimension");
4✔
2256

2257
   return p_unpacked_dimension();
2✔
2258
}
2259

2260
static vlog_node_t p_variable_decl_assignment(vlog_node_t datatype)
149✔
2261
{
2262
   // variable_identifier { variable_dimension } [ = expression ]
2263
   //   | dynamic_array_variable_identifier unsized_dimension
2264
   //       { variable_dimension } [ = dynamic_array_new ]
2265
   //   | class_variable_identifier [ = class_new ]
2266

2267
   BEGIN("variable declaration assignment");
149✔
2268

2269
   vlog_node_t v = vlog_new(V_VAR_DECL);
149✔
2270
   vlog_set_ident(v, p_identifier());
149✔
2271
   vlog_set_type(v, datatype);
149✔
2272

2273
   while (peek() == tLSQUARE)
151✔
2274
      vlog_add_range(v, p_variable_dimension());
2✔
2275

2276
   if (optional(tEQ))
149✔
2277
      vlog_set_value(v, p_expression());
7✔
2278

2279
   vlog_set_loc(v, CURRENT_LOC);
149✔
2280
   return v;
149✔
2281
}
2282

2283
static void p_list_of_variable_decl_assignments(vlog_node_t parent,
127✔
2284
                                                vlog_node_t datatype)
2285
{
2286
   // variable_decl_assignment { , variable_decl_assignment }
2287

2288
   BEGIN("list of variable declaration assignments");
254✔
2289

2290
   do {
149✔
2291
      vlog_add_decl(parent, p_variable_decl_assignment(datatype));
149✔
2292
   } while (optional(tCOMMA));
149✔
2293
}
127✔
2294

2295
static vlog_node_t p_type_declaration(void)
3✔
2296
{
2297
   // typedef data_type type_identifier { variable_dimension } ;
2298
   //   | typedef interface_instance_identifier constant_bit_select .
2299
   //       type_identifier type_identifier ;
2300
   //   | typedef [ enum | struct | union | class | interface class ]
2301
   //       type_identifier ;
2302

2303
   BEGIN("type declaration");
3✔
2304

2305
   consume(tTYPEDEF);
3✔
2306

2307
   vlog_node_t v = vlog_new(V_TYPE_DECL);
3✔
2308
   vlog_set_type(v, p_data_type());
3✔
2309
   vlog_set_ident(v, p_identifier());
3✔
2310

2311
   consume(tSEMI);
3✔
2312

2313
   vlog_set_loc(v, CURRENT_LOC);
3✔
2314
   return v;
3✔
2315
}
2316

2317
static void p_data_declaration(vlog_node_t mod)
121✔
2318
{
2319
   // [ const ] [ var ] [ lifetime ] data_type_or_implicit
2320
   //     list_of_variable_decl_assignments ;
2321
   //  | type_declaration | package_import_declaration | net_type_declaration
2322

2323
   BEGIN("data declaration");
242✔
2324

2325
   switch (peek()) {
121✔
2326
   case tTYPEDEF:
3✔
2327
      vlog_add_decl(mod, p_type_declaration());
3✔
2328
      break;
3✔
2329

2330
   default:
118✔
2331
      {
2332
         vlog_node_t dt = p_data_type_or_implicit();
118✔
2333
         p_list_of_variable_decl_assignments(mod, dt);
118✔
2334

2335
         consume(tSEMI);
118✔
2336
      }
2337
   }
2338
}
121✔
2339

2340
static v_port_kind_t p_port_direction(void)
3✔
2341
{
2342
   // input | output | inout | ref
2343

2344
   BEGIN("port direction");
6✔
2345

2346
   switch (one_of(tINPUT, tOUTPUT, tINOUT)) {
3✔
2347
   case tINPUT:  return V_PORT_INPUT;
2348
   case tOUTPUT: return V_PORT_OUTPUT;
1✔
2349
   case tINOUT:  return V_PORT_INOUT;
×
2350
   default:      return V_PORT_INPUT;
2351
   }
2352
}
2353

2354
static v_port_kind_t p_tf_port_direction(void)
3✔
2355
{
2356
   // port_direction | const ref
2357

2358
   BEGIN("task or function port direction");
6✔
2359

2360
   return p_port_direction();
3✔
2361
}
2362

2363
static vlog_node_t p_tf_port_item(void)
4✔
2364
{
2365
   // { attribute_instance } [ tf_port_direction ] [ var ]
2366
   //    data_type_or_implicit [ port_identifier { variable_dimension }
2367
   //    [ = expression ] ]
2368

2369
   BEGIN("task or function port item");
4✔
2370

2371
   vlog_node_t v = vlog_new(V_PORT_DECL);
4✔
2372

2373
   if (scan(tINPUT, tOUTPUT))
4✔
2374
      vlog_set_subkind(v, p_tf_port_direction());
3✔
2375
   else
2376
      vlog_set_subkind(v, V_PORT_INPUT);
1✔
2377

2378
   vlog_set_type(v, p_data_type_or_implicit());
4✔
2379

2380
   if (peek() == tID) {
4✔
2381
      vlog_set_ident(v, p_identifier());
4✔
2382

2383
      if (optional(tEQ))
4✔
2384
         vlog_set_value(v, p_expression());
×
2385
   }
2386

2387
   vlog_set_loc(v, CURRENT_LOC);
4✔
2388
   return v;
4✔
2389
}
2390

2391
static void p_tf_port_list(vlog_node_t tf)
2✔
2392
{
2393
   // tf_port_item { , tf_port_item }
2394

2395
   BEGIN("task or function port list");
4✔
2396

2397
   do {
4✔
2398
      p_tf_port_item();
4✔
2399
   } while (optional(tCOMMA));
4✔
2400
}
2✔
2401

2402
static void p_task_body_declaration(vlog_node_t task)
2✔
2403
{
2404
   // [ interface_identifier . | class_scope ] task_identifier ;
2405
   //    { tf_item_declaration } { statement_or_null }
2406
   //    endtask [ : task_identifier ]
2407
   // | [ interface_identifier . | class_scope ] task_identifier
2408
   //    ( [ tf_port_list ] ) ; { block_item_declaration }
2409
   //    { statement_or_null } endtask [ : task_identifier ]
2410

2411
   BEGIN("task body declaration");
4✔
2412

2413
   ident_t id = p_identifier();
2✔
2414
   vlog_set_ident(task, id);
2✔
2415

2416
   if (optional(tLPAREN)) {
2✔
2417
      p_tf_port_list(task);
1✔
2418
      consume(tRPAREN);
1✔
2419
   }
2420

2421
   consume(tSEMI);
2✔
2422

2423
   while (not_at_token(tENDTASK)) {
6✔
2424
      vlog_node_t s = p_statement_or_null();
2✔
2425
      if (s != NULL)
2✔
2426
         vlog_add_stmt(task, s);
2✔
2427
   }
2428

2429
   consume(tENDTASK);
2✔
2430
}
2✔
2431

2432
static vlog_node_t p_task_declaration(void)
2✔
2433
{
2434
   // task [ dynamic_override_specifiers ] [ lifetime ] task_body_declaration
2435

2436
   BEGIN("task declaration");
2✔
2437

2438
   vlog_node_t v = vlog_new(V_TASK_DECL);
2✔
2439

2440
   consume(tTASK);
2✔
2441

2442
   p_task_body_declaration(v);
2✔
2443

2444
   vlog_set_loc(v, CURRENT_LOC);
2✔
2445
   return v;
2✔
2446
}
2447

2448
static vlog_node_t p_function_data_type_or_implicit(void)
1✔
2449
{
2450
   // data_type_or_void | implicit_data_type
2451

2452
   BEGIN("function data type or implicit");
2✔
2453

2454
   return p_implicit_data_type();
1✔
2455
}
2456

2457
static void p_function_body_declaration(vlog_node_t func)
1✔
2458
{
2459
   // function_data_type_or_implicit [ interface_identifier . | class_scope ]
2460
   //    function_identifier ; { tf_item_declaration }
2461
   //    { function_statement_or_null } endfunction [ : function_identifier ]
2462
   // | function_data_type_or_implicit [ interface_identifier . | class_scope ]
2463
   //    function_identifier ( [ tf_port_list ] ) ; { block_item_declaration }
2464
   //    { function_statement_or_null } endfunction [ : function_identifier ]
2465

2466
   BEGIN("function body declaration");
2✔
2467

2468
   vlog_set_type(func, p_function_data_type_or_implicit());
1✔
2469

2470
   ident_t id = p_identifier();
1✔
2471
   vlog_set_ident(func, id);
1✔
2472

2473
   if (optional(tLPAREN)) {
1✔
2474
      p_tf_port_list(func);
1✔
2475
      consume(tRPAREN);
1✔
2476
   }
2477

2478
   consume(tSEMI);
1✔
2479

2480
   while (not_at_token(tENDFUNCTION)) {
3✔
2481
      vlog_node_t s = p_statement_or_null();
1✔
2482
      if (s != NULL)
1✔
2483
         vlog_add_stmt(func, s);
1✔
2484
   }
2485

2486
   consume(tENDFUNCTION);
1✔
2487
}
1✔
2488

2489
static vlog_node_t p_function_declaration(void)
1✔
2490
{
2491
   // function [ lifetime ] function_body_declaration
2492

2493
   BEGIN("function declaration");
1✔
2494

2495
   vlog_node_t v = vlog_new(V_FUNC_DECL);
1✔
2496

2497
   consume(tFUNCTION);
1✔
2498

2499
   p_function_body_declaration(v);
1✔
2500

2501
   vlog_set_loc(v, CURRENT_LOC);
1✔
2502
   return v;
1✔
2503
}
2504

2505
static vlog_node_t p_constant_param_expression(void)
9✔
2506
{
2507
   // mintypmax_expression | data_type | $
2508

2509
   BEGIN("constant parameter expression");
18✔
2510

2511
   return p_mintypmax_expression();
9✔
2512
}
2513

2514
static vlog_node_t p_param_assignment(vlog_node_t datatype, vlog_kind_t kind)
9✔
2515
{
2516
   // parameter_identifier { unpacked_dimension }
2517
   //   [ = constant_param_expression ]
2518

2519
   BEGIN("parameter assignment");
9✔
2520

2521
   vlog_node_t v = vlog_new(kind);
9✔
2522
   vlog_set_ident(v, p_identifier());
9✔
2523
   vlog_set_type(v, datatype);
9✔
2524

2525
   if (optional(tEQ))
9✔
2526
      vlog_set_value(v, p_constant_param_expression());
9✔
2527

2528
   vlog_set_loc(v, CURRENT_LOC);
9✔
2529
   return v;
9✔
2530
}
2531

2532
static void p_list_of_param_assignments(vlog_node_t parent,
9✔
2533
                                        vlog_node_t datatype,
2534
                                        vlog_kind_t kind)
2535
{
2536
   // param_assignment { , param_assignment }
2537

2538
   BEGIN("list of parameter assignments");
18✔
2539

2540
   do {
9✔
2541
      vlog_add_decl(parent, p_param_assignment(datatype, kind));
9✔
2542
   } while (optional(tCOMMA));
9✔
2543
}
9✔
2544

2545
static void p_parameter_declaration(vlog_node_t mod)
5✔
2546
{
2547
   // parameter data_type_or_implicit list_of_param_assignments
2548

2549
   BEGIN("parameter declaration");
10✔
2550

2551
   consume(tPARAMETER);
5✔
2552

2553
   vlog_node_t dt = p_data_type_or_implicit();
5✔
2554
   p_list_of_param_assignments(mod, dt, V_PARAM_DECL);
5✔
2555
}
5✔
2556

2557
static void p_local_parameter_declaration(vlog_node_t mod)
4✔
2558
{
2559
   // localparam data_type_or_implicit list_of_param_assignments
2560

2561
   BEGIN("local parameter declaration");
8✔
2562

2563
   consume(tLOCALPARAM);
4✔
2564

2565
   vlog_node_t dt = p_data_type_or_implicit();
4✔
2566
   p_list_of_param_assignments(mod, dt, V_LOCALPARAM);
4✔
2567
}
4✔
2568

2569
static void p_package_or_generate_item_declaration(vlog_node_t mod)
213✔
2570
{
2571
   // net_declaration | data_declaration | task_declaration
2572
   //   | function_declaration | checker_declaration | dpi_import_export
2573
   //   | extern_constraint_declaration | class_declaration
2574
   //   | class_constructor_declaration | local_parameter_declaration ;
2575
   //   | parameter_declaration ; | covergroup_declaration
2576
   //   | overload_declaration | assertion_item_declaration | ;
2577

2578
   BEGIN("package or generate item declaration");
426✔
2579

2580
   switch (peek()) {
213✔
2581
   case tWIRE:
80✔
2582
   case tSUPPLY0:
2583
   case tSUPPLY1:
2584
      p_net_declaration(mod);
80✔
2585
      break;
80✔
2586
   case tREG:
121✔
2587
   case tSTRUCT:
2588
   case tUNION:
2589
   case tTYPEDEF:
2590
   case tENUM:
2591
   case tSVINT:
2592
   case tINTEGER:
2593
   case tSVREAL:
2594
   case tSHORTREAL:
2595
   case tREALTIME:
2596
      p_data_declaration(mod);
121✔
2597
      break;
121✔
2598
   case tTASK:
2✔
2599
      vlog_add_decl(mod, p_task_declaration());
2✔
2600
      break;
2✔
2601
   case tFUNCTION:
1✔
2602
      vlog_add_decl(mod, p_function_declaration());
1✔
2603
      break;
1✔
2604
   case tLOCALPARAM:
4✔
2605
      p_local_parameter_declaration(mod);
4✔
2606
      consume(tSEMI);
4✔
2607
      break;
4✔
2608
   case tPARAMETER:
5✔
2609
      p_parameter_declaration(mod);
5✔
2610
      consume(tSEMI);
5✔
2611
      break;
5✔
2612
   default:
×
2613
      one_of(tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT, tUNION, tTYPEDEF,
×
2614
             tENUM, tSVINT, tINTEGER, tSVREAL, tSHORTREAL, tREALTIME, tTASK,
2615
             tFUNCTION, tLOCALPARAM, tPARAMETER);
2616
      drop_tokens_until(tSEMI);
×
2617
      break;
×
2618
   }
2619
}
213✔
2620

2621
static void p_module_or_generate_item_declaration(vlog_node_t mod)
213✔
2622
{
2623
   // package_or_generate_item_declaration | genvar_declaration
2624
   //   | clocking_declaration | default clocking clocking_identifier ;
2625
   //   | default disable iff expression_or_dist ;
2626

2627
   BEGIN("module or generate item declaration");
426✔
2628

2629
   p_package_or_generate_item_declaration(mod);
213✔
2630
}
213✔
2631

2632
static void p_module_common_item(vlog_node_t mod)
411✔
2633
{
2634
   // module_or_generate_item_declaration
2635
   //   | interface_instantiation | program_instantiation
2636
   //   | assertion_item | bind_directive | continuous_assign
2637
   //   | net_alias | initial_construct | final_construct
2638
   //   | always_construct | loop_generate_construct
2639
   //   | conditional_generate_construct | elaboration_system_task
2640

2641
   BEGIN("module common item");
822✔
2642

2643
   switch (peek()) {
411✔
2644
   case tALWAYS:
73✔
2645
      vlog_add_stmt(mod, p_always_construct());
73✔
2646
      break;
73✔
2647
   case tINITIAL:
74✔
2648
      vlog_add_stmt(mod, p_initial_construct());
74✔
2649
      break;
74✔
2650
   case tWIRE:
213✔
2651
   case tSUPPLY0:
2652
   case tSUPPLY1:
2653
   case tREG:
2654
   case tSTRUCT:
2655
   case tUNION:
2656
   case tTYPEDEF:
2657
   case tENUM:
2658
   case tSVINT:
2659
   case tINTEGER:
2660
   case tSVREAL:
2661
   case tSHORTREAL:
2662
   case tREALTIME:
2663
   case tTASK:
2664
   case tFUNCTION:
2665
   case tLOCALPARAM:
2666
   case tPARAMETER:
2667
      p_module_or_generate_item_declaration(mod);
213✔
2668
      break;
213✔
2669
   case tASSIGN:
51✔
2670
      p_continuous_assign(mod);
51✔
2671
      break;
51✔
2672
   default:
×
2673
      one_of(tALWAYS, tINITIAL, tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT,
×
2674
             tUNION, tTYPEDEF, tENUM, tSVINT, tINTEGER, tSVREAL, tSHORTREAL,
2675
             tREALTIME, tTASK, tFUNCTION, tPARAMETER, tLOCALPARAM, tASSIGN);
2676
      drop_tokens_until(tSEMI);
×
2677
   }
2678
}
411✔
2679

2680
static vlog_strength_t p_strength0(void)
4✔
2681
{
2682
   // supply0 | strong0 | pull0 | weak0
2683

2684
   BEGIN("strength0");
4✔
2685

2686
   switch (one_of(tSUPPLY0)) {
4✔
2687
   default:
2688
   case tSUPPLY0: return V_STRENGTH_SUPPLY;
4✔
2689
   }
2690
}
2691

2692
static vlog_strength_t p_strength1(void)
6✔
2693
{
2694
   // supply1 | strong1 | pull1 | weak1
2695

2696
   BEGIN("strength1");
6✔
2697

2698
   switch (one_of(tSUPPLY1)) {
6✔
2699
   default:
2700
   case tSUPPLY1: return V_STRENGTH_SUPPLY;
6✔
2701
   }
2702
}
2703

2704
static vlog_node_t p_pulldown_strength(void)
2✔
2705
{
2706
   // ( strength0 , strength1 ) | ( strength1 , strength0 ) | ( strength0 )
2707

2708
   BEGIN("pulldown strength");
2✔
2709

2710
   consume(tLPAREN);
2✔
2711

2712
   vlog_strength_t s0, s1;
2✔
2713
   switch (peek()) {
2✔
2714
   case tSUPPLY1:
×
2715
      s1 = p_strength1();
×
2716
      consume(tCOMMA);
×
2717
      s0 = p_strength0();
×
2718
      break;
×
2719
   default:
2✔
2720
      s0 = s1 = p_strength0();
2✔
2721
      if (optional(tCOMMA))
2✔
2722
         s1 = p_strength1();
×
2723
      break;
2724
   }
2725

2726
   consume(tRPAREN);
2✔
2727

2728
   vlog_node_t v = vlog_new(V_STRENGTH);
2✔
2729
   vlog_set_subkind(v, MAKE_STRENGTH(s0, s1));
2✔
2730
   vlog_set_loc(v, CURRENT_LOC);
2✔
2731
   return v;
2✔
2732
}
2733

2734
static vlog_node_t p_pullup_strength(void)
6✔
2735
{
2736
   // ( strength0 , strength1 ) | ( strength1 , strength0 ) | ( strength1 )
2737

2738
   BEGIN("pullup strength");
6✔
2739

2740
   consume(tLPAREN);
6✔
2741

2742
   vlog_strength_t s0, s1;
6✔
2743
   switch (peek()) {
6✔
2744
   case tSUPPLY0:
1✔
2745
      s0 = p_strength0();
1✔
2746
      consume(tCOMMA);
1✔
2747
      s1 = p_strength1();
1✔
2748
      break;
1✔
2749
   default:
5✔
2750
      s1 = s0 = p_strength1();
5✔
2751
      if (optional(tCOMMA))
5✔
2752
         s0 = p_strength0();
1✔
2753
      break;
2754
   }
2755

2756
   consume(tRPAREN);
6✔
2757

2758
   vlog_node_t v = vlog_new(V_STRENGTH);
6✔
2759
   vlog_set_subkind(v, MAKE_STRENGTH(s0, s1));
6✔
2760
   vlog_set_loc(v, CURRENT_LOC);
6✔
2761
   return v;
6✔
2762
}
2763

2764
static vlog_node_t p_pull_gate_instance(vlog_gate_kind_t kind, vlog_node_t st)
19✔
2765
{
2766
   // [ name_of_instance ] ( output_terminal )
2767

2768
   BEGIN("pull gate instance");
19✔
2769

2770
   vlog_node_t v = vlog_new(V_GATE_INST);
19✔
2771
   vlog_set_subkind(v, kind);
19✔
2772
   vlog_add_param(v, st);
19✔
2773

2774
   if (peek() == tID)
19✔
2775
      vlog_set_ident(v, p_identifier());
7✔
2776

2777
   consume(tLPAREN);
19✔
2778

2779
   vlog_set_target(v, p_net_lvalue());
19✔
2780

2781
   consume(tRPAREN);
19✔
2782

2783
   vlog_set_loc(v, CURRENT_LOC);
19✔
2784
   return v;
19✔
2785
}
2786

2787
static vlog_node_t p_n_terminal_gate_instance(vlog_gate_kind_t kind)
17✔
2788
{
2789
   // [ name_of_instance ] ( output_terminal , input_terminal
2790
   //     { , input_terminal } )
2791

2792
   BEGIN("N-terminal gate instance");
17✔
2793

2794
   vlog_node_t v = vlog_new(V_GATE_INST);
17✔
2795
   vlog_set_subkind(v, kind);
17✔
2796

2797
   if (peek() == tID)
17✔
2798
      vlog_set_ident(v, p_identifier());
2✔
2799

2800
   consume(tLPAREN);
17✔
2801

2802
   vlog_set_target(v, p_net_lvalue());
17✔
2803

2804
   consume(tCOMMA);
17✔
2805

2806
   do {
30✔
2807
      vlog_add_param(v, p_net_lvalue());
30✔
2808
   } while (optional(tCOMMA));
30✔
2809

2810
   consume(tRPAREN);
17✔
2811

2812
   vlog_set_loc(v, CURRENT_LOC);
17✔
2813
   return v;
17✔
2814
}
2815

2816
static void p_gate_instantiation(vlog_node_t mod)
36✔
2817
{
2818
   // cmos_switchtype [ delay3 ] cmos_switch_instance
2819
   //     { , cmos_switch_instance } ;
2820
   //  | enable_gatetype [ drive_strength ] [ delay3 ]
2821
   //     enable_gate_instance { , enable_gate_instance } ;
2822
   //  | mos_switchtype [ delay3 ] mos_switch_instance
2823
   //     { , mos_switch_instance } ;
2824
   //  | n_input_gatetype [ drive_strength ] [ delay2 ] n_input_gate_instance
2825
   //     { , n_input_gate_instance } ;
2826
   //  | n_output_gatetype [ drive_strength ] [ delay2 ] n_output_gate_instance
2827
   //     { , n_output_gate_instance } ;
2828
   //  | pass_en_switchtype [ delay2 ] pass_enable_switch_instance
2829
   //     { , pass_enable_switch_instance } ;
2830
   //  | pass_switchtype pass_switch_instance { , pass_switch_instance } ;
2831
   //  | pulldown [ pulldown_strength ] pull_gate_instance
2832
   //     { , pull_gate_instance } ;
2833
   //  | pullup [ pullup_strength ] pull_gate_instance
2834
   //     { , pull_gate_instance } ;
2835

2836
   BEGIN("gate instantiation");
72✔
2837

2838
   switch (one_of(tPULLDOWN, tPULLUP, tAND, tNAND, tOR, tNOR, tXOR, tXNOR,
36✔
2839
                  tNOT, tBUF)) {
2840
   case tPULLDOWN:
7✔
2841
      {
2842
         vlog_node_t st;
7✔
2843
         if (peek() == tLPAREN && peek_nth(2) != tID)
7✔
2844
            st = p_pulldown_strength();
2✔
2845
         else {
2846
            st = vlog_new(V_STRENGTH);
5✔
2847
            vlog_set_subkind(st, ST_PULLUP);
5✔
2848
         }
2849

2850
         do {
7✔
2851
            vlog_node_t g = p_pull_gate_instance(V_GATE_PULLDOWN, st);
7✔
2852
            vlog_add_stmt(mod, g);
7✔
2853
         } while (optional(tCOMMA));
7✔
2854
      }
2855
      break;
2856

2857
   case tPULLUP:
12✔
2858
      {
2859
         vlog_node_t st;
12✔
2860
         if (peek() == tLPAREN && peek_nth(2) != tID)
12✔
2861
            st = p_pullup_strength();
6✔
2862
         else {
2863
            st = vlog_new(V_STRENGTH);
6✔
2864
            vlog_set_subkind(st, ST_PULLUP);
6✔
2865
         }
2866

2867
         do {
12✔
2868
            vlog_node_t g = p_pull_gate_instance(V_GATE_PULLUP, st);
12✔
2869
            vlog_add_stmt(mod, g);
12✔
2870
         } while (optional(tCOMMA));
12✔
2871
      }
2872
      break;
2873

2874
   case tAND:
4✔
2875
      do {
4✔
2876
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_AND));
4✔
2877
      } while (optional(tCOMMA));
4✔
2878
      break;
2879

2880
   case tNAND:
3✔
2881
      do {
3✔
2882
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_NAND));
3✔
2883
      } while (optional(tCOMMA));
3✔
2884
      break;
2885

2886
   case tOR:
4✔
2887
      do {
4✔
2888
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_OR));
4✔
2889
      } while (optional(tCOMMA));
4✔
2890
      break;
2891

2892
   case tNOR:
×
2893
      do {
×
2894
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_NOR));
×
2895
      } while (optional(tCOMMA));
×
2896
      break;
2897

2898
   case tXOR:
3✔
2899
      do {
3✔
2900
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_XOR));
3✔
2901
      } while (optional(tCOMMA));
3✔
2902
      break;
2903

2904
   case tXNOR:
×
2905
      do {
×
2906
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_XNOR));
×
2907
      } while (optional(tCOMMA));
×
2908
      break;
2909

2910
   case tNOT:
3✔
2911
      do {
3✔
2912
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_NOT));
3✔
2913
      } while (optional(tCOMMA));
3✔
2914
      break;
2915

2916
   case tBUF:
×
2917
      do {
×
2918
         vlog_add_stmt(mod, p_n_terminal_gate_instance(V_GATE_BUF));
×
2919
      } while (optional(tCOMMA));
×
2920
      break;
2921

2922
   default:
2923
      break;
2924
   }
2925

2926
   consume(tSEMI);
36✔
2927
}
36✔
2928

2929
static void p_path_delay_expression(void)
3✔
2930
{
2931
   // constant_expression
2932
   //   | constant_expression : constant_expression : constant_expression
2933

2934
   BEGIN("path delay expression");
6✔
2935

2936
   (void)p_constant_expression();
3✔
2937
}
3✔
2938

2939
static void p_list_of_path_delay_expressions(void)
2✔
2940
{
2941
   // path_delay_expression { , path_delay_expression }
2942

2943
   BEGIN("list of path delay expressions");
4✔
2944

2945
   do {
3✔
2946
      p_path_delay_expression();
3✔
2947
   } while (optional(tCOMMA));
3✔
2948
}
2✔
2949

2950
static void p_path_delay_value(void)
2✔
2951
{
2952
   // list_of_path_delay_expressions | ( list_of_path_delay_expressions )
2953

2954
   BEGIN("path delay value");
4✔
2955

2956
   if (optional(tLPAREN)) {
2✔
2957
      p_list_of_path_delay_expressions();
1✔
2958
      consume(tRPAREN);
1✔
2959
   }
2960
   else
2961
      p_list_of_path_delay_expressions();
1✔
2962
}
2✔
2963

2964
static void p_specify_terminal_descriptor(void)
4✔
2965
{
2966
   // identifier [ [ constant_range_expression ] ]
2967

2968
   BEGIN("specify terminal descriptor");
8✔
2969

2970
   p_identifier();
4✔
2971
}
4✔
2972

2973
static void p_parallel_path_description(void)
2✔
2974
{
2975
   // ( specify_input_terminal_descriptor [ polarity_operator ] =>
2976
   //     specify_output_terminal_descriptor )
2977

2978
   BEGIN("parallel path description");
4✔
2979

2980
   consume(tLPAREN);
2✔
2981

2982
   p_specify_terminal_descriptor();
2✔
2983

2984
   consume(tASSOC);
2✔
2985

2986
   p_specify_terminal_descriptor();
2✔
2987

2988
   consume(tRPAREN);
2✔
2989
}
2✔
2990

2991
static void p_simple_path_declaration(void)
2✔
2992
{
2993
   // parallel_path_description = path_delay_value
2994
   //   | full_path_description = path_delay_value
2995

2996
   BEGIN("simple path declaration");
4✔
2997

2998
   p_parallel_path_description();
2✔
2999

3000
   consume(tEQ);
2✔
3001

3002
   p_path_delay_value();
2✔
3003
}
2✔
3004

3005
static void p_path_declaration(void)
2✔
3006
{
3007
   // simple_path_declaration ; | edge_sensitive_path_declaration ;
3008
   //   | state_dependent_path_declaration ;
3009

3010
   BEGIN("path declaration");
4✔
3011

3012
   p_simple_path_declaration();
2✔
3013

3014
   consume(tSEMI);
2✔
3015
}
2✔
3016

3017
static void p_specify_item(void)
2✔
3018
{
3019
   // specparam_declaration | pulsestyle_declaration | showcancelled_declaration
3020
   //   | path_declaration | system_timing_check
3021

3022
   BEGIN("specify item");
4✔
3023

3024
   switch (peek()) {
2✔
3025
   case tLPAREN:
2✔
3026
      p_path_declaration();
2✔
3027
      break;
2✔
3028
   default:
×
3029
      one_of(tLPAREN);
×
3030
   }
3031
}
2✔
3032

3033
static vlog_node_t p_specify_block(void)
1✔
3034
{
3035
   // specify { specify_item } endspecify
3036

3037
   BEGIN("specify block");
1✔
3038

3039
   consume(tSPECIFY);
1✔
3040

3041
   vlog_node_t v = vlog_new(V_SPECIFY);
1✔
3042

3043
   while (not_at_token(tENDSPECIFY))
3✔
3044
      p_specify_item();
2✔
3045

3046
   consume(tENDSPECIFY);
1✔
3047

3048
   vlog_set_loc(v, CURRENT_LOC);
1✔
3049
   return v;
1✔
3050
}
3051

3052
static vlog_node_t p_ordered_port_connection(void)
38✔
3053
{
3054
   // { attribute_instance } [ expression ]
3055

3056
   BEGIN("ordered port connection");
76✔
3057

3058
   return p_expression();
38✔
3059
}
3060

3061
static void p_list_of_port_connections(vlog_node_t inst)
17✔
3062
{
3063
   // ordered_port_connection { , ordered_port_connection }
3064
   //   | named_port_connection { , named_port_connection }
3065

3066
   BEGIN("list of port connections");
34✔
3067

3068
   do {
38✔
3069
      vlog_add_param(inst, p_ordered_port_connection());
38✔
3070
   } while (optional(tCOMMA));
38✔
3071
}
17✔
3072

3073
static vlog_node_t p_hierarchical_instance(ident_t module_id)
17✔
3074
{
3075
   // name_of_instance ( [ list_of_port_connections ] )
3076

3077
   BEGIN("hierarchical instance");
17✔
3078

3079
   vlog_node_t v = vlog_new(V_MOD_INST);
17✔
3080
   vlog_set_ident(v, p_identifier());
17✔
3081
   vlog_set_ident2(v, module_id);
17✔
3082

3083
   consume(tLPAREN);
17✔
3084

3085
   if (peek() != tRPAREN)
17✔
3086
      p_list_of_port_connections(v);
17✔
3087

3088
   consume(tRPAREN);
17✔
3089

3090
   vlog_set_loc(v, CURRENT_LOC);
17✔
3091
   return v;
17✔
3092
}
3093

3094
static void p_module_instantiation(vlog_node_t mod)
17✔
3095
{
3096
   // module_identifier [ parameter_value_assignment ] hierarchical_instance
3097
   //   { , hierarchical_instance } ;
3098

3099
   BEGIN("module instantiation");
34✔
3100

3101
   ident_t module_id = p_identifier();
17✔
3102

3103
   do {
17✔
3104
      vlog_add_stmt(mod, p_hierarchical_instance(module_id));
17✔
3105
   } while (optional(tCOMMA));
17✔
3106

3107
   consume(tSEMI);
17✔
3108
}
17✔
3109

3110
static void p_module_or_generate_item(vlog_node_t mod)
464✔
3111
{
3112
   // { attribute_instance } parameter_override
3113
   //   | { attribute_instance } gate_instantiation
3114
   //   | { attribute_instance } udp_instantiation
3115
   //   | { attribute_instance } module_instantiation
3116
   //   | { attribute_instance } module_common_item
3117

3118
   BEGIN("module or generate item");
928✔
3119

3120
   while (peek() == tATTRBEGIN)
470✔
3121
      p_attribute_instance();
6✔
3122

3123
   switch (peek()) {
464✔
3124
   case tALWAYS:
411✔
3125
   case tWIRE:
3126
   case tSUPPLY0:
3127
   case tSUPPLY1:
3128
   case tREG:
3129
   case tSTRUCT:
3130
   case tUNION:
3131
   case tASSIGN:
3132
   case tINITIAL:
3133
   case tTYPEDEF:
3134
   case tENUM:
3135
   case tSVINT:
3136
   case tINTEGER:
3137
   case tSVREAL:
3138
   case tSHORTREAL:
3139
   case tREALTIME:
3140
   case tTASK:
3141
   case tFUNCTION:
3142
   case tLOCALPARAM:
3143
   case tPARAMETER:
3144
      p_module_common_item(mod);
411✔
3145
      break;
411✔
3146
   case tPULLDOWN:
36✔
3147
   case tPULLUP:
3148
   case tAND:
3149
   case tNAND:
3150
   case tOR:
3151
   case tNOR:
3152
   case tXOR:
3153
   case tXNOR:
3154
   case tNOT:
3155
   case tBUF:
3156
      p_gate_instantiation(mod);
36✔
3157
      break;
36✔
3158
   case tID:
17✔
3159
      p_module_instantiation(mod);
17✔
3160
      break;
17✔
3161
   default:
×
3162
      one_of(tALWAYS, tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT, tUNION, tASSIGN,
×
3163
             tINITIAL, tTYPEDEF, tENUM, tSVINT, tINTEGER, tSVREAL, tSHORTREAL,
3164
             tREALTIME, tTASK, tFUNCTION, tLOCALPARAM, tPARAMETER, tPULLDOWN,
3165
             tPULLUP, tID, tAND, tNAND, tOR, tNOR, tXOR, tXNOR, tNOT, tBUF);
3166
      drop_tokens_until(tSEMI);
×
3167
   }
3168
}
464✔
3169

3170
static void p_non_port_module_item(vlog_node_t mod)
467✔
3171
{
3172
   // generate_region | module_or_generate_item | specify_block
3173
   //   | { attribute_instance } specparam_declaration | program_declaration
3174
   //   | module_declaration | interface_declaration | timeunits_declaration
3175

3176
   BEGIN("non-port module item");
934✔
3177

3178
   switch (peek()) {
467✔
3179
   case tALWAYS:
464✔
3180
   case tWIRE:
3181
   case tSUPPLY0:
3182
   case tSUPPLY1:
3183
   case tREG:
3184
   case tSTRUCT:
3185
   case tUNION:
3186
   case tASSIGN:
3187
   case tINITIAL:
3188
   case tPULLDOWN:
3189
   case tPULLUP:
3190
   case tID:
3191
   case tATTRBEGIN:
3192
   case tAND:
3193
   case tNAND:
3194
   case tOR:
3195
   case tNOR:
3196
   case tXOR:
3197
   case tXNOR:
3198
   case tNOT:
3199
   case tBUF:
3200
   case tTYPEDEF:
3201
   case tENUM:
3202
   case tSVINT:
3203
   case tINTEGER:
3204
   case tSVREAL:
3205
   case tSHORTREAL:
3206
   case tREALTIME:
3207
   case tTASK:
3208
   case tFUNCTION:
3209
   case tLOCALPARAM:
3210
   case tPARAMETER:
3211
      p_module_or_generate_item(mod);
464✔
3212
      break;
464✔
3213
   case tSPECIFY:
1✔
3214
      vlog_add_stmt(mod, p_specify_block());
1✔
3215
      break;
1✔
3216
   default:
2✔
3217
      one_of(tALWAYS, tWIRE, tSUPPLY0, tSUPPLY1, tREG, tSTRUCT, tUNION,
2✔
3218
             tASSIGN, tPULLDOWN, tPULLUP, tID, tATTRBEGIN, tAND, tNAND,
3219
             tOR, tNOR, tXOR, tXNOR, tNOT, tBUF, tTYPEDEF, tENUM, tSVINT,
3220
             tINTEGER, tSVREAL, tSHORTREAL, tREALTIME, tTASK, tFUNCTION,
3221
             tLOCALPARAM, tPARAMETER, tSPECIFY);
3222
      drop_tokens_until(tSEMI);
2✔
3223
   }
3224
}
467✔
3225

3226
static void p_module_item(vlog_node_t mod)
524✔
3227
{
3228
   // port_declaration ; | non_port_module_item
3229

3230
   BEGIN("module item");
1,048✔
3231

3232
   if (scan(tINOUT, tINPUT, tOUTPUT)) {
524✔
3233
      p_port_declaration(mod);
57✔
3234
      consume(tSEMI);
57✔
3235
   }
3236
   else
3237
      p_non_port_module_item(mod);
467✔
3238
}
524✔
3239

3240
static void p_ansi_port_declaration(vlog_node_t mod, v_port_kind_t *kind,
53✔
3241
                                    bool *isreg)
3242
{
3243
   // [ net_port_header | interface_port_header ] port_identifier
3244
   //     { unpacked_dimension } [ = constant_expression ]
3245
   // | [ variable_port_header ] port_identifier { variable_dimension }
3246
   //     [ = constant_expression ]
3247
   // | [ port_direction ] . port_identifier ( [ expression ] )
3248

3249
   BEGIN("ANSI port declaration");
106✔
3250

3251
   vlog_node_t dt;
53✔
3252
   if (peek() != tID)
53✔
3253
      dt = p_net_port_header(kind, isreg);
36✔
3254
   else
3255
      dt = logic_type();
17✔
3256

3257
   ident_t id, ext;
53✔
3258
   p_external_identifier(&id, &ext);
53✔
3259

3260
   vlog_node_t v = vlog_new(V_PORT_DECL);
53✔
3261
   vlog_set_subkind(v, *kind);
53✔
3262
   vlog_set_ident(v, id);
53✔
3263
   vlog_set_ident2(v, ext);
53✔
3264
   vlog_set_type(v, dt);
53✔
3265
   vlog_set_loc(v, &state.last_loc);
53✔
3266

3267
   vlog_add_decl(mod, v);
53✔
3268

3269
   if (*isreg) {
53✔
3270
      vlog_node_t reg = vlog_new(V_VAR_DECL);
10✔
3271
      vlog_set_loc(reg, CURRENT_LOC);
10✔
3272
      vlog_set_ident(reg, id);
10✔
3273
      vlog_set_type(reg, dt);
10✔
3274

3275
      vlog_add_decl(mod, reg);
10✔
3276
   }
3277

3278
   vlog_node_t ref = vlog_new(V_REF);
53✔
3279
   vlog_set_loc(ref, CURRENT_LOC);
53✔
3280
   vlog_set_ident(ref, id);
53✔
3281
   vlog_set_ref(ref, v);
53✔
3282

3283
   vlog_add_port(mod, ref);
53✔
3284
}
53✔
3285

3286
static void p_list_of_port_declarations(vlog_node_t mod)
17✔
3287
{
3288
   // ( [ { attribute_instance } ansi_port_declaration
3289
   //   { , { attribute_instance } ansi_port_declaration } ] )
3290

3291
   BEGIN("list of port declarations");
34✔
3292

3293
   consume(tLPAREN);
17✔
3294

3295
   if (peek() != tRPAREN) {
17✔
3296
      v_port_kind_t kind = V_PORT_INPUT;
14✔
3297
      bool isreg = false;
14✔
3298
      do {
53✔
3299
         p_ansi_port_declaration(mod, &kind, &isreg);
53✔
3300
      } while (optional(tCOMMA));
53✔
3301
   }
3302

3303
   consume(tRPAREN);
17✔
3304
}
17✔
3305

3306
static void p_module_ansi_header(vlog_node_t mod)
91✔
3307
{
3308
   // { attribute_instance } module_keyword [ lifetime ] module_identifier
3309
   //    { package_import_declaration } [ parameter_port_list ]
3310
   ///   [ list_of_port_declarations ] ;
3311

3312
   EXTEND("module ANSI header");
182✔
3313

3314
   if (peek() == tLPAREN)
91✔
3315
      p_list_of_port_declarations(mod);
17✔
3316

3317
   consume(tSEMI);
91✔
3318

3319
   vlog_set_loc(mod, CURRENT_LOC);
91✔
3320
}
91✔
3321

3322
static vlog_node_t p_port_reference(void)
64✔
3323
{
3324
   // port_identifier constant_select
3325

3326
   BEGIN("port reference");
128✔
3327

3328
   return p_constant_select(p_identifier());
64✔
3329
}
3330

3331
static vlog_node_t p_port_expression(void)
64✔
3332
{
3333
   // port_reference | { port_reference { , port_reference } }
3334

3335
   BEGIN("port expression");
128✔
3336

3337
   return p_port_reference();
64✔
3338
}
3339

3340
static vlog_node_t p_port(void)
64✔
3341
{
3342
   // [ port_expression ] | . port_identifier ( [ port_expression ] )
3343

3344
   BEGIN("port");
128✔
3345

3346
   return p_port_expression();
64✔
3347
}
3348

3349
static void p_list_of_ports(vlog_node_t mod)
21✔
3350
{
3351
   // ( port { , port } )
3352

3353
   BEGIN("list of ports");
42✔
3354

3355
   consume(tLPAREN);
21✔
3356

3357
   do {
64✔
3358
      p_port();
64✔
3359
   } while (optional(tCOMMA));
64✔
3360

3361
   consume(tRPAREN);
21✔
3362
}
21✔
3363

3364
static void p_module_nonansi_header(vlog_node_t mod)
21✔
3365
{
3366
   // { attribute_instance } module_keyword [ lifetime ] module_identifier
3367
   //    { package_import_declaration } [ parameter_port_list ] list_of_ports ;
3368

3369
   EXTEND("module non-ANSI header");
42✔
3370

3371
   p_list_of_ports(mod);
21✔
3372

3373
   consume(tSEMI);
21✔
3374

3375
   vlog_set_loc(mod, CURRENT_LOC);
21✔
3376
}
21✔
3377

3378
static vlog_node_t p_module_declaration(void)
112✔
3379
{
3380
   // module_nonansi_header [ timeunits_declaration ] { module_item }
3381
   //      endmodule [ : module_identifier ]
3382
   //   | module_ansi_header [ timeunits_declaration ] { non_port_module_item }
3383
   //      endmodule [ : module_identifier ]
3384
   //   | { attribute_instance } module_keyword [ lifetime ] module_identifier
3385
   //      ( .* ) ; [ timeunits_declaration ] { module_item } endmodule
3386
   //      [ : module_identifier ]
3387
   //   | extern module_nonansi_header
3388
   //   | extern module_ansi_header
3389

3390
   BEGIN("module declaration");
112✔
3391

3392
   vlog_node_t mod = vlog_new(V_MODULE);
112✔
3393

3394
   while (peek() == tATTRBEGIN)
112✔
3395
      p_attribute_instance();
×
3396

3397
   consume(tMODULE);
112✔
3398

3399
   ident_t id, ext;
112✔
3400
   p_external_identifier(&id, &ext);
112✔
3401
   vlog_set_ident2(mod, id);
112✔
3402

3403
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
112✔
3404
   vlog_set_ident(mod, qual);
112✔
3405

3406
   if (peek() == tLPAREN && peek_nth(2) == tID)
112✔
3407
      p_module_nonansi_header(mod);
21✔
3408
   else
3409
      p_module_ansi_header(mod);
91✔
3410

3411
   while (not_at_token(tENDMODULE))
636✔
3412
      p_module_item(mod);
524✔
3413

3414
   consume(tENDMODULE);
112✔
3415

3416
   return mod;
112✔
3417
}
3418

3419
static void p_udp_port_list(vlog_node_t udp)
16✔
3420
{
3421
   // output_port_identifier , input_port_identifier { , input_port_identifier }
3422

3423
   BEGIN("UDP port list");
32✔
3424

3425
   vlog_node_t oref = vlog_new(V_REF);
16✔
3426
   vlog_set_ident(oref, p_identifier());
16✔
3427
   vlog_set_loc(oref, &state.last_loc);
16✔
3428

3429
   vlog_add_port(udp, oref);
16✔
3430

3431
   consume(tCOMMA);
16✔
3432

3433
   vlog_node_t iref = vlog_new(V_REF);
16✔
3434
   vlog_set_ident(iref, p_identifier());
16✔
3435
   vlog_set_loc(iref, &state.last_loc);
16✔
3436

3437
   vlog_add_port(udp, iref);
16✔
3438

3439
   while (optional(tCOMMA)) {
38✔
3440
      vlog_node_t iref = vlog_new(V_REF);
22✔
3441
      vlog_set_ident(iref, p_identifier());
22✔
3442
      vlog_set_loc(iref, &state.last_loc);
22✔
3443

3444
      vlog_add_port(udp, iref);
22✔
3445
   }
3446
}
16✔
3447

3448
static vlog_node_t p_udp_nonansi_declaration(void)
16✔
3449
{
3450
   // { attribute_instance } primitive udp_identifier ( udp_port_list ) ;
3451

3452
   BEGIN("UDP non-ANSI declaration");
16✔
3453

3454
   vlog_node_t udp = vlog_new(V_PRIMITIVE);
16✔
3455

3456
   consume(tPRIMITIVE);
16✔
3457

3458
   ident_t id, ext;
16✔
3459
   p_external_identifier(&id, &ext);
16✔
3460
   vlog_set_ident2(udp, id);
16✔
3461

3462
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
16✔
3463
   vlog_set_ident(udp, qual);
16✔
3464

3465
   consume(tLPAREN);
16✔
3466

3467
   p_udp_port_list(udp);
16✔
3468

3469
   consume(tRPAREN);
16✔
3470
   consume(tSEMI);
16✔
3471

3472
   vlog_set_loc(udp, CURRENT_LOC);
16✔
3473
   return udp;
16✔
3474
}
3475

3476
static void p_list_of_udp_port_identifiers(vlog_node_t udp, v_port_kind_t kind)
17✔
3477
{
3478
   // port_identifier { , port_identifier }
3479

3480
   BEGIN("list of UDP port identifiers");
34✔
3481

3482
   do {
38✔
3483
      ident_t id, ext;
38✔
3484
      p_external_identifier(&id, &ext);
38✔
3485

3486
      vlog_node_t p = vlog_new(V_PORT_DECL);
38✔
3487
      vlog_set_subkind(p, kind);
38✔
3488
      vlog_set_ident(p, id);
38✔
3489
      vlog_set_ident2(p, ext);
38✔
3490
      vlog_set_type(p, logic_type());
38✔
3491
      vlog_set_loc(p, &state.last_loc);
38✔
3492

3493
      vlog_add_decl(udp, p);
38✔
3494
   } while (optional(tCOMMA));
38✔
3495
}
17✔
3496

3497
static void p_udp_output_declaration(vlog_node_t udp, bool *has_reg)
17✔
3498
{
3499
   // { attribute_instance } output port_identifier
3500
   //    | { attribute_instance } output reg port_identifier
3501
   //         [ = constant_expression ]
3502

3503
   BEGIN("UDP output declaration");
34✔
3504

3505
   consume(tOUTPUT);
17✔
3506

3507
   const bool isreg = optional(tREG);
17✔
3508

3509
   ident_t id, ext;
17✔
3510
   p_external_identifier(&id, &ext);
17✔
3511

3512
   vlog_node_t logic = logic_type();
17✔
3513

3514
   vlog_node_t v = vlog_new(V_PORT_DECL);
17✔
3515
   vlog_set_subkind(v, V_PORT_OUTPUT);
17✔
3516
   vlog_set_ident(v, id);
17✔
3517
   vlog_set_ident2(v, ext);
17✔
3518
   vlog_set_type(v, logic);
17✔
3519
   vlog_set_loc(v, &state.last_loc);
17✔
3520

3521
   vlog_add_decl(udp, v);
17✔
3522

3523
   if (isreg) {
17✔
3524
      vlog_node_t reg = vlog_new(V_VAR_DECL);
2✔
3525
      vlog_set_loc(reg, &state.last_loc);
2✔
3526
      vlog_set_ident(reg, id);
2✔
3527
      vlog_set_type(reg, logic);
2✔
3528

3529
      vlog_add_decl(udp, reg);
2✔
3530

3531
      *has_reg = true;
2✔
3532
   }
3533
}
17✔
3534

3535
static void p_udp_input_declaration(vlog_node_t udp)
17✔
3536
{
3537
   // { attribute_instance } input list_of_udp_port_identifiers
3538

3539
   BEGIN("UDP input declaration");
34✔
3540

3541
   consume(tINPUT);
17✔
3542

3543
   p_list_of_udp_port_identifiers(udp, V_PORT_INPUT);
17✔
3544
}
17✔
3545

3546
static vlog_node_t p_udp_reg_declaration(void)
7✔
3547
{
3548
   // { attribute_instance } reg variable_identifier
3549

3550
   BEGIN("UDP reg declaration");
7✔
3551

3552
   consume(tREG);
7✔
3553

3554
   ident_t id = p_identifier();
7✔
3555

3556
   vlog_node_t reg = vlog_new(V_VAR_DECL);
7✔
3557
   vlog_set_loc(reg, &state.last_loc);
7✔
3558
   vlog_set_ident(reg, id);
7✔
3559
   vlog_set_type(reg, logic_type());
7✔
3560

3561
   return reg;
7✔
3562
}
3563

3564
static void p_udp_port_declaration(vlog_node_t udp, bool *has_reg)
39✔
3565
{
3566
   // udp_output_declaration ; | udp_input_declaration ; | udp_reg_declaration ;
3567

3568
   BEGIN("UDP port declaration");
78✔
3569

3570
   switch (peek()) {
39✔
3571
   case tOUTPUT:
16✔
3572
      p_udp_output_declaration(udp, has_reg);
16✔
3573
      break;
16✔
3574
   case tINPUT:
16✔
3575
      p_udp_input_declaration(udp);
16✔
3576
      break;
16✔
3577
   case tREG:
7✔
3578
      vlog_add_decl(udp, p_udp_reg_declaration());
7✔
3579
      *has_reg = true;
7✔
3580
      break;
7✔
3581
   default:
×
3582
      one_of(tOUTPUT, tINPUT, tREG);
×
3583
      break;
×
3584
   }
3585

3586
   consume(tSEMI);
39✔
3587
}
39✔
3588

3589
static void p_udp_declaration_port_list(vlog_node_t udp, bool *has_reg)
1✔
3590
{
3591
   // udp_output_declaration , udp_input_declaration { , udp_input_declaration }
3592

3593
   BEGIN("UDP declaration port list");
2✔
3594

3595
   p_udp_output_declaration(udp, has_reg);
1✔
3596

3597
   consume(tCOMMA);
1✔
3598

3599
   do {
1✔
3600
      p_udp_input_declaration(udp);
1✔
3601
   } while (optional(tCOMMA));
1✔
3602

3603
   const int ndecls = vlog_decls(udp);
1✔
3604
   for (int i = 0; i < ndecls; i++) {
4✔
3605
      vlog_node_t p = vlog_decl(udp, i);
3✔
3606
      if (vlog_kind(p) != V_PORT_DECL)
3✔
3607
         continue;
1✔
3608

3609
      vlog_node_t ref = vlog_new(V_REF);
2✔
3610
      vlog_set_loc(ref, vlog_loc(p));
2✔
3611
      vlog_set_ident(ref, vlog_ident(p));
2✔
3612
      vlog_set_ref(ref, p);
2✔
3613

3614
      vlog_add_port(udp, ref);
2✔
3615
   }
3616
}
1✔
3617

3618
static char p_output_symbol(void)
79✔
3619
{
3620
   // 0 | 1 | x | X
3621

3622
   BEGIN("output symbol");
158✔
3623

3624
   if (consume(tUDPLEVEL)) {
79✔
3625
      switch (state.last_lval.i64) {
79✔
3626
      case '0':
79✔
3627
      case '1':
3628
      case 'x':
3629
      case 'X':
3630
         return (char)state.last_lval.i64;
79✔
3631
      default:
×
3632
         parse_error(&state.last_loc, "'%c' is not a valid output symbol",
×
3633
                  (char)state.last_lval.i64);
3634
         break;
3635
      }
3636
   }
3637

3638
   return 'x';
3639
}
3640

3641
static char p_level_symbol(void)
229✔
3642
{
3643
   // 0 | 1 | x | X | ? | b | B
3644

3645
   BEGIN("level symbol");
458✔
3646

3647
   if (consume(tUDPLEVEL))
229✔
3648
      return (char)state.last_lval.i64;
229✔
3649
   else
3650
      return 'x';
3651
}
3652

3653
static char p_next_state(void)
67✔
3654
{
3655
   // output_symbol | -
3656

3657
   BEGIN("next state");
134✔
3658

3659
   switch (peek()) {
67✔
3660
   case tMINUS:
21✔
3661
      consume(tMINUS);
21✔
3662
      return '-';
21✔
3663
   case tUDPLEVEL:
46✔
3664
      return p_output_symbol();
46✔
3665
   default:
×
3666
      one_of(tUDPLEVEL, tMINUS);
×
3667
      return '-';
×
3668
   }
3669
}
3670

3671
static char p_edge_symbol(void)
10✔
3672
{
3673
   // r | R | f | F | p | P | n | N | *
3674

3675
   BEGIN("edge symbol");
20✔
3676

3677
   if (consume(tUDPEDGE))
10✔
3678
      return (char)state.last_lval.i64;
10✔
3679
   else
3680
      return '*';
3681
}
3682

3683
static void p_level_input_list(text_buf_t *tb)
33✔
3684
{
3685
   // level_symbol { level_symbol }
3686

3687
   BEGIN("level input list");
66✔
3688

3689
   do {
96✔
3690
      tb_append(tb, p_level_symbol());
96✔
3691
   } while (not_at_token(tCOLON));
96✔
3692
}
33✔
3693

3694
static void p_edge_indicator(text_buf_t *tb)
67✔
3695
{
3696
   // ( level_symbol level_symbol ) | edge_symbol
3697

3698
   BEGIN("edge indicator");
134✔
3699

3700
   switch (peek()) {
67✔
3701
   case tUDPEDGE:
10✔
3702
      tb_append(tb, p_edge_symbol());
10✔
3703
      break;
10✔
3704
   case tUDPIND:
57✔
3705
      consume(tUDPIND);
57✔
3706
      tb_cat(tb, state.last_lval.str);
57✔
3707
      free(state.last_lval.str);
57✔
3708
      break;
57✔
3709
   default:
×
3710
      should_not_reach_here();
3711
   }
3712
}
67✔
3713

3714
static void p_seq_input_list(text_buf_t *tb)
67✔
3715
{
3716
   // level_input_list | edge_input_list
3717

3718
   BEGIN("sequential input list");
134✔
3719

3720
   bool have_edge = false;
67✔
3721
   do {
133✔
3722
      switch (peek()) {
133✔
3723
      case tUDPEDGE:
67✔
3724
      case tUDPIND:
3725
         p_edge_indicator(tb);
67✔
3726
         if (have_edge)
67✔
3727
            parse_error(&state.last_loc, "a sequential input list may have at "
1✔
3728
                        "most one edge indicator");
3729
         have_edge = true;
3730
         break;
3731

3732
      case tUDPLEVEL:
66✔
3733
         tb_append(tb, p_level_symbol());
66✔
3734
         break;
66✔
3735

3736
      default:
×
3737
         one_of(tUDPEDGE, tUDPIND, tUDPLEVEL);
×
3738
         break;
×
3739
      }
3740
   } while (not_at_token(tCOLON));
133✔
3741
}
67✔
3742

3743
static vlog_node_t p_combinational_entry(void)
33✔
3744
{
3745
   // level_input_list : output_symbol ;
3746

3747
   BEGIN("combinational entry");
66✔
3748

3749
   LOCAL_TEXT_BUF tb = tb_new();
33✔
3750
   p_level_input_list(tb);
33✔
3751

3752
   consume(tCOLON);
33✔
3753
   tb_append(tb, ':');
33✔
3754

3755
   tb_append(tb, p_output_symbol());
33✔
3756

3757
   vlog_node_t v = vlog_new(V_UDP_ENTRY);
33✔
3758
   vlog_set_text(v, tb_get(tb));
33✔
3759

3760
   consume(tSEMI);
33✔
3761

3762
   vlog_set_loc(v, CURRENT_LOC);
33✔
3763
   return v;
33✔
3764
}
3765

3766
static vlog_node_t p_combinational_body(void)
8✔
3767
{
3768
   // table combinational_entry { combinational_entry } endtable
3769

3770
   BEGIN("combinational UDP body");
8✔
3771

3772
   consume(tTABLE);
8✔
3773

3774
   scan_as_udp();
8✔
3775

3776
   vlog_node_t v = vlog_new(V_UDP_TABLE);
8✔
3777
   vlog_set_subkind(v, V_UDP_COMB);
8✔
3778
   vlog_set_ident(v, ident_new("combinational"));
8✔
3779

3780
   do {
33✔
3781
      vlog_add_param(v, p_combinational_entry());
33✔
3782
   } while (not_at_token(tENDTABLE));
33✔
3783

3784
   scan_as_verilog();
8✔
3785

3786
   consume(tENDTABLE);
8✔
3787

3788
   vlog_set_loc(v, CURRENT_LOC);
8✔
3789
   return v;
8✔
3790
}
3791

3792
static vlog_node_t p_sequential_entry(void)
67✔
3793
{
3794
   // seq_input_list : current_state : next_state ;
3795

3796
   BEGIN("sequential entry");
134✔
3797

3798
   LOCAL_TEXT_BUF tb = tb_new();
67✔
3799
   p_seq_input_list(tb);
67✔
3800

3801
   consume(tCOLON);
67✔
3802
   tb_append(tb, ':');
67✔
3803

3804
   tb_append(tb, p_level_symbol());
67✔
3805

3806
   consume(tCOLON);
67✔
3807
   tb_append(tb, ':');
67✔
3808

3809
   tb_append(tb, p_next_state());
67✔
3810

3811
   vlog_node_t v = vlog_new(V_UDP_ENTRY);
67✔
3812
   vlog_set_text(v, tb_get(tb));
67✔
3813

3814
   consume(tSEMI);
67✔
3815

3816
   vlog_set_loc(v, CURRENT_LOC);
67✔
3817
   return v;
67✔
3818
}
3819

3820
static vlog_node_t p_udp_initial_statement(void)
4✔
3821
{
3822
   // initial output_port_identifier = init_val ;
3823

3824
   BEGIN("UDP initial statement");
4✔
3825

3826
   consume(tINITIAL);
4✔
3827

3828
   vlog_node_t ref = vlog_new(V_REF);
4✔
3829
   vlog_set_ident(ref, p_identifier());
4✔
3830
   vlog_set_loc(ref, &state.last_loc);
4✔
3831

3832
   consume(tEQ);
4✔
3833

3834
   vlog_node_t v = vlog_new(V_BASSIGN);
4✔
3835
   vlog_set_target(v, ref);
4✔
3836
   vlog_set_value(v, p_integral_number());
4✔
3837

3838
   consume(tSEMI);
4✔
3839

3840
   vlog_set_loc(v, CURRENT_LOC);
4✔
3841
   return v;
4✔
3842
}
3843

3844
static vlog_node_t p_sequential_body(void)
9✔
3845
{
3846
   // [ udp_initial_statement ] table sequential_entry
3847
   //     { sequential_entry } endtable
3848

3849
   BEGIN("sequential UDP body");
9✔
3850

3851
   vlog_node_t v = vlog_new(V_UDP_TABLE);
9✔
3852
   vlog_set_subkind(v, V_UDP_SEQ);
9✔
3853
   vlog_set_ident(v, ident_new("sequential"));
9✔
3854

3855
   if (peek() == tINITIAL)
9✔
3856
      vlog_add_stmt(v, p_udp_initial_statement());
4✔
3857

3858
   consume(tTABLE);
9✔
3859

3860
   scan_as_udp();
9✔
3861

3862
   do {
67✔
3863
      vlog_add_param(v, p_sequential_entry());
67✔
3864
   } while (not_at_token(tENDTABLE));
67✔
3865

3866
   scan_as_verilog();
9✔
3867

3868
   consume(tENDTABLE);
9✔
3869

3870
   vlog_set_loc(v, CURRENT_LOC);
9✔
3871
   return v;
9✔
3872
}
3873

3874
static vlog_node_t p_udp_body(bool has_reg)
17✔
3875
{
3876
   // combinational_body | sequential_body
3877

3878
   BEGIN("UDP body");
34✔
3879

3880
   if (has_reg)
17✔
3881
      return p_sequential_body();
9✔
3882
   else
3883
      return p_combinational_body();
8✔
3884
}
3885

3886
static vlog_node_t p_udp_ansi_declaration(bool *has_reg)
1✔
3887
{
3888
   // { attribute_instance } primitive udp_identifier
3889
   //    ( udp_declaration_port_list ) ;
3890

3891
   BEGIN("UDP ANSI declaration");
1✔
3892

3893
   while (peek() == tATTRBEGIN)
1✔
3894
      p_attribute_instance();
×
3895

3896
   vlog_node_t udp = vlog_new(V_PRIMITIVE);
1✔
3897

3898
   consume(tPRIMITIVE);
1✔
3899

3900
   ident_t id, ext;
1✔
3901
   p_external_identifier(&id, &ext);
1✔
3902
   vlog_set_ident2(udp, id);
1✔
3903

3904
   ident_t qual = ident_prefix(lib_name(lib_work()), ext, '.');
1✔
3905
   vlog_set_ident(udp, qual);
1✔
3906

3907
   consume(tLPAREN);
1✔
3908

3909
   p_udp_declaration_port_list(udp, has_reg);
1✔
3910

3911
   consume(tRPAREN);
1✔
3912
   consume(tSEMI);
1✔
3913

3914
   vlog_set_loc(udp, CURRENT_LOC);
1✔
3915
   return udp;
1✔
3916
}
3917

3918
static vlog_node_t p_udp_declaration(void)
17✔
3919
{
3920
   // udp_nonansi_declaration udp_port_declaration { udp_port_declaration }
3921
   //        udp_body endprimitive [ : udp_identifier ]
3922
   //   | udp_ansi_declaration udp_body endprimitive [ : udp_identifier ]
3923
   //   | extern udp_nonansi_declaration
3924
   //   | extern udp_ansi_declaration
3925
   //   | { attribute_instance } primitive udp_identifier ( .* ) ;
3926
   //        { udp_port_declaration } udp_body endprimitive [ : udp_identifier ]
3927

3928
   BEGIN("UDP declaration");
17✔
3929

3930
   bool has_reg = false;
17✔
3931
   vlog_node_t udp;
17✔
3932
   if (peek_nth(4) == tID) {
17✔
3933
      udp = p_udp_nonansi_declaration();
16✔
3934

3935
      do {
39✔
3936
         p_udp_port_declaration(udp, &has_reg);
39✔
3937
      } while (not_at_token(tTABLE, tINITIAL));
39✔
3938
   }
3939
   else
3940
      udp = p_udp_ansi_declaration(&has_reg);
1✔
3941

3942
   vlog_add_stmt(udp, p_udp_body(has_reg));
17✔
3943

3944
   consume(tENDPRIMITIVE);
17✔
3945

3946
   return udp;
17✔
3947
}
3948

3949
static vlog_node_t p_description(void)
129✔
3950
{
3951
   // module_declaration | udp_declaration | interface_declaration
3952
   //   | program_declaration | package_declaration
3953
   //   | { attribute_instance } package_item
3954
   //   | { attribute_instance } bind_directive
3955
   //   | config_declaration
3956

3957
   BEGIN("description");
258✔
3958

3959
   switch (peek()) {
129✔
3960
   case tMODULE:
112✔
3961
      return p_module_declaration();
112✔
3962
   case tPRIMITIVE:
17✔
3963
      return p_udp_declaration();
17✔
3964
   default:
×
3965
      expect(tPRIMITIVE, tMODULE);
×
3966
      return NULL;
×
3967
   }
3968
}
3969

3970
static void p_timescale_compiler_directive(void)
9✔
3971
{
3972
   // `timescale time_unit / time_precision
3973

3974
   BEGIN("timescale compiler directive");
18✔
3975

3976
   consume(tTIMESCALE);
9✔
3977

3978
   consume(tUNSIGNED);
9✔
3979
   char *unit_value LOCAL = state.last_lval.str;
18✔
3980

3981
   consume(tID);
9✔
3982
   char *unit_name LOCAL = state.last_lval.str;
18✔
3983

3984
   consume(tOVER);
9✔
3985

3986
   consume(tUNSIGNED);
9✔
3987
   char *prec_value LOCAL = state.last_lval.str;
18✔
3988

3989
   consume(tID);
9✔
3990
   char *prec_name LOCAL = state.last_lval.str;
18✔
3991

3992
   set_timescale(unit_value, unit_name, prec_value, prec_name, CURRENT_LOC);
9✔
3993
}
9✔
3994

3995
static void p_defaultnettype_compiler_directive(void)
12✔
3996
{
3997
   // `default_nettype wire | tri | tri0 | tri1 | wand | triand | wor | trior | trireg | uwire | none
3998

3999
   BEGIN("default_nettype directive");
24✔
4000

4001
   consume(tDEFNETTYPE);
12✔
4002

4003
   one_of(tWIRE, tTRI, tTRI0, tTRI1, tWAND, tTRIAND, tWOR, tTRIOR, tTRIREG, tUWIRE, tNONE);
12✔
4004

4005
   // TODO: do something with the directive
4006
}
12✔
4007

4008
static void p_keywords_directive(void)
1✔
4009
{
4010
   // `begin_keywords "version_specifier"
4011

4012
   BEGIN("keywords directive");
1✔
4013

4014
   consume(tBEGINKEYWORDS);
1✔
4015

4016
   consume(tSTRING);
1✔
4017
   free(state.last_lval.str);
1✔
4018
}
1✔
4019

4020
static void p_endkeywords_directive(void)
1✔
4021
{
4022
   // `end_keywords
4023

4024
   BEGIN("endkeywords directive");
2✔
4025

4026
   consume(tENDKEYWORDS);
1✔
4027
}
1✔
4028

4029
static void p_directive_list(void)
130✔
4030
{
4031
   BEGIN("directive list");
130✔
4032

4033
   for (;;) {
153✔
4034
      switch (peek()) {
153✔
4035
      case tDEFNETTYPE:
12✔
4036
         p_defaultnettype_compiler_directive();
12✔
4037
         break;
12✔
4038
      case tTIMESCALE:
9✔
4039
         p_timescale_compiler_directive();
9✔
4040
         break;
9✔
4041
      case tBEGINKEYWORDS:
1✔
4042
         p_keywords_directive();
1✔
4043
         break;
1✔
4044
      case tENDKEYWORDS:
1✔
4045
         p_endkeywords_directive();
1✔
4046
         break;
1✔
4047
      default:
4048
         return;
130✔
4049
      }
4050
   }
4051
}
4052

4053
vlog_node_t vlog_parse(void)
226✔
4054
{
4055
   state.n_correct = RECOVER_THRESH;
226✔
4056

4057
   scan_as_verilog();
226✔
4058

4059
   if (peek() == tEOF)
226✔
4060
      return NULL;
4061

4062
   p_directive_list();
130✔
4063

4064
   make_new_arena();
130✔
4065

4066
   if (peek() == tEOF)
130✔
4067
      return NULL;
4068

4069
   return p_description();
129✔
4070
}
4071

4072
void reset_verilog_parser(void)
186✔
4073
{
4074
   state.tokenq_head = state.tokenq_tail = 0;
186✔
4075
}
186✔
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