Skip to content

Commit 869b9ea

Browse files
committed
class interface for flex
This adds an abstract class that serves as interface for flex-generated tokenizers.
1 parent d0c223d commit 869b9ea

6 files changed

Lines changed: 124 additions & 48 deletions

src/verilog/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
SRC = aval_bval_encoding.cpp \
22
convert_literals.cpp \
33
expr2verilog.cpp \
4+
flex_interface.cpp \
45
sva_expr.cpp \
56
typename.cpp \
67
verilog_bits.cpp \

src/verilog/flex_interface.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*******************************************************************\
2+
3+
Module: Flex Interface
4+
5+
Author: Daniel Kroening, kroening@kroening.com
6+
7+
\*******************************************************************/
8+
9+
#include "flex_interface.h"
10+
11+
#include <util/invariant.h>
12+
13+
#include <istream>
14+
15+
std::size_t flex_interfacet::yy_input(char *buffer, std::size_t max_size)
16+
{
17+
PRECONDITION(in != nullptr);
18+
19+
std::size_t result = 0;
20+
while(result < max_size)
21+
{
22+
char ch;
23+
if(!in->get(ch))
24+
break; // eof
25+
buffer[result++] = ch;
26+
if(ch == '\n')
27+
{
28+
// We need to abort prematurely to enable
29+
// switching input streams, e.g., for include files.
30+
break;
31+
}
32+
}
33+
return result;
34+
}

src/verilog/flex_interface.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*******************************************************************\
2+
3+
Module: Flex Interface
4+
5+
Author: Daniel Kroening, dkr@amazon.com
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_FLEX_INTERFACE_H
10+
#define CPROVER_FLEX_INTERFACE_H
11+
12+
#include <cstddef>
13+
#include <iosfwd>
14+
#include <utility>
15+
16+
// This is a C++ interface for a flex-generated tokenizer.
17+
// Defining our own avoids the issue with the different versions
18+
// of the FlexLexer.h, which needs to match the version of the
19+
// flex binary.
20+
21+
class flex_interfacet
22+
{
23+
public:
24+
virtual ~flex_interfacet()
25+
{
26+
destroy();
27+
}
28+
29+
// the return type is hard-wired by flex
30+
virtual int lex() = 0;
31+
32+
// for calling yylex_init
33+
virtual void init()
34+
{
35+
}
36+
37+
// for calling yylex_destroy
38+
virtual void destroy()
39+
{
40+
}
41+
42+
// to be called by the YY_INPUT macro, as follows
43+
// #define YY_INPUT(buf, result, max_size)
44+
// { result = flex_interface.yy_input(buf, max_size); }
45+
std::size_t yy_input(char *buffer, std::size_t max_size);
46+
47+
// yytext and yyleng
48+
using text_and_lengt = std::pair<char *, std::size_t>;
49+
virtual text_and_lengt text_and_leng() = 0;
50+
51+
std::istream *in = nullptr;
52+
};
53+
54+
#endif // CPROVER_FLEX_INTERFACE_H

src/verilog/verilog_preprocessor_tokenizer.cpp

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -81,38 +81,20 @@ auto verilog_preprocessor_token_sourcet::next_token() -> const tokent &
8181

8282
verilog_preprocessor_tokenizert::verilog_preprocessor_tokenizert(
8383
std::istream &_in)
84-
: in(_in)
8584
{
85+
flex.in = &_in;
86+
flex.init();
8687
}
8788

88-
std::size_t
89-
verilog_preprocessor_tokenizert::yy_input(char *buffer, std::size_t max_size)
90-
{
91-
std::size_t result = 0;
92-
while(result < max_size)
93-
{
94-
char ch;
95-
if(!in.get(ch))
96-
break; // eof
97-
buffer[result++] = ch;
98-
if(ch == '\n')
99-
{
100-
// We need to abort prematurely to enable
101-
// switching input streams on `include.
102-
break;
103-
}
104-
}
105-
return result;
106-
}
107-
108-
int yyverilog_preprocessorlex();
109-
verilog_preprocessor_tokenizert *verilog_preprocessor_tokenizer;
89+
verilog_preprocessor_tokenizert::flext *verilog_preprocessor_flex;
11090

11191
void verilog_preprocessor_tokenizert::get_token_from_stream()
11292
{
113-
verilog_preprocessor_tokenizer = this;
114-
token.kind = static_cast<verilog_preprocessor_tokenizert::tokent::kindt>(
115-
yyverilog_preprocessorlex());
93+
verilog_preprocessor_flex = &flex;
94+
token.kind =
95+
static_cast<verilog_preprocessor_tokenizert::tokent::kindt>(flex.lex());
96+
auto [text, leng] = flex.text_and_leng();
97+
token.text = std::string(text, leng);
11698
}
11799

