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

nickg / nvc / 9898011961

11 Jul 2024 08:24PM UTC coverage: 91.578% (-0.002%) from 91.58%
9898011961

push

github

nickg
Fix handling of multi-line PSL comments

1 of 1 new or added line in 1 file covered. (100.0%)

13 existing lines in 2 files now uncovered.

56943 of 62180 relevant lines covered (91.58%)

671692.08 hits per line

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

91.97
/src/lexer.l
1
/* -*- mode: c; c-basic-offset: 3 -*- */
2

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

20

21
%option noyywrap
22
%option nounput
23
%option noinput
24

25
%{
26
#include "util.h"
27
#include "common.h"
28
#include "diag.h"
29
#include "ident.h"
30
#include "option.h"
31
#include "scan.h"
32
#include "tree.h"
33

34
#include <ctype.h>
35
#include <math.h>
36
#include <string.h>
37

38
#define YY_INPUT(buf, result, max_size) {    \
39
      result = get_next_char(buf, max_size); \
40
      if (result <= 0)                       \
41
         result = YY_NULL;                   \
42
   }
43

44
#define YY_USER_ACTION begin_token(yytext, yyleng);
45

46
#define TOKEN(t) return (last_token = (t))
47

48
#define TOKEN_LRM(t, lrm) do {                                          \
49
      if (standard() < lrm) {                                           \
50
         static bool warned = false;                                    \
51
         if (!warned) {                                                 \
52
            warn_lrm(lrm, "`%s' is a reserved word in VHDL-%s",         \
53
                     yytext, standard_text(lrm));                       \
54
            warned = true;                                              \
55
         }                                                              \
56
         return isalnum(yytext[0]) ? parse_id(yytext) : tERROR;         \
57
      }                                                                 \
58
      else                                                              \
59
         return (last_token = (t));                                     \
60
   } while (0)
61

62
#define MIN_STD(lrm, what) do {                                         \
63
      static bool warned = false;                                       \
64
      if (!warned && standard() < lrm) {                                \
65
         warn_lrm(lrm, "%s are a VHDL-%s feature", what,                \
66
                  standard_text(lrm));                                  \
67
         warned = true;                                                 \
68
      }                                                                 \
69
   } while (0)
70

71
#define TOKEN_00(t) TOKEN_LRM(t, STD_00)
72
#define TOKEN_08(t) TOKEN_LRM(t, STD_08)
73
#define TOKEN_19(t) TOKEN_LRM(t, STD_19)
74

75
static int parse_id(char *str);
76
static int parse_ex_id(char *str);
77
static int parse_bit_string(const char *str);
78
static int parse_string(const char *str);
79
static int parse_decimal_literal(const char *str);
80
static int parse_based_literal(const char *str);
81
static int resolve_ir1045(void);
82
static void warn_lrm(vhdl_standard_t std, const char *fmt, ...);
83
static void warn_utf8(const char *str);
84
static bool begin_psl_comment(void);
85
static int escape_verilog_string(const char *str);
86
static int report_unterminated_string(const char *str);
87
static int report_bad_identifier(char *str);
88

89
static int last_token = -1;
90
static int comment_caller = 0;
91

92
extern loc_t yylloc;
93
extern yylval_t yylval;
94
%}
95

