forked from github/verilator
Fix parsing "#0 'b0", bug256.
This commit is contained in:
parent
9e76078939
commit
85c5765c00
2
Changes
2
Changes
@ -9,6 +9,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
*** Add parameters into trace files, bug706. [Alex Solomatnikov]
|
||||
|
||||
**** Fix parsing "#0 'b0", bug256.
|
||||
|
||||
**** Fix array bound checks on real variables.
|
||||
|
||||
**** Fix --skip-identical mis-detecting on OS-X, bug707.
|
||||
|
@ -105,6 +105,7 @@ class V3ParseImp {
|
||||
int m_inBeginKwd; // Inside a `begin_keywords
|
||||
int m_lastVerilogState; // Last LEX state in `begin_keywords
|
||||
|
||||
int m_prevLexToken; // previous parsed token (for lexer)
|
||||
bool m_ahead; // aheadToken is valid
|
||||
int m_aheadToken; // Token we read ahead
|
||||
V3ParseBisonYYSType m_aheadVal; // aheadToken's value
|
||||
@ -193,6 +194,7 @@ public:
|
||||
void statePushVlg(); // Parser -> lexer communication
|
||||
void statePop(); // Parser -> lexer communication
|
||||
static int stateVerilogRecent(); // Parser -> lexer communication
|
||||
int prevLexToken() { return m_prevLexToken; } // Parser -> lexer communication
|
||||
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
|
||||
|
||||
//==== Symbol tables
|
||||
@ -208,11 +210,13 @@ public:
|
||||
m_inLibrary = false;
|
||||
m_inBeginKwd = 0;
|
||||
m_lastVerilogState = stateVerilogRecent();
|
||||
m_prevLexToken = 0;
|
||||
m_ahead = false;
|
||||
m_aheadToken = 0;
|
||||
}
|
||||
~V3ParseImp();
|
||||
void parserClear();
|
||||
void unputString(const char* textp, size_t length);
|
||||
|
||||
// METHODS
|
||||
// Preprocess and read the Verilog file specified into the netlist database
|
||||
@ -223,6 +227,7 @@ public:
|
||||
|
||||
private:
|
||||
void lexFile(const string& modname);
|
||||
int yylexReadTok();
|
||||
int lexToken(); // Internal; called from lexToBison
|
||||
};
|
||||
|
||||
|
@ -57,11 +57,26 @@ public:
|
||||
void statePop() {
|
||||
yy_pop_state();
|
||||
}
|
||||
void unputString(const char* textp, size_t length) {
|
||||
// Add characters to input stream in back-to-front order
|
||||
const char* cp = textp;
|
||||
for (cp += length - 1; length--; cp--) {
|
||||
unput(*cp);
|
||||
}
|
||||
}
|
||||
};
|
||||
void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); }
|
||||
void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); }
|
||||
void V3ParseImp::statePop() { parsep()->m_lexerp->statePop(); }
|
||||
int V3ParseImp::yylexThis() { return parsep()->m_lexerp->yylex(); }
|
||||
|
||||
void V3ParseImp::unputString(const char* textp, size_t length) { parsep()->m_lexerp->unputString(textp, length); }
|
||||
|
||||
int V3ParseImp::yylexReadTok() {
|
||||
// Call yylex() remembering last non-whitespace token
|
||||
int token = parsep()->m_lexerp->yylex();
|
||||
m_prevLexToken = token; // Save so can find '#' to parse following number
|
||||
return token;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Read class functions
|
||||
|
@ -43,7 +43,8 @@ extern void yyerrorf(const char* format, ...);
|
||||
//======================================================================
|
||||
|
||||
#define NEXTLINE() {PARSEP->linenoInc();}
|
||||
#define LINECHECK() { const char* cp=yytext; for (int n=yyleng; n; --n) if (cp[n]=='\n') NEXTLINE(); }
|
||||
#define LINECHECKS(textp,len) { const char* cp=textp; for (int n=len; n; --n) if (cp[n]=='\n') NEXTLINE(); }
|
||||
#define LINECHECK() LINECHECKS(yytext,yyleng)
|
||||
#define CRELINE() (PARSEP->copyOrSameFileLine())
|
||||
|
||||
#define FL { yylval.fl = CRELINE(); }
|
||||
@ -149,6 +150,13 @@ id [a-zA-Z_][a-zA-Z0-9_$]*
|
||||
/* escaped identifier */
|
||||
escid \\[^ \t\f\r\n]+
|
||||
word [a-zA-Z0-9_]+
|
||||
/* verilog numbers, constructed to not match the ' that begins a '( or '{ */
|
||||
vnum1 [0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]*
|
||||
vnum2 [0-9]*?['']s?[01xXzZ]
|
||||
vnum3 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+
|
||||
vnum4 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]
|
||||
vnum5 [0-9][_0-9]*[ \t\n]*['']s
|
||||
vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
|
||||
%%
|
||||
|
||||
@ -912,24 +920,21 @@ word [a-zA-Z0-9_]+
|
||||
}
|
||||
\" { yy_push_state(STRING); yymore(); }
|
||||
|
||||
[0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]* {
|
||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
||||
return yaINTNUM;
|
||||
}
|
||||
[0-9]*?['']s?[01xXzZ] { /* SystemVerilog */
|
||||
FL; yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
||||
return yaINTNUM;
|
||||
}
|
||||
/* Note below is constructed to not match the ' that begins a '( or '{ */
|
||||
[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+ {
|
||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
||||
return yaINTNUM;
|
||||
}
|
||||
[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH] {
|
||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
||||
return yaINTNUM;
|
||||
}
|
||||
[0-9][_0-9]*[ \t\n]*['']s {
|
||||
{vnum} {
|
||||
/* "# 1'b0" is a delay value so must lex as "#" "1" "'b0" */
|
||||
if (PARSEP->prevLexToken()=='#') {
|
||||
int shortlen = 0;
|
||||
while (isdigit(yytext[shortlen])) shortlen++;
|
||||
if (shortlen) {
|
||||
// Push rest for later parse
|
||||
PARSEP->unputString(yytext+shortlen, yyleng-shortlen);
|
||||
FL; LINECHECKS(yytext,shortlen);
|
||||
// Return is stuff before '
|
||||
yytext[shortlen] = '\0';
|
||||
yylval.nump = PARSEP->newNumber(yylval.fl, (char*)yytext);
|
||||
return yaINTNUM;
|
||||
}
|
||||
}
|
||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
||||
return yaINTNUM;
|
||||
}
|
||||
@ -1106,8 +1111,8 @@ int V3ParseImp::lexToken() {
|
||||
yylval = m_aheadVal;
|
||||
} else {
|
||||
// Parse new token
|
||||
token = yylexThis();
|
||||
//yylval // Set by yylexThis()
|
||||
token = yylexReadTok();
|
||||
//yylval // Set by yylexReadTok()
|
||||
}
|
||||
// If a paren, read another
|
||||
if (token == yCONST__LEX
|
||||
@ -1116,7 +1121,7 @@ int V3ParseImp::lexToken() {
|
||||
) {
|
||||
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
|
||||
V3ParseBisonYYSType curValue = yylval; // Remember value, as about to read ahead
|
||||
int nexttok = yylexThis();
|
||||
int nexttok = yylexReadTok();
|
||||
m_ahead = true;
|
||||
m_aheadToken = nexttok;
|
||||
m_aheadVal = yylval;
|
||||
|
18
test_regress/t/t_parse_delay.pl
Executable file
18
test_regress/t/t_parse_delay.pl
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
20
test_regress/t/t_parse_delay.v
Normal file
20
test_regress/t/t_parse_delay.v
Normal file
@ -0,0 +1,20 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
reg [6:0] myreg1;
|
||||
|
||||
initial begin
|
||||
myreg1 = # 100 7'd0;
|
||||
myreg1 = # 100 'b0; // [#] [100] ['b0]
|
||||
myreg1 = #100'b0; // [#] [100] ['b0]
|
||||
myreg1 = 100'b0;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user