yosys/frontends/verilog/verilog_lexer.l

606 lines
18 KiB
Plaintext
Raw Normal View History

2013-01-05 04:13:26 -06:00
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
2015-07-02 04:14:30 -05:00
*
2013-01-05 04:13:26 -06:00
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
2015-07-02 04:14:30 -05:00
*
2013-01-05 04:13:26 -06:00
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ---
*
* The Verilog frontend.
*
* This frontend is using the AST frontend library (see frontends/ast/).
* Thus this frontend does not generate RTLIL code directly but creates an
* AST directly from the Verilog parse tree and then passes this AST to
* the AST frontend library.
*
* ---
*
* A simple lexer for Verilog code. Non-preprocessor compiler directives are
* handled here. The preprocessor stuff is handled in preproc.cc. Everything
* else is left to the bison parser (see verilog_parser.y).
2013-01-05 04:13:26 -06:00
*
*/
%{
#ifdef __clang__
// bison generates code using the 'register' storage class specifier
#pragma clang diagnostic ignored "-Wdeprecated-register"
// flex generates weirdly-indented code
#pragma clang diagnostic ignored "-Wmisleading-indentation"
#endif
2013-01-05 04:13:26 -06:00
#include "kernel/log.h"
#include "frontends/verilog/verilog_frontend.h"
2013-01-05 04:13:26 -06:00
#include "frontends/ast/ast.h"
#include "verilog_parser.tab.hh"
2013-01-05 04:13:26 -06:00
USING_YOSYS_NAMESPACE
2013-01-05 04:13:26 -06:00
using namespace AST;
using namespace VERILOG_FRONTEND;
#define YYSTYPE FRONTEND_VERILOG_YYSTYPE
#define YYLTYPE FRONTEND_VERILOG_YYLTYPE
YOSYS_NAMESPACE_BEGIN
2013-01-05 04:13:26 -06:00
namespace VERILOG_FRONTEND {
std::vector<std::string> fn_stack;
std::vector<int> ln_stack;
YYLTYPE real_location;
YYLTYPE old_location;
2013-01-05 04:13:26 -06:00
}
YOSYS_NAMESPACE_END
2013-01-05 04:13:26 -06:00
#define SV_KEYWORD(_tok) \
if (sv_mode) return _tok; \
log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\
"recognized unless read_verilog is called with -sv!\n", yytext, \
AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); \
yylval->string = new std::string(std::string("\\") + yytext); \
return TOK_ID;
#define NON_KEYWORD() \
yylval->string = new std::string(std::string("\\") + yytext); \
return TOK_ID;
#define YY_INPUT(buf,result,max_size) \
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
#define YY_USER_ACTION \
old_location = real_location; \
real_location.first_line = real_location.last_line; \
real_location.first_column = real_location.last_column; \
for(int i = 0; yytext[i] != '\0'; ++i){ \
if(yytext[i] == '\n') { \
real_location.last_line++; \
real_location.last_column = 1; \
} \
else { \
real_location.last_column++; \
} \
} \
(*yylloc) = real_location;
#define YY_BREAK \
(*yylloc) = old_location; \
break;
#undef YY_BUF_SIZE
#define YY_BUF_SIZE 65536
extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param);
static bool isUserType(std::string &s)
{
// check current scope then outer scopes for a name
for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) {
if (it->count(s) > 0) {
return true;
}
}
return false;
}
2013-01-05 04:13:26 -06:00
%}
%option yylineno
%option noyywrap
%option nounput
%option bison-locations
%option bison-bridge
2013-01-05 04:13:26 -06:00
%option prefix="frontend_verilog_yy"
%x COMMENT
%x STRING
%x SYNOPSYS_TRANSLATE_OFF
%x SYNOPSYS_FLAGS
%x IMPORT_DPI
%x BASED_CONST
2013-01-05 04:13:26 -06:00
UNSIGNED_NUMBER [0-9][0-9_]*
FIXED_POINT_NUMBER_DEC [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)?
FIXED_POINT_NUMBER_NO_DEC [0-9][0-9_]*[eE][-+]?[0-9_]+
TIME_SCALE_SUFFIX [munpf]?s
2013-01-05 04:13:26 -06:00
%%
// Initialise comment_caller to something to avoid a "maybe undefined"
// warning from GCC.
int comment_caller = INITIAL;
2013-01-05 04:13:26 -06:00
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* {
2013-01-05 04:13:26 -06:00
fn_stack.push_back(current_filename);
ln_stack.push_back(frontend_verilog_yyget_lineno());
current_filename = yytext+11;
if (!current_filename.empty() && current_filename.front() == '"')
current_filename = current_filename.substr(1);
if (!current_filename.empty() && current_filename.back() == '"')
current_filename = current_filename.substr(0, current_filename.size()-1);
2013-01-05 04:13:26 -06:00
frontend_verilog_yyset_lineno(0);
yylloc->first_line = yylloc->last_line = 0;
real_location.first_line = real_location.last_line = 0;
2013-01-05 04:13:26 -06:00
}
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_pop"[^\n]*\n {
2013-01-05 04:13:26 -06:00
current_filename = fn_stack.back();
fn_stack.pop_back();
2013-01-05 04:13:26 -06:00
frontend_verilog_yyset_lineno(ln_stack.back());
yylloc->first_line = yylloc->last_line = ln_stack.back();
real_location.first_line = real_location.last_line = ln_stack.back();
ln_stack.pop_back();
2013-01-05 04:13:26 -06:00
}
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`line"[ \t]+[^ \t\r\n]+[ \t]+\"[^ \r\n]+\"[^\r\n]*\n {
char *p = yytext + 5;
while (*p == ' ' || *p == '\t') p++;
frontend_verilog_yyset_lineno(atoi(p));
yylloc->first_line = yylloc->last_line = atoi(p);
real_location.first_line = real_location.last_line = atoi(p);
while (*p && *p != ' ' && *p != '\t') p++;
while (*p == ' ' || *p == '\t') p++;
char *q = *p ? p + 1 : p;
while (*q && *q != '"') q++;
current_filename = std::string(p).substr(1, q-p-1);
}
2013-01-05 04:13:26 -06:00
"`file_notfound "[^\n]* {
log_error("Can't open include file `%s'!\n", yytext + 15);
}
"`timescale"[ \t]+[^ \t\r\n/]+[ \t]*"/"[ \t]*[^ \t\r\n]* /* ignore timescale directive */
"`celldefine"[^\n]* /* ignore `celldefine */
"`endcelldefine"[^\n]* /* ignore `endcelldefine */
"`default_nettype"[ \t]+[^ \t\r\n/]+ {
char *p = yytext;
while (*p != 0 && *p != ' ' && *p != '\t') p++;
while (*p == ' ' || *p == '\t') p++;
if (!strcmp(p, "none"))
VERILOG_FRONTEND::default_nettype_wire = false;
else if (!strcmp(p, "wire"))
VERILOG_FRONTEND::default_nettype_wire = true;
else
frontend_verilog_yyerror("Unsupported default nettype: %s", p);
}
2018-10-16 08:33:37 -05:00
"`protect"[^\n]* /* ignore `protect*/
"`endprotect"[^\n]* /* ignore `endprotect*/
2013-01-05 04:13:26 -06:00
"`"[a-zA-Z_$][a-zA-Z0-9_$]* {
frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext);
}
"module" { return TOK_MODULE; }
"endmodule" { return TOK_ENDMODULE; }
"function" { return TOK_FUNCTION; }
"endfunction" { return TOK_ENDFUNCTION; }
"task" { return TOK_TASK; }
"endtask" { return TOK_ENDTASK; }
"specify" { return specify_mode ? TOK_SPECIFY : TOK_IGNORED_SPECIFY; }
"endspecify" { return TOK_ENDSPECIFY; }
"specparam" { return TOK_SPECPARAM; }
"package" { SV_KEYWORD(TOK_PACKAGE); }
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
"interface" { SV_KEYWORD(TOK_INTERFACE); }
"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); }
"modport" { SV_KEYWORD(TOK_MODPORT); }
2013-01-05 04:13:26 -06:00
"parameter" { return TOK_PARAMETER; }
"localparam" { return TOK_LOCALPARAM; }
"defparam" { return TOK_DEFPARAM; }
2013-01-05 04:13:26 -06:00
"assign" { return TOK_ASSIGN; }
"always" { return TOK_ALWAYS; }
"initial" { return TOK_INITIAL; }
"begin" { return TOK_BEGIN; }
"end" { return TOK_END; }
"if" { return TOK_IF; }
"else" { return TOK_ELSE; }
"for" { return TOK_FOR; }
"posedge" { return TOK_POSEDGE; }
"negedge" { return TOK_NEGEDGE; }
"or" { return TOK_OR; }
"case" { return TOK_CASE; }
"casex" { return TOK_CASEX; }
"casez" { return TOK_CASEZ; }
"endcase" { return TOK_ENDCASE; }
"default" { return TOK_DEFAULT; }
"generate" { return TOK_GENERATE; }
"endgenerate" { return TOK_ENDGENERATE; }
"while" { return TOK_WHILE; }
"repeat" { return TOK_REPEAT; }
"automatic" { return TOK_AUTOMATIC; }
2013-01-05 04:13:26 -06:00
"unique" { SV_KEYWORD(TOK_UNIQUE); }
"unique0" { SV_KEYWORD(TOK_UNIQUE0); }
"priority" { SV_KEYWORD(TOK_PRIORITY); }
"always_comb" { SV_KEYWORD(TOK_ALWAYS_COMB); }
"always_ff" { SV_KEYWORD(TOK_ALWAYS_FF); }
"always_latch" { SV_KEYWORD(TOK_ALWAYS_LATCH); }
/* use special token for labels on assert, assume, cover, and restrict because it's insanley complex
to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
global state.. its a mess) */
[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
if (!strcmp(yytext, "default"))
return TOK_DEFAULT;
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_SVA_LABEL;
}
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); }
"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); }
Add support for parsing the SystemVerilog 'bind' construct This doesn't do anything useful yet: the patch just adds support for the syntax to the lexer and parser and adds some tests to check the syntax parses properly. This generates AST nodes, but doesn't yet generate RTLIL. Since our existing hierarchical_identifier parser doesn't allow bit selects (so you can't do something like foo[1].bar[2].baz), I've also not added support for a trailing bit select (the "constant_bit_select" non-terminal in "bind_target_instance" in the spec). If we turn out to need this in future, we'll want to augment hierarchical_identifier and its other users too. Note that you can't easily use the BNF from the spec: bind_directive ::= "bind" bind_target_scope [ : bind_target_instance_list] bind_instantiation ; | "bind" bind_target_instance bind_instantiation ; even if you fix the lookahead problem, because code like this matches both branches in the BNF: bind a b b_i (.*); The problem is that 'a' could either be a module name or a degenerate hierarchical reference. This seems to be a genuine syntactic ambiguity, which the spec resolves (p739) by saying that we have to wait until resolution time (the hierarchy pass) and take whatever is defined, treating 'a' as an instance name if it names both an instance and a module. To keep the parser simple, it currently accepts this invalid syntax: bind a.b : c d e (.*); This is invalid because we're in the first branch of the BNF above, so the "a.b" term should match bind_target_scope: a module or interface identifier, not an arbitrary hierarchical identifier. This will fail in the hierarchy pass (when it's implemented in a future patch).
2020-05-21 11:36:29 -05:00
"bind" { if (formal_mode) return TOK_BIND; SV_KEYWORD(TOK_BIND); }
"final" { SV_KEYWORD(TOK_FINAL); }
"logic" { SV_KEYWORD(TOK_LOGIC); }
"var" { SV_KEYWORD(TOK_VAR); }
2020-05-08 08:40:49 -05:00
"bit" { SV_KEYWORD(TOK_LOGIC); }
"int" { SV_KEYWORD(TOK_INT); }
"byte" { SV_KEYWORD(TOK_BYTE); }
"shortint" { SV_KEYWORD(TOK_SHORTINT); }
"longint" { SV_KEYWORD(TOK_LONGINT); }
"void" { SV_KEYWORD(TOK_VOID); }
"eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
"s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
2013-01-05 04:13:26 -06:00
"input" { return TOK_INPUT; }
"output" { return TOK_OUTPUT; }
"inout" { return TOK_INOUT; }
"wire" { return TOK_WIRE; }
"tri" { return TOK_WIRE; }
"wor" { return TOK_WOR; }
"trior" { return TOK_WOR; }
"wand" { return TOK_WAND; }
"triand" { return TOK_WAND; }
2013-01-05 04:13:26 -06:00
"reg" { return TOK_REG; }
"integer" { return TOK_INTEGER; }
"signed" { return TOK_SIGNED; }
2020-05-08 08:40:49 -05:00
"unsigned" { SV_KEYWORD(TOK_UNSIGNED); }
2013-01-05 04:13:26 -06:00
"genvar" { return TOK_GENVAR; }
"real" { return TOK_REAL; }
2013-01-05 04:13:26 -06:00
2017-01-17 10:33:52 -06:00
"enum" { SV_KEYWORD(TOK_ENUM); }
"typedef" { SV_KEYWORD(TOK_TYPEDEF); }
"struct" { SV_KEYWORD(TOK_STRUCT); }
"union" { SV_KEYWORD(TOK_UNION); }
"packed" { SV_KEYWORD(TOK_PACKED); }
2017-01-17 10:33:52 -06:00
{UNSIGNED_NUMBER} {
yylval->string = new std::string(yytext);
2017-02-08 07:38:15 -06:00
return TOK_CONSTVAL;
2013-01-05 04:13:26 -06:00
}
\'[01zxZX] {
yylval->string = new std::string(yytext);
return TOK_UNBASED_UNSIZED_CONSTVAL;
}
\'[sS]?[bodhBODH] {
BEGIN(BASED_CONST);
yylval->string = new std::string(yytext);
return TOK_BASE;
}
<BASED_CONST>[0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* {
BEGIN(0);
yylval->string = new std::string(yytext);
return TOK_BASED_CONSTVAL;
2013-01-05 04:13:26 -06:00
}
{FIXED_POINT_NUMBER_DEC} {
yylval->string = new std::string(yytext);
return TOK_REALVAL;
}
{FIXED_POINT_NUMBER_NO_DEC} {
yylval->string = new std::string(yytext);
return TOK_REALVAL;
}
2013-01-05 04:13:26 -06:00
\" { BEGIN(STRING); }
<STRING>\\. { yymore(); real_location = old_location; }
2013-01-05 04:13:26 -06:00
<STRING>\" {
BEGIN(0);
char *yystr = strdup(yytext);
yystr[strlen(yytext) - 1] = 0;
int i = 0, j = 0;
while (yystr[i]) {
if (yystr[i] == '\\' && yystr[i + 1]) {
i++;
2018-05-03 05:35:01 -05:00
if (yystr[i] == 'a')
yystr[i] = '\a';
else if (yystr[i] == 'f')
yystr[i] = '\f';
else if (yystr[i] == 'n')
2013-01-05 04:13:26 -06:00
yystr[i] = '\n';
2018-05-03 05:35:01 -05:00
else if (yystr[i] == 'r')
yystr[i] = '\r';
2013-01-05 04:13:26 -06:00
else if (yystr[i] == 't')
yystr[i] = '\t';
2018-05-03 05:35:01 -05:00
else if (yystr[i] == 'v')
yystr[i] = '\v';
2013-01-05 04:13:26 -06:00
else if ('0' <= yystr[i] && yystr[i] <= '7') {
yystr[i] = yystr[i] - '0';
if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0';
i++;
}
if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0';
i++;
}
}
}
yystr[j++] = yystr[i++];
}
yystr[j] = 0;
yylval->string = new std::string(yystr, j);
2013-01-05 04:13:26 -06:00
free(yystr);
return TOK_STRING;
}
<STRING>. { yymore(); real_location = old_location; }
2013-01-05 04:13:26 -06:00
and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
yylval->string = new std::string(yytext);
2013-01-05 04:13:26 -06:00
return TOK_PRIMITIVE;
}
supply0 { return TOK_SUPPLY0; }
supply1 { return TOK_SUPPLY1; }
2023-06-27 20:51:20 -05:00
"$"(display[bho]?|write[bho]?|strobe|monitor|time|realtime|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
yylval->string = new std::string(yytext);
2013-01-05 04:13:26 -06:00
return TOK_ID;
}
"$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) {
if (!specify_mode) REJECT;
yylval->string = new std::string(yytext);
return TOK_ID;
}
"$"(info|warning|error|fatal) {
yylval->string = new std::string(yytext);
return TOK_MSG_TASKS;
}
2013-01-05 04:13:26 -06:00
"$signed" { return TOK_TO_SIGNED; }
"$unsigned" { return TOK_TO_UNSIGNED; }
2020-02-27 10:57:35 -06:00
[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* {
// package qualifier
auto s = std::string("\\") + yytext;
if (pkg_user_types.count(s) > 0) {
// package qualified typedefed name
2020-02-27 10:57:35 -06:00
yylval->string = new std::string(s);
return TOK_PKG_USER_TYPE;
2020-02-27 10:57:35 -06:00
}
else {
// backup before :: just return first part
size_t len = strchr(yytext, ':') - yytext;
yyless(len);
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
}
}
[a-zA-Z_$][a-zA-Z0-9_$]* {
2020-02-27 10:57:35 -06:00
auto s = std::string("\\") + yytext;
if (isUserType(s)) {
// previously typedefed name
2020-02-27 10:57:35 -06:00
yylval->string = new std::string(s);
return TOK_USER_TYPE;
}
else {
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
}
2013-01-05 04:13:26 -06:00
}
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
}
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
2014-12-26 20:40:27 -06:00
static bool printed_warning = false;
if (!printed_warning) {
2021-03-29 10:03:46 -05:00
log_warning(
"Encountered `translate_off' comment! Such legacy hot "
"comments are supported by Yosys, but are not part of "
"any formal language specification. Using a portable "
"and standards-compliant construct such as `ifdef is "
"recommended!\n"
);
2014-12-26 20:40:27 -06:00
printed_warning = true;
}
2013-01-05 04:13:26 -06:00
BEGIN(SYNOPSYS_TRANSLATE_OFF);
}
<SYNOPSYS_TRANSLATE_OFF>. /* ignore synopsys translate_off body */
<SYNOPSYS_TRANSLATE_OFF>\n /* ignore synopsys translate_off body */
<SYNOPSYS_TRANSLATE_OFF>"/*"[ \t]*(synopsys|synthesis)[ \t]*"translate_on"[ \t]*"*/" { BEGIN(0); }
2013-01-05 04:13:26 -06:00
"/*"[ \t]*(synopsys|synthesis)[ \t]+ {
2013-01-05 04:13:26 -06:00
BEGIN(SYNOPSYS_FLAGS);
}
<SYNOPSYS_FLAGS>full_case {
2014-12-26 20:40:27 -06:00
static bool printed_warning = false;
if (!printed_warning) {
2021-03-29 10:03:46 -05:00
log_warning(
"Encountered `full_case' comment! Such legacy hot "
"comments are supported by Yosys, but are not part of "
"any formal language specification. Using the Verilog "
"`full_case' attribute or the SystemVerilog `unique' "
"or `unique0' keywords is recommended!\n"
);
2014-12-26 20:40:27 -06:00
printed_warning = true;
}
2013-01-05 04:13:26 -06:00
return TOK_SYNOPSYS_FULL_CASE;
}
<SYNOPSYS_FLAGS>parallel_case {
2014-12-26 20:40:27 -06:00
static bool printed_warning = false;
if (!printed_warning) {
2021-03-29 10:03:46 -05:00
log_warning(
"Encountered `parallel_case' comment! Such legacy hot "
"comments are supported by Yosys, but are not part of "
"any formal language specification. Using the Verilog "
"`parallel_case' attribute or the SystemVerilog "
"`unique' or `priority' keywords is recommended!\n"
);
2014-12-26 20:40:27 -06:00
printed_warning = true;
}
2013-01-05 04:13:26 -06:00
return TOK_SYNOPSYS_PARALLEL_CASE;
}
<SYNOPSYS_FLAGS>. /* ignore everything else */
<SYNOPSYS_FLAGS>"*/" { BEGIN(0); }
import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
BEGIN(IMPORT_DPI);
return TOK_DPI_FUNCTION;
}
<IMPORT_DPI>[a-zA-Z_$][a-zA-Z0-9_$]* {
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
}
<IMPORT_DPI>[ \t\r\n] /* ignore whitespaces */
<IMPORT_DPI>";" {
BEGIN(0);
return *yytext;
}
<IMPORT_DPI>. {
return *yytext;
}
2013-01-05 04:13:26 -06:00
"\\"[^ \t\r\n]+ {
yylval->string = new std::string(yytext);
2013-01-05 04:13:26 -06:00
return TOK_ID;
}
"(*" { return ATTR_BEGIN; }
"*)" { return ATTR_END; }
"{*" { return DEFATTR_BEGIN; }
"*}" { return DEFATTR_END; }
2013-01-05 04:13:26 -06:00
"**" { return OP_POW; }
"||" { return OP_LOR; }
"&&" { return OP_LAND; }
"==" { return OP_EQ; }
"!=" { return OP_NE; }
"<=" { return OP_LE; }
">=" { return OP_GE; }
"===" { return OP_EQX; }
"!==" { return OP_NEX; }
2013-05-07 07:35:40 -05:00
"~&" { return OP_NAND; }
"~|" { return OP_NOR; }
2013-01-05 04:13:26 -06:00
"~^" { return OP_XNOR; }
"^~" { return OP_XNOR; }
"<<" { return OP_SHL; }
">>" { return OP_SHR; }
"<<<" { return OP_SSHL; }
">>>" { return OP_SSHR; }
"'" { return OP_CAST; }
"::" { return TOK_PACKAGESEP; }
"++" { return TOK_INCREMENT; }
"--" { return TOK_DECREMENT; }
2013-11-20 06:05:27 -06:00
"+:" { return TOK_POS_INDEXED; }
"-:" { return TOK_NEG_INDEXED; }
".*" { return TOK_WILDCARD_CONNECT; }
"|=" { SV_KEYWORD(TOK_BIT_OR_ASSIGN); }
"&=" { SV_KEYWORD(TOK_BIT_AND_ASSIGN); }
"+=" { SV_KEYWORD(TOK_ADD_ASSIGN); }
"-=" { SV_KEYWORD(TOK_SUB_ASSIGN); }
"^=" { SV_KEYWORD(TOK_BIT_XOR_ASSIGN); }
"/=" { SV_KEYWORD(TOK_DIV_ASSIGN); }
"%=" { SV_KEYWORD(TOK_MOD_ASSIGN); }
"*=" { SV_KEYWORD(TOK_MUL_ASSIGN); }
"<<=" { SV_KEYWORD(TOK_SHL_ASSIGN); }
">>=" { SV_KEYWORD(TOK_SHR_ASSIGN); }
"<<<=" { SV_KEYWORD(TOK_SSHL_ASSIGN); }
">>>=" { SV_KEYWORD(TOK_SSHR_ASSIGN); }
[-+]?[=*]> {
if (!specify_mode) REJECT;
yylval->string = new std::string(yytext);
return TOK_SPECIFY_OPER;
}
"&&&" {
if (!specify_mode) return TOK_IGNORED_SPECIFY_AND;
return TOK_SPECIFY_AND;
}
{UNSIGNED_NUMBER}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
{FIXED_POINT_NUMBER_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
{FIXED_POINT_NUMBER_NO_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
<INITIAL,BASED_CONST>"/*" { comment_caller=YY_START; BEGIN(COMMENT); }
2013-01-05 04:13:26 -06:00
<COMMENT>. /* ignore comment body */
<COMMENT>\n /* ignore comment body */
<COMMENT>"*/" { BEGIN(comment_caller); }
2013-01-05 04:13:26 -06:00
<INITIAL,BASED_CONST>[ \t\r\n] /* ignore whitespaces */
<INITIAL,BASED_CONST>\\[\r\n] /* ignore continuation sequence */
<INITIAL,BASED_CONST>"//"[^\r\n]* /* ignore one-line comments */
2014-11-24 07:48:07 -06:00
<INITIAL>. { return *yytext; }
<*>. { BEGIN(0); return *yytext; }
2013-01-05 04:13:26 -06:00
%%
// this is a hack to avoid the 'yyinput defined but not used' error msgs
void *frontend_verilog_avoid_input_warnings() {
return (void*)&yyinput;
}