96
LOWER           [a-z\xdf-\xf6\xf8-\xff]
97
UPPER           [A-Z\xc0-\xd6\xd8-\xde]
98
VHDL_ID         ({LOWER}|{UPPER})(_?({LOWER}|{UPPER}|[0-9]))*
99
BAD_ID          ({LOWER}|{UPPER}|_)({LOWER}|{UPPER}|[0-9_])*
100
EXID            \\([^\\\n]|\\\\)*\\
101
VLOG_ID         [a-zA-Z_]([a-zA-Z0-9_$])*
102
SYSTASK         \$[a-zA-Z_$]([a-zA-Z0-9_$])*
103
STRING          (\"([^\"\n]|\"\")*\")|(\%([^\"\n\%]|\%\%)*\%)
104
BADSTRING       (\"([^\"\n]|\"\")*)|(\%([^\"\n\%]|\%\%)*)
105
VLOG_STRING     "\""[^\n\"]*"\""
106
BITSTRING       [0-9]*[usUS]?(?i:[boxd]\"[^\"\n]*\")|(?i:[boxd]\%[^\n\%]*\%)
107
CHAR            '.'
108
INTEGER         [0-9][0-9_]*
109
EXPONENT        [Ee][+-]?{INTEGER}
110
DECIMAL         {INTEGER}(\.{INTEGER})?{EXPONENT}?
111
HEX             [0-9a-fA-F][0-9a-fA-F_]*
112
BASED_HASH      {INTEGER}[#]{HEX}(\.{HEX})?[#]{EXPONENT}?
113
BASED_COLON     {INTEGER}[:]{HEX}(\.{HEX})?[:]{EXPONENT}?
114
BASED           {BASED_HASH}|{BASED_COLON}
115
SPACE           [ \t\r]+
116
TICK            \'
117
PRAGMA          --[ \t]*
118
SYNTH_OFF       {PRAGMA}(?i:synthesis)[ \t]+(?i:translate_off).*
119
SYNTH_ON        {PRAGMA}(?i:synthesis)[ \t]+(?i:translate_on).*
120
COVERAGE_OFF    {PRAGMA}(?i:coverage)[ \t]+(?i:off).*
121
COVERAGE_ON     {PRAGMA}(?i:coverage)[ \t]+(?i:on).*
122
TRANSLATE_OFF   {PRAGMA}(?i:pragma)[ \t]+(?i:translate_off).*
123
TRANSLATE_ON    {PRAGMA}(?i:pragma)[ \t]+(?i:translate_on).*
124
PSL_COMMENT     {PRAGMA}(?i:psl)[ \t]+
125
PSL_CONT        ^{SPACE}*({PSL_COMMENT}|"--")
126
UTF8_MB         [\x80-\xff][\x80-\xbf]{1,3}
127
VLOG_NUMBER     {INTEGER}?\'[bhd]{HEX}
128

129
%x COMMENT C_COMMENT PSL VLOG
130

131
ENTITY        ?i:entity
132
IS            ?i:is
133
END           ?i:end
134
GENERIC       ?i:generic
135
PORT          ?i:port
136
CONSTANT      ?i:constant
137
CONFIGURATION ?i:configuration
138
COMPONENT     ?i:component
139
ARCHITECTURE  ?i:architecture
140
OF            ?i:of
141
BEGIN         ?i:begin
142
AND           ?i:and
143
OR            ?i:or
144
XOR           ?i:xor
145
XNOR          ?i:xnor
146
NOR           ?i:nor
147
NAND          ?i:nand
148
ABS           ?i:abs
149
NOT           ?i:not
150
ALL           ?i:all
151
IN            ?i:in
152
OUT           ?i:out
153
BUFFER        ?i:buffer
154
BUS           ?i:bus
155
REGISTER      ?i:register
156
UNAFFECTED    ?i:unaffected
157
SIGNAL        ?i:signal
158
PROCESS       ?i:process
159
WAIT          ?i:wait
160
REPORT        ?i:report
161
INOUT         ?i:inout
162
LINKAGE       ?i:linkage
163
VARIABLE      ?i:variable
164
FOR           ?i:for
165
TYPE          ?i:type
166
RANGE         ?i:range
167
TO            ?i:to
168
DOWNTO        ?i:downto
169
SUBTYPE       ?i:subtype
170
UNITS         ?i:units
171
PACKAGE       ?i:package
172
LIBRARY       ?i:library
173
USE           ?i:use
174
NULL          ?i:null
175
FUNCTION      ?i:function
176
IMPURE        ?i:impure
177
PURE          ?i:pure
178
RETURN        ?i:return
179
ARRAY         ?i:array
180
OTHERS        ?i:others
181
ASSERT        ?i:assert
182
SEVERITY      ?i:severity
183
ON            ?i:on
184
MAP           ?i:map
185
IF            ?i:if
186
THEN          ?i:then
187
ELSE          ?i:else
188
ELSIF         ?i:elsif
189
BODY          ?i:body
190
WHILE         ?i:while
191
LOOP          ?i:loop
192
AFTER         ?i:after
193
ALIAS         ?i:alias
194
MOD           ?i:mod
195
ATTRIBUTE     ?i:attribute
196
PROCEDURE     ?i:procedure
197
EXIT          ?i:exit
198
REM           ?i:rem
199
WHEN          ?i:when
200
CASE          ?i:case
201
TRANSPORT     ?i:transport
202
INERTIAL      ?i:inertial
203
REJECT        ?i:reject
204
BLOCK         ?i:block
205
WITH          ?i:with
206
SELECT        ?i:select
207
GENERATE      ?i:generate
208
ACCESS        ?i:access
209
POSTPONED     ?i:postponed
210
FILE          ?i:file
211
OPEN          ?i:open
212
UNTIL         ?i:until
213
RECORD        ?i:record
214
NEW           ?i:new
215
SHARED        ?i:shared
216
NEXT          ?i:next
217
SLL           ?i:sll
218
SRL           ?i:srl
219
SLA           ?i:sla
220
SRA           ?i:sra
221
ROL           ?i:rol
222
ROR           ?i:ror
223
GROUP         ?i:group
224
LABEL         ?i:label
225
LITERAL       ?i:literal
226
GUARDED       ?i:guarded
227
REVRANGE      ?i:reverse_range
228
PROTECTED     ?i:protected
229
CONTEXT       ?i:context
230
ERROR         ?i:error
231
WARNING       ?i:warning
232
DISCONNECT    ?i:disconnect
233
FORCE         ?i:force
234
RELEASE       ?i:release
235
PARAMETER     ?i:parameter
236
ALWAYS        ?i:always
237
DEFAULT       ?i:default
238
CLOCK         ?i:clock
239
NEVER         ?i:never
240
EVENTUALLY    ?i:eventually
241
NEXT_A        ?i:next_a
242
NEXT_E        ?i:next_e
243
NEXT_EVENT    ?i:next_event
244
ASSUME        ?i:assume
245
ASSUME_G      ?i:assume_guarantee
246
RESTRICT      ?i:restrict
247
RESTRICT_G    ?i:restrict_guarantee
248
STRONG        ?i:strong
249
FAIRNESS      ?i:fairness
250
COVER         ?i:cover
251
PROPERTY      ?i:property
252
SEQUENCE      ?i:sequence
253
CONST         ?i:const
254
MUTABLE       ?i:mutable
255
HDLTYPE       ?i:hdltype
256
BOOLEAN       ?i:boolean
257
BIT           ?i:bit
258
BITVECTOR     ?i:bitvector
259
NUMERIC       ?i:numeric
260
STRING_K      ?i:string
261
WITHIN        ?i:within
262
VIEW          ?i:view
263
PRIVATE       ?i:private
264
PREV          ?i:prev
265
STABLE        ?i:stable
266
ROSE          ?i:rose
267
FELL          ?i:fell
268
ENDED         ?i:ended
269
NONDET        ?i:nondet
270
NONDET_V      ?i:nondet_vector
271
UNION         ?i:union
272

273
%%
274

275
{SYNTH_OFF}              { TOKEN(tSYNTHOFF); }
4✔
276
{SYNTH_ON}               { TOKEN(tSYNTHON); }
3✔
277
{COVERAGE_OFF}           { TOKEN(tCOVERAGEOFF); }
23✔
278
{COVERAGE_ON}            { TOKEN(tCOVERAGEON); }
25✔
279
{TRANSLATE_OFF}          { TOKEN(tTRANSLATEOFF); }
24✔
280
{TRANSLATE_ON}           { TOKEN(tTRANSLATEON); }
22✔
281

1✔
282
<PSL,INITIAL>"--"        { comment_caller = YY_START; BEGIN(COMMENT); }
×
283
<VLOG>"//"               { comment_caller = YY_START; BEGIN(COMMENT); }
52,203✔
284
{PSL_COMMENT}            { if (begin_psl_comment()) {
387✔
285
                              BEGIN(PSL);
160✔
286
                              TOKEN(tSTARTPSL);
454✔
287
                           }
288
                           else {
289
                              comment_caller = YY_START;
×
290
                              BEGIN(COMMENT);
×
291
                           }
292
                         }
293

×
294
<COMMENT>\n              { BEGIN(comment_caller); }
104,726✔
295
<COMMENT>.*              { }
52,363✔
296

101,994✔
297
"/*"                     { MIN_STD(STD_08, "delimited comments");
49,634✔
298
                           comment_caller = YY_START;
3✔
299
                           BEGIN(C_COMMENT);
3✔
300
                         }
301
<VLOG>"/*"               { comment_caller = YY_START; BEGIN(C_COMMENT); }
3✔
302
<C_COMMENT>"*/"          { BEGIN(comment_caller); }
6✔
303
<C_COMMENT>\n            { /* Must match a single character */ }
15✔
304
<C_COMMENT>.             { }
9✔
305

4,898✔
306
<PSL>;                   { TOKEN(tSEMI); }
2,818✔
307
<PSL>{PSL_CONT}          { /* Multi-line PSL comment */ }
316✔
308
<PSL>"--"                { comment_caller = YY_START; BEGIN(COMMENT); }
14✔
309

7✔
310
{ENTITY}                 { TOKEN(tENTITY); }
9,622✔
311
{IS}                     { TOKEN(tIS); }
43,139✔
312
{END}                    { TOKEN(tEND); }
39,721✔
313
{GENERIC}                { TOKEN(tGENERIC); }
35,461✔
314
{PORT}                   { TOKEN(tPORT); }
41,986✔
315
{CONSTANT}               { TOKEN(tCONSTANT); }
13,606✔
316
{COMPONENT}              { TOKEN(tCOMPONENT); }
3,034✔
317
{CONFIGURATION}          { TOKEN(tCONFIGURATION); }
11,903✔
318
{ARCHITECTURE}           { TOKEN(tARCHITECTURE); }
9,300✔
319
{OF}                     { TOKEN(tOF); }
7,764✔
320
{BEGIN}                  { TOKEN(tBEGIN); }
27,157✔
321
{IN}                     { TOKEN(tIN); }
18,973✔
322
{OUT}                    { TOKEN(tOUT); }
21,348✔
323
{BUFFER}                 { TOKEN(tBUFFER); }
11,459✔
324
{BUS}                    { TOKEN(tBUS); }
2,745✔
325
{REGISTER}               { TOKEN(tREGISTER); }
12✔
326
{UNAFFECTED}             { TOKEN(tUNAFFECTED); }
39✔
327
{SIGNAL}                 { TOKEN(tSIGNAL); }
6,089✔
328
{PROCESS}                { TOKEN(tPROCESS); }
8,847✔
329
{WAIT}                   { TOKEN(tWAIT); }
14,647✔
330
{REPORT}                 { TOKEN(tREPORT); }
17,101✔
331
{INOUT}                  { TOKEN(tINOUT); }
10,184✔
332
{LINKAGE}                { TOKEN(tLINKAGE); }
8,277✔
333
{VARIABLE}               { TOKEN(tVARIABLE); }
12,302✔
334
{FOR}                    { TOKEN(tFOR); }
7,785✔
335
{TYPE}                   { TOKEN(tTYPE); }
15,841✔
336
{SUBTYPE}                { TOKEN(tSUBTYPE); }
9,247✔
337
{UNITS}                  { TOKEN(tUNITS); }
5,256✔
338
{PACKAGE}                { TOKEN(tPACKAGE); }
5,712✔
339
{LIBRARY}                { TOKEN(tLIBRARY); }
1,046✔
340
{USE}                    { TOKEN(tUSE); }
7,192✔
341
{FUNCTION}               { TOKEN(tFUNCTION); }
19,458✔
342
{IMPURE}                 { TOKEN(tIMPURE); }
3,760✔
343
{PURE}                   { TOKEN(tPURE); }
18,542✔
344
{RETURN}                 { TOKEN(tRETURN); }
27,221✔
345
{ARRAY}                  { TOKEN(tARRAY); }
2,399✔
346
{OTHERS}                 { TOKEN(tOTHERS); }
29,242✔
347
{ASSERT}                 { TOKEN(tASSERT); }
18,927✔
348
{SEVERITY}               { TOKEN(tSEVERITY); }
9,210✔
349
{ON}                     { TOKEN(tON); }
16,898✔
350
{MAP}                    { TOKEN(tMAP); }
8,555✔
351
{IF}                     { TOKEN(tIF); }
17,733✔
352
{THEN}                   { TOKEN(tTHEN); }
11,690✔
353
{ELSE}                   { TOKEN(tELSE); }
19,930✔
354
{ELSIF}                  { TOKEN(tELSIF); }
10,370✔
355
{BODY}                   { TOKEN(tBODY); }
4,269✔
356
{WHILE}                  { TOKEN(tWHILE); }
1,058✔
357
{LOOP}                   { TOKEN(tLOOP); }
7,566✔
358
{AFTER}                  { TOKEN(tAFTER); }
964✔
359
{ALIAS}                  { TOKEN(tALIAS); }
7,333✔
360
{ATTRIBUTE}              { TOKEN(tATTRIBUTE); }
1,202✔
361
{PROCEDURE}              { TOKEN(tPROCEDURE); }
6,288✔
362
{POSTPONED}              { TOKEN(tPOSTPONED); }
482✔
363
{EXIT}                   { TOKEN(tEXIT); }
5,099✔
364
{WHEN}                   { TOKEN(tWHEN); }
3,214✔
365
{CASE}                   { TOKEN(tCASE); }
1,391✔
366
{TRANSPORT}              { TOKEN(tTRANSPORT); }
3,234✔
367
{REJECT}                 { TOKEN(tREJECT); }
1,087✔
368
{INERTIAL}               { TOKEN(tINERTIAL); }
89✔
369
{BLOCK}                  { TOKEN(tBLOCK); }
628✔
370
{WITH}                   { TOKEN(tWITH); }
85✔
371
{SELECT}                 { TOKEN(tSELECT); }
675✔
372
{GENERATE}               { TOKEN(tGENERATE); }
713✔
373
{ACCESS}                 { TOKEN(tACCESS); }
373✔
374
{FILE}                   { TOKEN(tFILE); }
931✔
375
{OPEN}                   { TOKEN(tOPEN); }
466✔
376
{RECORD}                 { TOKEN(tRECORD); }
2,511✔
377
{NEW}                    { TOKEN(tNEW); }
1,101✔
378
{SHARED}                 { TOKEN(tSHARED); }
2,405✔
379
{NEXT}                   { TOKEN(tNEXT); }
1,045✔
380
{LITERAL}                { TOKEN(tLITERAL); }
184✔
381
{GROUP}                  { TOKEN(tGROUP); }
100✔
382
{LABEL}                  { TOKEN(tLABEL); }
16✔
383
{GUARDED}                { TOKEN(tGUARDED); }
28✔
384
{DISCONNECT}             { TOKEN(tDISCONNECT); }
17✔
385
{REVRANGE}               { TOKEN(tREVRANGE); }
70✔
386
{PROTECTED}              { TOKEN_00(tPROTECTED); }
810✔
387
{CONTEXT}                { TOKEN_08(tCONTEXT); }
108✔
388
{FORCE}                  { TOKEN_08(tFORCE); }
851✔
389
{RELEASE}                { TOKEN_08(tRELEASE); }
98✔
390
{PARAMETER}              { TOKEN_08(tPARAMETER); }
96✔
391
{DEFAULT}                { TOKEN_08(tDEFAULT); }
46✔
392
{VIEW}                   { TOKEN_19(tVIEW); }
239✔
393
{PRIVATE}                { TOKEN_19(tPRIVATE); }
36✔
394

198✔
395
`{IF}                    { TOKEN(tCONDIF); }
80✔
396
`{ELSE}                  { TOKEN(tCONDELSE); }
66✔
397
`{ELSIF}                 { TOKEN(tCONDELSIF); }
4✔
398
`{END}                   { TOKEN(tCONDEND); }
66✔
399
`{ERROR}                 { TOKEN(tCONDERROR); }
8✔
400
`{WARNING}               { TOKEN(tCONDWARN); }
60✔
401

4✔
402
<INITIAL,PSL>{AND}       { TOKEN(tAND); }
5,783✔
403
<INITIAL,PSL>{OR}        { TOKEN(tOR); }
7,579✔
404
<INITIAL,PSL>{XOR}       { TOKEN(tXOR); }
342✔
405
<INITIAL,PSL>{XNOR}      { TOKEN(tXNOR); }
1,943✔
406
<INITIAL,PSL>{NAND}      { TOKEN(tNAND); }
489✔
407
<INITIAL,PSL>{NOR}       { TOKEN(tNOR); }
292✔
408
<INITIAL,PSL>{ABS}       { TOKEN(tABS); }
395✔
409
<INITIAL,PSL>{NOT}       { TOKEN(tNOT); }
3,059✔
410
<INITIAL,PSL>{ALL}       { TOKEN(tALL); }
3,983✔
411
<INITIAL,PSL>{TICK}      { TOKEN(tTICK); }
28,973✔
412
<INITIAL,PSL>{SLL}       { TOKEN(tSLL); }
3,771✔
413
<INITIAL,PSL>{SRL}       { TOKEN(tSRL); }
26,097✔
414
<INITIAL,PSL>{SLA}       { TOKEN(tSLA); }
62✔
415
<INITIAL,PSL>{SRA}       { TOKEN(tSRA); }
64✔
416
<INITIAL,PSL>{ROL}       { TOKEN(tROL); }
119✔
417
<INITIAL,PSL>{ROR}       { TOKEN(tROR); }
122✔
418
<INITIAL,PSL>{REM}       { TOKEN(tREM); }
231✔
419
<INITIAL,PSL>{MOD}       { TOKEN(tMOD); }
359✔
420
<INITIAL,PSL>{NULL}      { TOKEN(tNULL); }
562✔
421
<INITIAL,PSL>{RANGE}     { TOKEN(tRANGE); }
5,005✔
422
<INITIAL,PSL>{TO}        { TOKEN(tTO); }
7,437✔
423
<INITIAL,PSL>{DOWNTO}    { TOKEN(tDOWNTO); }
11,542✔
424
<INITIAL,PSL>{UNTIL}     { TOKEN(tUNTIL); }
7,265✔
425

6,806✔
426
<*>"("                   { TOKEN(tLPAREN); }
102,356✔
427
<*>")"                   { TOKEN(tRPAREN); }
204,207✔
428
<*>"["                   { TOKEN(tLSQUARE); }
788✔
429
<*>"]"                   { TOKEN(tRSQUARE); }
102,915✔
430
<*>"{"                   { TOKEN(tLBRACE); }
883✔
431
<*>"}"                   { TOKEN(tRBRACE); }
907✔
432
<*>","                   { TOKEN(tCOMMA); }
68,442✔
433
<*>";"                   { TOKEN(tSEMI); }
173,543✔
434
<*>":"                   { TOKEN(tCOLON); }
132,650✔
435
<*>"<"                   { TOKEN(tLT); }
175,890✔
436
<*>">"                   { TOKEN(tGT); }
65,774✔
437
<*>"+"                   { TOKEN(tPLUS); }
6,194✔
438
<*>"-"                   { TOKEN(tMINUS); }
15,445✔
439
<*>"*"                   { TOKEN(tTIMES); }
5,516✔
440
<*>"@"                   { TOKEN(tAT); }
14,029✔
441
<*>"?"                   { TOKEN(tQUESTION); }
1,835✔
442
<*>"{"                   { TOKEN(tLBRACE); }
55✔
443
<*>"}"                   { TOKEN(tRBRACE); }
71✔
444
<*>"/"                   { TOKEN(tOVER); }
891✔
445
<*>"."                   { TOKEN(tDOT); }
18,664✔
446
<*>"&"                   { TOKEN(tAMP); }
3,302✔
447
<*>"|"                   { TOKEN(tBAR); }
19,632✔
448
<*>"["                   { TOKEN(tLSQUARE); }
2,411✔
449
<*>"]"                   { TOKEN(tRSQUARE); }
968✔
450
<*>"="                   { TOKEN(tEQ); }
22,777✔
451
<*>"#"                   { TOKEN(tHASH); }
126✔
452
<*>"~"                   { TOKEN(tTILDE); }
22,794✔
453
<*>"[["                  { TOKEN(t2LSQUARE); }
128✔
454
<*>"]]"                  { TOKEN(t2RSQUARE); }
19✔
455

2✔
456
<INITIAL,PSL>"!"         { TOKEN(tBAR); }
4✔
457
<VLOG>"!"                { TOKEN(tBANG); }
15✔
458

303✔
459
<INITIAL,PSL>"**"        { TOKEN(tPOWER); }
303✔
460
<INITIAL,PSL>":="        { TOKEN(tASSIGN); }
31,188✔
461
<INITIAL,PSL>"<>"        { TOKEN(tBOX); }
2,058✔
462
<INITIAL,PSL>"?<"        { TOKEN_08(tMLT); }
30,956✔
463
<INITIAL,PSL>"?<="       { TOKEN_08(tMLE); }
2,116✔
464
<INITIAL,PSL>"?>"        { TOKEN_08(tMGT); }
113✔
465
<INITIAL,PSL>"?>="       { TOKEN_08(tMGE); }
113✔
466
<INITIAL,PSL>"??"        { TOKEN_08(tCCONV); }
57✔
467
<INITIAL,PSL>"/="        { TOKEN(tNEQ); }
1,120✔
468
<INITIAL,PSL>"?/="       { TOKEN_08(tMNEQ); }
65✔
469
<INITIAL,PSL>"?="        { TOKEN_08(tMEQ); }
1,161✔
470
<INITIAL,PSL>"<<"        { TOKEN(tLTLT); }
195✔
471
<INITIAL,PSL>">>"        { TOKEN(tGTGT); }
228✔
472
<INITIAL,PSL>"^"         { TOKEN(tCARET); }
173✔
473

132✔
474
<INITIAL,PSL,VLOG>"<="   { TOKEN(tLE); }
7,401✔
475
<INITIAL,PSL,VLOG>">="   { TOKEN(tGE); }
8,192✔
476
<INITIAL,PSL,VLOG>"=>"   { TOKEN(tASSOC); }
13,974✔
477

832✔
478
<PSL>{ASSERT}            { TOKEN(tASSERT); }
14,084✔
479
<PSL>{ASSUME}            { TOKEN(tASSUME); }
112✔
480
<PSL>{ASSUME_G}          { TOKEN(tASSUMEG); }
1✔
481
<PSL>{RESTRICT}          { TOKEN(tRESTRICT); }
4✔
482
<PSL>{RESTRICT_G}        { TOKEN(tRESTRICTG); }
2✔
483
<PSL>{STRONG}            { TOKEN(tSTRONG); }
3✔
484
<PSL>{FAIRNESS}          { TOKEN(tFAIRNESS); }
4✔
485
<PSL>{COVER}             { TOKEN(tCOVER); }
56✔
486
<PSL>{PROPERTY}          { TOKEN(tPROPERTY); }
24✔
487
<PSL>{SEQUENCE}          { TOKEN(tSEQUENCE); }
59✔
488
<PSL>{CONST}             { TOKEN(tCONST); }
31✔
489
<PSL>{MUTABLE}           { TOKEN(tMUTABLE); }
10✔
490
<PSL>{HDLTYPE}           { TOKEN(tHDLTYPE); }
17✔
491
<PSL>{BOOLEAN}           { TOKEN(tBOOLEAN); }
8✔
492
<PSL>{BIT}               { TOKEN(tBIT); }
9✔
493
<PSL>{BITVECTOR}         { TOKEN(tBITVECTOR); }
4✔
494
<PSL>{NUMERIC}           { TOKEN(tNUMERIC); }
5✔
495
<PSL>{STRING_K}          { TOKEN(tSTRINGK); }
4✔
496
<PSL>{ALWAYS}            { TOKEN(tALWAYS); }
89✔
497
<PSL>{DEFAULT}           { TOKEN(tDEFAULT); }
32✔
498
<PSL>{CLOCK}             { TOKEN(tCLOCK); }
120✔
499
<PSL>{IS}                { TOKEN(tIS); }
87✔
500
<PSL>"->"                { TOKEN(tIFIMPL); }
104✔
501
<PSL>"<->"               { TOKEN(tIFFIMPL); }
57✔
502
<PSL>{NEXT}              { TOKEN(tNEXT); }
120✔
503
<PSL>{NEXT}!             { TOKEN(tNEXT1); }
1✔
504
<PSL>{NEVER}             { TOKEN(tNEVER); }
53✔
505
<PSL>{EVENTUALLY}!       { TOKEN(tEVENTUALLY); }
2✔
506
<PSL>{NEXT_A}            { TOKEN(tNEXTA); }
5✔
507
<PSL>{NEXT_A}!           { TOKEN(tNEXTA1); }
1✔
508
<PSL>{NEXT_E}            { TOKEN(tNEXTE); }
2✔
509
<PSL>{NEXT_E}!           { TOKEN(tNEXTE1); }
×
510
<PSL>{NEXT_EVENT}        { TOKEN(tNEXTEVENT); }
1✔
511
<PSL>{NEXT_EVENT}!       { TOKEN(tNEXTEVENT1); }
×
512
<PSL>"[*"                { TOKEN(tTIMESRPT); }
21✔
513
<PSL>"[+]"               { TOKEN(tPLUSRPT); }
2✔
514
<PSL>"[="                { TOKEN(tGOTORPT); }
23✔
515
<PSL>"[->"               { TOKEN(tARROWRPT); }
3✔
516
<PSL>"&&"                { TOKEN(tDBLAMP); }
5✔
517
<PSL>{WITHIN}            { TOKEN(tWITHIN); }
2✔
518
<PSL>{PREV}              { TOKEN(tPREV); }
2✔
519
<PSL>{STABLE}            { TOKEN(tSTABLE); }
1✔
520
<PSL>{ROSE}              { TOKEN(tROSE); }
×
521
<PSL>{FELL}              { TOKEN(tFELL); }
×
522
<PSL>{ENDED}             { TOKEN(tENDED); }
×
523
<PSL>{NONDET}            { TOKEN(tNONDET); }
×
524
<PSL>{NONDET_V}          { TOKEN(tNONDETV); }
×
525
<PSL>{UNION}             { TOKEN(tUNION); }
×
526
<PSL>{UNTIL}!            { TOKEN(tUNTIL1); }
2✔
527
<PSL>{UNTIL}_            { TOKEN(tUNTIL_); }
10✔
528
<PSL>{UNTIL}_!           { TOKEN(tUNTIL_1); }
3✔
529

10✔
530
<VLOG>"module"           { return tMODULE; }
70✔
531
<VLOG>"endmodule"        { return tENDMODULE; }
138✔
532
<VLOG>"input"            { return tINPUT; }
28✔
533
<VLOG>"output"           { return tOUTPUT; }
100✔
534
<VLOG>"inout"            { return tINOUT; }
29✔
535
<VLOG>"reg"              { return tREG; }
119✔
536
<VLOG>"always"           { return tALWAYS; }
58✔
537
<VLOG>"posedge"          { return tPOSEDGE; }
104✔
538
<VLOG>"negedge"          { return tNEGEDGE; }
57✔
539
<VLOG>"initial"          { return tINITIAL; }
61✔
540
<VLOG>"begin"            { return tBEGIN; }
84✔
541
<VLOG>"end"              { return tEND; }
129✔
542
<VLOG>"wire"             { return tWIRE; }
110✔
543
<VLOG>"assign"           { return tASSIGN; }
113✔
544
<VLOG>"if"               { return tIF; }
70✔
545
<VLOG>"else"             { return tELSE; }
40✔
546
<VLOG>"`timescale"       { return tTIMESCALE; }
53✔
547
<VLOG>"`celldefine"      { }
11✔
548
<VLOG>"`endcelldefine"   { }
9✔
549
<VLOG>"supply0"          { return tSUPPLY0; }
10✔
550
<VLOG>"supply1"          { return tSUPPLY1; }
9✔
551
<VLOG>"pulldown"         { return tPULLDOWN; }
16✔
552
<VLOG>"pullup"           { return tPULLUP; }
21✔
553
<VLOG>"forever"          { return tFOREVER; }
9✔
554
<VLOG>"=="               { return tLOGEQ; }
12✔
555
<VLOG>"!="               { return tLOGNEQ; }
3✔
556
<VLOG>"==="              { return tCASEEQ; }
3✔
557
<VLOG>"!=="              { return tCASENEQ; }
30✔
558
<VLOG>"(*"               { return tATTRBEGIN; }
9✔
559
<VLOG>"*)"               { return tATTREND; }
36✔
560
<VLOG>"specify"          { return tSPECIFY; }
7✔
561
<VLOG>"endspecify"       { return tENDSPECIFY; }
7✔
562

1✔
563
<VLOG>{SYSTASK}          { yylval.str = xstrdup(yytext); return tSYSTASK; }
239✔
564
<VLOG>{VLOG_ID}          { yylval.str = xstrdup(yytext); return tID; }
1,138✔
565
<VLOG>{INTEGER}          { yylval.str = xstrdup(yytext); return tUNSIGNED; }
404✔
566
<VLOG>{VLOG_STRING}      { return escape_verilog_string(yytext); }
1,054✔
567
<VLOG>{VLOG_NUMBER}      { yylval.str = xstrdup(yytext); return tNUMBER; }
426✔
568

154✔
569
<INITIAL,PSL>{DECIMAL}   { return parse_decimal_literal(yytext); }
83,715✔
570
<INITIAL,PSL>{BASED}     { return parse_based_literal(yytext); }
83,744✔
571
<INITIAL,PSL>{BITSTRING} { return parse_bit_string(yytext); }
1,902✔
572
<INITIAL,PSL>{STRING}    { return parse_string(yytext); }
30,078✔
573
<INITIAL,PSL>{BADSTRING} { return report_unterminated_string(yytext); }
1,905✔
574
<INITIAL,PSL>{CHAR}      { if (resolve_ir1045()) {
48,705✔
575
                              yylval.ident = ident_new(yytext);
18,665✔
576
                              TOKEN(tID);
37,340✔
577
                           }
578
                           REJECT;
16✔
579
                         }
580

×
581
% /* These PSL tokens must be scanned in VHDL mode for look-ahead */
×
UNCOV
582
"->"                     { TOKEN(tIFIMPL); }
×
583
"<->"                    { TOKEN(tIFFIMPL); }
×
UNCOV
584
"[*"                     { TOKEN(tTIMESRPT); }
×
UNCOV
585
"[+]"                    { TOKEN(tPLUSRPT); }
×
UNCOV
586
"[="                     { TOKEN(tGOTORPT); }
×
UNCOV
587
"[->"                    { TOKEN(tARROWRPT); }
×
UNCOV
588
{UNTIL}!                 { TOKEN(tUNTIL1); }
×
UNCOV
589
{UNTIL}_                 { TOKEN(tUNTIL_); }
×
UNCOV
590
{UNTIL}_!                { TOKEN(tUNTIL_1); }
×
UNCOV
591

×
UNCOV
592
% /* These VHDL tokens must be scanned in PSL mode for look-ahead */
×
593
<PSL>{SEVERITY}          { TOKEN(tSEVERITY); }
×
594
<PSL>{REPORT}            { TOKEN(tREPORT); }
29✔
595

×
596
<INITIAL,PSL>{UTF8_MB}   { warn_utf8(yytext); REJECT; }
30✔
597

1✔
598
<INITIAL,PSL>{VHDL_ID}   { return parse_id(yytext); }
447,722✔
599
{EXID}                   { return parse_ex_id(yytext); }
447,754✔
600
<INITIAL,PSL>{BAD_ID}    { return report_bad_identifier(yytext); }
5✔
601
<*>{SPACE}               { }
32✔
602
<*>"\n"                  { /* Must match a single character */ }
5✔
603
<*><<EOF>>               { return 0; }
1,041,940✔
604
<*>.                     { TOKEN(tERROR); }
4✔
605

314,379✔
606
%%
4✔
607

×
608
static int resolve_ir1045(void)
18,678✔
609
{
610
   // See here for discussion:
611
   //   http://www.eda-stds.org/isac/IRs-VHDL-93/IR1045.txt
612
   // The set of tokens that may precede a character literal is
613
   // disjoint from that which may precede a single tick token.
614

615
   switch (last_token) {
18,678✔
616
   case tRSQUARE:
617
   case tRPAREN:
618
   case tALL:
619
   case tID:
620
      // Cannot be a character literal
621
      return 0;
622
   default:
18,662✔
623
      return 1;
18,662✔
624
   }
625
}
626

627
static bool begin_psl_comment(void)
227✔
628
{
629
   static bool printed = false;
227✔
630

631
   if (opt_get_int(OPT_PSL_COMMENTS))
227✔
632
      return true;
633
   else if (!printed) {
×
634
      // TODO: enable this once PSL support is complete
635
      // note_at(&yylloc, "pass $bold$--psl$$ to enable parsing of PSL "
636
      //   "directives in comments");
637
      printed = true;
×
638
      return false;
×
639
   }
640
   else
641
      return false;
642
}
643

644
static int parse_id(char *str)
447,729✔
645
{
646
   for (char *p = str; *p; p++)
3,174,873✔
647
      *p = toupper_iso88591(*p);
2,727,144✔
648

649
   yylval.ident = ident_new(str);
447,729✔
650
   TOKEN(tID);
447,729✔
651
}
652

653
static int parse_ex_id(char *str)
32✔
654
{
655
   // Replace double '\\' character by single '\\'
656
   char *p = str + 1;
32✔
657
   for (char *s = p; *s; ) {
198✔
658
      if (*s == '\\' && *(s + 1) == '\\') s++;
166✔
659
      *p++ = *s++;
166✔
660
   }
661
   *p = '\0';
32✔
662

663
   yylval.ident = ident_new(str);
32✔
664
   TOKEN(tID);
32✔
665
}
666

667
static void strip_underscores(char *s)
83,744✔
668
{
669
   bool error = false;
83,744✔
670
   char *p;
83,744✔
671
   for (p = s; *s; s++) {
432,887✔
672
      if (*s != '_')
349,143✔
673
         *p++ = *s;
348,927✔
674
      else if ((s[1] == '\0' || s[1] == '_') && !error) {
216✔
675
         error_at(&yylloc, "a literal may not end with an underscore or "
2✔
676
                  "contain multiple consecutive underscores");
677
         error = true;
2✔
678
      }
679
   }
680
   *p = '\0';
83,744✔
681
}
83,744✔
682

683
static int parse_decimal_literal(const char *str)
83,693✔
684
{
685
   // Transform a string into a literal as specified in LRM 13.4.1
686
   //   decimal_literal ::= integer [.integer] [exponent]
687

688
   int tok = tERROR;
83,693✔
689
   char *tmp LOCAL = xstrdup(str);
83,693✔
690
   strip_underscores(tmp);
83,693✔
691

692
   char *dot = strpbrk(tmp, ".");
83,693✔
693

694
   if (dot == NULL) {
83,693✔
695
      char *sign = strpbrk(tmp, "-");
66,277✔
696
      char *val  = strtok(tmp, "eE");
66,277✔
697
      char *exp  = strtok(NULL, "eE");
66,277✔
698

699
      errno = 0;
66,277✔
700
      yylval.i64 = strtoll(val, NULL, 10);
66,277✔
701
      bool overflow = (errno == ERANGE);
66,277✔
702

703
      long long int e = (exp ? atoll(exp) : 0);
66,277✔
704

705
      if (e >= 0) {  // Minus sign forbidden for an integer literal
12✔
706
         for (; e > 0; e--) {
190,485✔
707
            if (__builtin_mul_overflow(yylval.i64, INT64_C(10), &yylval.i64))
124,208✔
708
               overflow = true;
50✔
709
         }
710
         tok = (sign == NULL) ? tINT : tERROR;
66,277✔
711
      }
712

713
      if (overflow)
66,277✔
714
         error_at(&yylloc, "value %s is outside implementation defined range "
2✔
715
                  "of universal_integer", str);
716
   }
717
   else {
718
      yylval.real = strtod(tmp, NULL);
17,416✔
719
      tok = tREAL;
17,416✔
720
   }
721

722
   TOKEN(tok);
83,693✔
723
}
724

725
static int parse_based_literal(const char *str)
51✔
726
{
727
   // Transform a string into a literal as specified in LRM 13.4.2
728
   //   based_literal ::= base [#:] based_integer [.based_integer] [#:]
729
   //     [exponent]
730

731
   int tok = tERROR;
51✔
732
   char *tmp LOCAL = xstrdup(str);
51✔
733
   strip_underscores(tmp);
51✔
734

735
   char *dot  = strpbrk(tmp, ".");
51✔
736
   char *sign = strpbrk(tmp, "-");
51✔
737
   char *base = strtok(tmp, "#:");
51✔
738
   char *val  = strtok(NULL, "#:");
51✔
739
   char *exp  = strtok(NULL, "eE");
51✔
740

741
   // Base must be at least 2 and at most 16
742
   if ((2 <= atoi(base)) && (atoi(base) <= 16)) {
51✔
743
      if (dot == NULL) {
51✔
744
         char *eptr;
48✔
745
         yylval.i64 = strtoll(val, &eptr, atoi(base));
48✔
746

747
         long long int e = (exp ? atoll(exp) : 0);
48✔
748

749
         if (e >= 0) {  // Minus sign forbidden for an integer literal
1✔
750
            for (; e > 0; e--) yylval.i64 *= atoi(base);
49✔
751
            tok = ((*eptr == '\0') && (sign == NULL)) ? tINT : tERROR;
48✔
752
         }
753
      }
754
      else {
755
         char *eptr_integer, *eptr_rational;
3✔
756
         char *integer  = strtok(val, ".");
3✔
757
         char *rational = strtok(NULL, ".");
3✔
758

759
         yylval.real = (double)strtoll(integer, &eptr_integer, atoi(base));
3✔
760

761
         double tmp = (double)strtoll(rational, &eptr_rational, atoi(base));
3✔
762
         tmp *= pow((double)atoi(base), (double)((long)(0 - strlen(rational))));
3✔
763

764
         yylval.real += tmp;
3✔
765

766
         long long int e = (exp ? atoll(exp) : 0);
3✔
767

768
         if (e != 0)
3✔
769
            yylval.real *= pow((double) atoi(base), (double) e);
3✔
770

771
         if (*eptr_integer == '\0' && *eptr_rational == '\0')
3✔
772
            tok = tREAL;
773
         else
774
            tok = tERROR;
×
775
      }
776
   }
777

778
   TOKEN(tok);
51✔
779
}
780

781
static int parse_string(const char *str)
30,030✔
782
{
783
   // Replaces all double '\"' by single '\"' or all double '%' by
784
   // single '%'.  In the case when '\%' is used as string brackets, the
785
   // enclosed senquence of characters should not contain quotation
786
   // marks!
787

788
   char *s = (yylval.str = xstrdup(str));
30,030✔
789

790
   // Replacing double '\"' character by single '\"' or double '%'
791
   // character by single '%'
792
   // Begins after first character
793
   s++;
30,030✔
794
   char *p = s;
30,030✔
795
   while (*p) {
397,536✔
796
      if ((*p == *(yylval.str)) && (*(p+1) == *(yylval.str))) p++;
367,506✔
797
      *s++ = *p++;
367,506✔
798
   }
799
   *s = *p;
30,030✔
800

801
   TOKEN(tSTRING);
30,030✔
802
}
803

804
static int parse_bit_string(const char *str)
1,902✔
805
{
806
   // Copy input, remove all '_' characters and replace all '\%'
807
   // characters by '\"'.
808

809
   char *copy = (yylval.str = xstrdup(str));
1,902✔
810

811
   bool error = false;
1,902✔
812
   for (char *src = copy, *dst = src; *src != '\0'; src++) {
13,575✔
813
      if (*src == '%')
11,673✔
814
         *dst++ = '\"';
8✔
815
      else if (*src != '_')
11,665✔
816
         *dst++ = *src;
11,572✔
817
      else if ((src[-1] == '\"' || src[1] == '\"') && !error) {
93✔
818
         error_at(&yylloc, "a bit string literal may not start or end with "
2✔
819
                  "an underscore");
820
         error = true;
2✔
821
      }
822
      else if (src[-1] == '_' && !error) {
91✔
823
         error_at(&yylloc, "a bit string literal may not contain multiple "
1✔
824
                  "consecutive underscores");
825
         error = true;
1✔
826
      }
827
   }
828

829
   TOKEN(tBITSTRING);
1,902✔
830
}
831

832
static int report_unterminated_string(const char *str)
3✔
833
{
834
   diag_t *d = diag_new(DIAG_ERROR, &yylloc);
3✔
835
   diag_printf(d, "unterminated string literal");
3✔
836
   diag_hint(d, NULL, "a string literal must fit on one line since it "
3✔
837
             "is a lexical element, longer strings can be formed using "
838
             "concatenation");
839
   diag_lrm(d, STD_08, "15.7");
3✔
840
   diag_emit(d);
3✔
841

842
   return parse_string(str);
3✔
843
}
844

845
static int report_bad_identifier(char *str)
5✔
846
{
847
   diag_t *d = diag_new(DIAG_ERROR, &yylloc);
5✔
848
   diag_printf(d, "a VHDL basic identifier must not start or end with an "
5✔
849
               "underscore, or contain multiple consecutive underscores");
850
   diag_lrm(d, STD_08, "15.4.2");
5✔
851
   diag_emit(d);
5✔
852

853
   return parse_id(str);
5✔
854
}
855

856
static int escape_verilog_string(const char *str)
154✔
857
{
858
   char *s = (yylval.str = xstrdup(str));
154✔
859
   for (char *p = s; *p; p++) {
2,823✔
860
      if (*p == '\\') {
2,669✔
861
         switch (*++p) {
39✔
862
         case 'n': *s++ = '\n'; break;
39✔
863
         case 'r': *s++ = '\r'; break;
×
864
         case 't': *s++ = '\t'; break;
×
865
         case 'b': *s++ = '\b'; break;
×
866
         default:
×
867
            warn_at(&yylloc, "unrecognised escaped character '%c'", *p);
×
868
            *s++ = *p;
×
869
         }
870
      }
871
      else
872
         *s++ = *p;
2,630✔
873
   }
874
   *s = '\0';
154✔
875

876
   return tSTRING;
154✔
877
}
878

879
static void warn_lrm(vhdl_standard_t std, const char *fmt, ...)
2✔
880
{
881
   va_list ap;
2✔
882
   va_start(ap, fmt);
2✔
883

884
   diag_t *d = diag_new(DIAG_WARN, &yylloc);
2✔
885
   diag_vprintf(d, fmt, ap);
2✔
886
   diag_hint(d, NULL, "pass $bold$--std=%s$$ to enable this feature",
2✔
887
             standard_text(std));
888
   diag_emit(d);
2✔
889

890
   va_end(ap);
2✔
891
}
2✔
892

893
static void warn_utf8(const char *text)
1✔
894
{
895
   static bool warned = false;
1✔
896

897
   if (!warned) {
1✔
898
      diag_t *d = diag_new(DIAG_WARN, &yylloc);
1✔
899
      diag_printf(d, "possible multi-byte UTF-8 character found in input");
1✔
900
      diag_hint(d, NULL, "the native encoding of VHDL is ISO-8859-1");
1✔
901
      diag_emit(d);
1✔
902

903
      warned = true;
1✔
904
   }
905
}
1✔
906

907
void reset_scanner(void)
4,011✔
908
{
909
   YY_FLUSH_BUFFER;
4,011✔
910
   BEGIN(INITIAL);
4,011✔
911
}
4,011✔
912

913
void scan_as_psl(void)
308✔
914
{
915
   BEGIN(PSL);
308✔
916
}
308✔
917

918
void scan_as_vhdl(void)
308✔
919
{
920
   BEGIN(INITIAL);
308✔
921
}
308✔
922

923
void scan_as_verilog(void)
121✔
924
{
925
   BEGIN(VLOG);
121✔
926
}
121✔
927

928
bool is_scanned_as_psl(void)
×
929
{
930
   return (YY_START == PSL);
×
931
}
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