Improve error to note common :: package errors

This commit is contained in:
Wilson Snyder 2017-09-18 22:54:54 -04:00
parent 3862f2f022
commit b3cf5c4f5f
4 changed files with 66 additions and 13 deletions

View File

@ -42,11 +42,13 @@ typedef enum { uniq_NONE, uniq_UNIQUE, uniq_UNIQUE0, uniq_PRIORITY } V3UniqState
typedef enum { iprop_NONE, iprop_CONTEXT, iprop_PURE } V3ImportProperty;
//============================================================================
// Parser YYSType, e.g. for parser's yylval
// We can't use bison's %union as we want to pass the fileline with all tokens
struct V3ParseBisonYYSType {
FileLine* fl;
AstNode* scp; // Symbol table scope for future lookups
int token; // Read token, aka tok
union {
V3Number* nump;
string* strp;
@ -107,9 +109,10 @@ class V3ParseImp {
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
bool m_ahead; // aheadval is valid
V3ParseBisonYYSType m_aheadVal; // ahead token value
V3ParseBisonYYSType m_curBisonVal; // current token for error reporting
V3ParseBisonYYSType m_prevBisonVal; // previous token for error reporting
deque<string*> m_stringps; // Created strings for later cleanup
deque<V3Number*> m_numberps; // Created numbers for later cleanup
@ -194,6 +197,8 @@ public:
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); }
const V3ParseBisonYYSType curBisonVal() const { return m_curBisonVal; }
const V3ParseBisonYYSType prevBisonVal() const { return m_prevBisonVal; }
//==== Symbol tables
V3ParseSym* symp() { return m_symp; }
@ -210,7 +215,8 @@ public:
m_lastVerilogState = stateVerilogRecent();
m_prevLexToken = 0;
m_ahead = false;
m_aheadToken = 0;
m_curBisonVal.token = 0;
m_prevBisonVal.token = 0;
// m_aheadVal not used as m_ahead = false
}
~V3ParseImp();
@ -227,7 +233,7 @@ public:
private:
void lexFile(const string& modname);
int yylexReadTok();
int lexToken(); // Internal; called from lexToBison
void lexToken(); // Internal; called from lexToBison
};
#endif // Guard

View File

@ -109,6 +109,14 @@ void V3ParseImp::verilatorCmtBad(const char* textp) {
void yyerror(const char* errmsg) {
PARSEP->fileline()->v3error(errmsg);
static const char* colonmsg = "syntax error, unexpected ::, ";
//tokens;
if (0==strncmp(errmsg, colonmsg, strlen(colonmsg))
&& PARSEP->prevBisonVal().token == yaID__ETC
&& PARSEP->curBisonVal().token == yP_COLONCOLON) {
PARSEP->fileline()->v3error("Perhaps '"+*PARSEP->prevBisonVal().strp
+"' is a package which needs to be predeclared? (IEEE 2012 26.3)");
}
}
void yyerrorf(const char* format, ...) {
@ -994,14 +1002,14 @@ double V3ParseImp::parseDouble(const char* textp, size_t length, bool* successp)
return d;
}
int V3ParseImp::lexToken() {
void V3ParseImp::lexToken() {
// called from lexToBison, has a "this"
// Fetch next token from prefetch or real lexer
int token;
if (m_ahead) {
// We prefetched an extra token, give it back
m_ahead = false;
token = m_aheadToken;
token = m_aheadVal.token;
yylval = m_aheadVal;
} else {
// Parse new token
@ -1017,8 +1025,8 @@ int V3ParseImp::lexToken() {
V3ParseBisonYYSType curValue = yylval; // Remember value, as about to read ahead
int nexttok = yylexReadTok();
m_ahead = true;
m_aheadToken = nexttok;
m_aheadVal = yylval;
m_aheadVal.token = nexttok;
yylval = curValue;
// Now potentially munge the current token
if (token == yCONST__LEX) {
@ -1060,21 +1068,25 @@ int V3ParseImp::lexToken() {
token = yaID__ETC;
}
}
return token;
yylval.token = token;
// effectively returns yylval
}
int V3ParseImp::lexToBison() {
// Called as global since bison doesn't have our pointer
int tok = lexToken();
lexToken(); // sets yylval
m_prevBisonVal = m_curBisonVal;
m_curBisonVal = yylval;
//yylval.scp = NULL; // Symbol table not yet needed - no packages
if (debugFlex()>=6 || debugBison()>=6) {
cout<<" {"<<yylval.fl->filenameLetters()<<yylval.fl->lineno()
<<"} lexToBison TOKEN="<<tok<<" "<<tokenName(tok);
if (tok == yaID__ETC || tok == yaID__LEX || tok == yaID__aTYPE) {
<<"} lexToBison TOKEN="<<yylval.token<<" "<<tokenName(yylval.token);
if (yylval.token == yaID__ETC || yylval.token == yaID__LEX || yylval.token == yaID__aTYPE) {
cout<<" strp='"<<*(yylval.strp)<<"'";
}
cout<<endl;
}
return tok;
return yylval.token;
}

View File

@ -0,0 +1,27 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2008 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.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
v_flags2 => ["--lint-only"],
fails=>1,
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
expect=> quotemeta(
qq{%Error: t/t_lint_pkg_colon_bad.v:6: syntax error, unexpected ::, expecting ')' or ','
%Error: t/t_lint_pkg_colon_bad.v:6: Perhaps 'mispkg' is a package which needs to be predeclared? (IEEE 2012 26.3)
%Error: t/t_lint_pkg_colon_bad.v:7: syntax error, unexpected ::, expecting ',' or ';'
%Error: t/t_lint_pkg_colon_bad.v:7: Perhaps 'mispkgb' is a package which needs to be predeclared? (IEEE 2012 26.3)
}).'%Error: Exiting due to.*'
);
ok(1);
1;

View File

@ -0,0 +1,8 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2017 by Wilson Snyder.
module t (input mispkg::foo_t a);
reg mispkgb::bar_t b;
endmodule