118100
std::vector<verilog_preprocessor_token_sourcet::tokent>

src/verilog/verilog_preprocessor_tokenizer.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, kroening@kroening.com
99
#ifndef VERILOG_PREPROCESSOR_TOKENIZER_H
1010
#define VERILOG_PREPROCESSOR_TOKENIZER_H
1111

12+
#include "flex_interface.h"
1213
#include "verilog_preprocessor_error.h"
1314

1415
#include <vector>
@@ -88,22 +89,17 @@ class verilog_preprocessor_tokenizert
8889
: public verilog_preprocessor_token_sourcet
8990
{
9091
public:
91-
explicit verilog_preprocessor_tokenizert(std::istream &_in);
92+
explicit verilog_preprocessor_tokenizert(std::istream &);
9293

93-
// for flex
94-
std::size_t yy_input(char *buffer, std::size_t max_size);
95-
void text(const char *buffer, std::size_t len)
94+
class flext : public flex_interfacet
9695
{
97-
token.text = std::string(buffer, len);
98-
}
99-
100-
void text(char ch)
101-
{
102-
token.text = std::string(1, ch);
103-
}
96+
public:
97+
int lex() override;
98+
void init() override;
99+
text_and_lengt text_and_leng() override;
100+
} flex;
104101

105102
protected:
106-
std::istream &in;
107103
void get_token_from_stream() override;
108104
};
109105

src/verilog/verilog_preprocessor_tokenizer.l

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@ static int isatty(int) { return 0; }
1313

1414
#include "verilog_preprocessor_tokenizer.h"
1515

16-
extern verilog_preprocessor_tokenizert *verilog_preprocessor_tokenizer;
16+
extern flex_interfacet *verilog_preprocessor_flex;
1717
using tokent = verilog_preprocessor_tokenizert::tokent;
1818

19-
#define TOKENIZER (*verilog_preprocessor_tokenizer)
20-
2119
#define YY_INPUT(buf, result, max_size) \
22-
{ result = TOKENIZER.yy_input(buf, max_size); }
20+
{ result = verilog_preprocessor_flex->yy_input(buf, max_size); }
2321
%}
2422

2523
%s SLCOMMENT
@@ -33,13 +31,13 @@ String \"(\\.|[^"\\])*\"
3331

3432
<INITIAL>"//" { BEGIN SLCOMMENT; /* single-line comment */ }
3533
<INITIAL>"/*" { BEGIN MLCOMMENT; /* multi-line comment */ }
36-
<INITIAL>{String} { TOKENIZER.text(yytext, yyleng); return tokent::STRING_LITERAL; }
37-
<INITIAL>{Identifier} { TOKENIZER.text(yytext, yyleng); return tokent::IDENTIFIER; }
38-
<INITIAL>.|\n { TOKENIZER.text(yytext[0]); return yytext[0]; /* anything else */ }
39-
<SLCOMMENT>\n { BEGIN INITIAL; TOKENIZER.text('\n'); return '\n'; }
34+
<INITIAL>{String} { return tokent::STRING_LITERAL; }
35+
<INITIAL>{Identifier} { return tokent::IDENTIFIER; }
36+
<INITIAL>.|\n { return yytext[0]; /* anything else */ }
37+
<SLCOMMENT>\n { BEGIN INITIAL; return '\n'; }
4038
<SLCOMMENT>. { /* just eat up */ }
4139
<SLCOMMENT><<EOF>> { /* we allow that */ BEGIN INITIAL; }
42-
<MLCOMMENT>\n { TOKENIZER.text('\n'); return '\n'; }
40+
<MLCOMMENT>\n { return '\n'; }
4341
<MLCOMMENT>"*/" { BEGIN INITIAL; /* comment done */ }
4442
<MLCOMMENT>. { /* just eat up */ }
4543
<MLCOMMENT><<EOF>> { throw verilog_preprocessor_errort() << "EOF inside a comment"; }
@@ -48,8 +46,19 @@ String \"(\\.|[^"\\])*\"
4846

4947
int yywrap() { return 1; }
5048

51-
void verilog_preprocessor_tokenizer_init()
49+
void verilog_preprocessor_tokenizert::flext::init()
5250
{
5351
YY_FLUSH_BUFFER;
5452
BEGIN INITIAL;
5553
}
54+
55+
int verilog_preprocessor_tokenizert::flext::lex()
56+
{
57+
return yylex();
58+
}
59+
60+
flex_interfacet::text_and_lengt
61+
verilog_preprocessor_tokenizert::flext::text_and_leng()
62+
{
63+
return {yytext, yyleng};
64+
}

0 commit comments

Comments
 (0)