Fix some syntax error context by splitting internal parse and lex filelines

This commit is contained in:
Wilson Snyder 2020-06-07 13:45:50 -04:00
parent 466fd56d18
commit b469feb44b
11 changed files with 53 additions and 45 deletions

View File

@ -73,13 +73,13 @@ void V3ParseImp::lexPpline(const char* textp) {
// Handle lexer `line directive
FileLine* prevFl = copyOrSameFileLine();
int enterExit;
fileline()->lineDirective(textp, enterExit /*ref*/);
lexFileline()->lineDirective(textp, enterExit /*ref*/);
if (enterExit == 1) { // Enter
fileline()->parent(prevFl);
lexFileline()->parent(prevFl);
} else if (enterExit == 2) { // Exit
FileLine* upFl = fileline()->parent();
FileLine* upFl = lexFileline()->parent();
if (upFl) upFl = upFl->parent();
if (upFl) fileline()->parent(upFl);
if (upFl) lexFileline()->parent(upFl);
}
}
@ -141,8 +141,8 @@ void V3ParseImp::lexVerilatorCmtLint(FileLine* fl, const char* textp, bool warnO
string msg = sp;
string::size_type pos;
if ((pos = msg.find('*')) != string::npos) msg.erase(pos);
// Use parsep()->fileline() as want to affect later FileLine's warnings
if (!(parsep()->fileline()->warnOff(msg, warnOff))) {
// Use parsep()->lexFileline() as want to affect later FileLine's warnings
if (!(parsep()->lexFileline()->warnOff(msg, warnOff))) {
if (!v3Global.opt.isFuture(msg)) {
fl->v3error("Unknown verilator lint message code: '" << msg << "', in '" << textp
<< "'");
@ -274,8 +274,9 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
string modname = V3Os::filenameNonExt(modfilename);
UINFO(2, __FUNCTION__ << ": " << modname << (inLibrary ? " [LIB]" : "") << endl);
m_fileline = new FileLine(fileline);
m_fileline->newContent();
m_lexFileline = new FileLine(fileline);
m_lexFileline->newContent();
m_bisonLastFileline = m_lexFileline;
m_inLibrary = inLibrary;
// Preprocess into m_ppBuffer
@ -323,7 +324,7 @@ void V3ParseImp::lexFile(const string& modname) {
// Prepare for lexing
UINFO(3, "Lexing " << modname << endl);
s_parsep = this;
fileline()->warnResetDefault(); // Reenable warnings on each file
lexFileline()->warnResetDefault(); // Reenable warnings on each file
lexDestroy(); // Restart from clean slate.
lexNew();
@ -483,6 +484,7 @@ int V3ParseImp::lexToBison() {
lexToken(); // sets yylval
m_bisonValPrev = m_bisonValCur;
m_bisonValCur = yylval;
m_bisonLastFileline = yylval.fl;
// yylval.scp = NULL; // Symbol table not yet needed - no packages
if (debugFlex() >= 6 || debugBison() >= 6) { // --debugi-flex and --debugi-bison
@ -490,7 +492,7 @@ int V3ParseImp::lexToBison() {
<< "} lexToBison TOKEN=" << yylval.token << " " << tokenName(yylval.token);
if (yylval.token == yaID__ETC //
|| yylval.token == yaID__LEX //
|| yylval.token == yaID__aTYPE) {
|| yylval.token == yaID__aPACKAGE || yylval.token == yaID__aTYPE) {
cout << " strp='" << *(yylval.strp) << "'";
}
cout << endl;

View File

@ -105,7 +105,9 @@ class V3ParseImp {
V3Lexer* m_lexerp; // Current FlexLexer
static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based
FileLine* m_fileline; // Filename/linenumber currently active
FileLine* m_lexFileline; // Filename/linenumber currently active for lexing
FileLine* m_bisonLastFileline; // Filename/linenumber of last token
bool m_inLibrary; // Currently reading a library vs. regular file
int m_lexKwdDepth; // Inside a `begin_keywords
@ -144,7 +146,6 @@ public:
int yylexThis();
static bool optFuture(const string& flag) { return v3Global.opt.isFuture(flag); }
void linenoInc() { fileline()->linenoInc(); }
void tagNodep(AstNode* nodep) { m_tagNodep = nodep; }
AstNode* tagNodep() const { return m_tagNodep; }
void lexTimescaleParse(FileLine* fl, const char* textp);
@ -152,6 +153,8 @@ public:
bool precSet, double precVal);
VTimescale timeLastUnit() const { return m_timeLastUnit; }
FileLine* lexFileline() const { return m_lexFileline; }
FileLine* lexCopyOrSameFileLine() { return lexFileline()->copyOrSameFileLine(); }
static void lexErrorPreprocDirective(FileLine* fl, const char* textp);
static string lexParseTag(const char* textp);
static double lexParseTimenum(const char* text);
@ -178,7 +181,7 @@ public:
void ppPushText(const string& text) {
m_ppBuffers.push_back(text);
if (fileline()->contentp()) fileline()->contentp()->pushText(text);
if (lexFileline()->contentp()) lexFileline()->contentp()->pushText(text);
}
size_t ppInputToLex(char* buf, size_t max_size);
@ -209,10 +212,13 @@ public:
return nump;
}
// Bison sometimes needs error context without a token, so remember last token's line
// Only use this if do not have and cannot get a token-relevent fileline
FileLine* bisonLastFileline() const { return m_bisonLastFileline; }
// Return next token, for bison, since bison isn't class based, use a global THIS
FileLine* fileline() const { return m_fileline; }
AstNetlist* rootp() const { return m_rootp; }
FileLine* copyOrSameFileLine() { return fileline()->copyOrSameFileLine(); }
FileLine* copyOrSameFileLine() { return bisonLastFileline()->copyOrSameFileLine(); }
bool inLibrary() const { return m_inLibrary; }
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; }
@ -239,7 +245,7 @@ public:
: m_rootp(rootp)
, m_filterp(filterp)
, m_symp(parserSymp) {
m_fileline = NULL;
m_lexFileline = NULL;
m_lexerp = NULL;
m_inLibrary = false;
m_lexKwdDepth = 0;

View File

@ -52,7 +52,7 @@ void V3ParseImp::lexUnputString(const char* textp, size_t length) {
int V3ParseImp::yylexReadTok() {
// Call yylex() remembering last non-whitespace token
parsep()->fileline()->startToken();
parsep()->lexFileline()->startToken();
int token = parsep()->m_lexerp->yylex();
m_lexPrevToken = token; // Save so can find '#' to parse following number
return token;

View File

@ -36,11 +36,11 @@
//======================================================================
#define FL_FWD (PARSEP->fileline()->forwardToken(yytext, yyleng, true))
#define FL_FWD (PARSEP->lexFileline()->forwardToken(yytext, yyleng, true))
// Use this to break between tokens whereever not return'ing a token (e.g. skipping inside lexer)
#define FL_BRK (PARSEP->fileline()->startToken())
#define FL_BRK (PARSEP->lexFileline()->startToken())
#define CRELINE() (PARSEP->copyOrSameFileLine())
#define CRELINE() (PARSEP->lexCopyOrSameFileLine())
#define FL \
do { \
@ -686,15 +686,15 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"/*verilator clock_enable*/" { FL; return yVL_CLOCK_ENABLE; }
"/*verilator clocker*/" { FL; return yVL_CLOCKER; }
"/*verilator coverage_block_off*/" { FL; return yVL_COVERAGE_BLOCK_OFF; }
"/*verilator coverage_off*/" { FL_FWD; PARSEP->fileline()->coverageOn(false); FL_BRK; }
"/*verilator coverage_on*/" { FL_FWD; PARSEP->fileline()->coverageOn(true); FL_BRK; }
"/*verilator coverage_off*/" { FL_FWD; PARSEP->lexFileline()->coverageOn(false); FL_BRK; }
"/*verilator coverage_on*/" { FL_FWD; PARSEP->lexFileline()->coverageOn(true); FL_BRK; }
"/*verilator full_case*/" { FL; return yVL_FULL_CASE; }
"/*verilator inline_module*/" { FL; return yVL_INLINE_MODULE; }
"/*verilator isolate_assignments*/" { FL; return yVL_ISOLATE_ASSIGNMENTS; }
"/*verilator lint_off"[^*]*"*/" { FL; PARSEP->lexVerilatorCmtLint(yylval.fl, yytext, true); FL_BRK; }
"/*verilator lint_on"[^*]*"*/" { FL; PARSEP->lexVerilatorCmtLint(yylval.fl, yytext, false); FL_BRK; }
"/*verilator lint_restore*/" { FL; PARSEP->lexVerilatorCmtLintRestore(PARSEP->fileline()); FL_BRK; }
"/*verilator lint_save*/" { FL; PARSEP->lexVerilatorCmtLintSave(PARSEP->fileline()); FL_BRK; }
"/*verilator lint_restore*/" { FL; PARSEP->lexVerilatorCmtLintRestore(PARSEP->lexFileline()); FL_BRK; }
"/*verilator lint_save*/" { FL; PARSEP->lexVerilatorCmtLintSave(PARSEP->lexFileline()); FL_BRK; }
"/*verilator no_clocker*/" { FL; return yVL_NO_CLOCKER; }
"/*verilator no_inline_module*/" { FL; return yVL_NO_INLINE_MODULE; }
"/*verilator no_inline_task*/" { FL; return yVL_NO_INLINE_TASK; }
@ -711,8 +711,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"/*verilator systemc_clock*/" { FL; return yVL_CLOCK; }
"/*verilator tag"[^*]*"*/" { FL; yylval.strp = PARSEP->newString(V3ParseImp::lexParseTag(yytext));
return yVL_TAG; }
"/*verilator tracing_off*/" { FL_FWD; PARSEP->fileline()->tracingOn(false); FL_BRK; }
"/*verilator tracing_on*/" { FL_FWD; PARSEP->fileline()->tracingOn(true); FL_BRK; }
"/*verilator tracing_off*/" { FL_FWD; PARSEP->lexFileline()->tracingOn(false); FL_BRK; }
"/*verilator tracing_on*/" { FL_FWD; PARSEP->lexFileline()->tracingOn(true); FL_BRK; }
"/**/" { FL_FWD; FL_BRK; }
"/*"[^*]+"*/" { FL; V3ParseImp::lexVerilatorCmtBad(yylval.fl, yytext); FL_BRK; }
@ -930,10 +930,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
"`accelerate" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`autoexpand_vectornets" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`celldefine" { FL_FWD; PARSEP->fileline()->celldefineOn(true); FL_BRK; }
"`celldefine" { FL_FWD; PARSEP->lexFileline()->celldefineOn(true); FL_BRK; }
"`default_decay_time"{ws}+[^\n\r]* { FL_FWD; FL_BRK; } // Verilog spec - delays only
"`default_nettype"{ws}+"wire" { FL_FWD; PARSEP->fileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE, true); FL_BRK; }
"`default_nettype"{ws}+"none" { FL_FWD; PARSEP->fileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE, false); FL_BRK; }
"`default_nettype"{ws}+"wire" { FL_FWD; PARSEP->lexFileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE, true); FL_BRK; }
"`default_nettype"{ws}+"none" { FL_FWD; PARSEP->lexFileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE, false); FL_BRK; }
"`default_nettype"{ws}+[a-zA-Z0-9]* { FL; yylval.fl->v3error("Unsupported: `default_nettype of other than none or wire: '" << yytext << "'");
FL_BRK; }
"`default_trireg_strength"{ws}+[^\n\r]* { FL; yylval.fl->v3error("Unsupported: Verilog optional directive not implemented: '" << yytext << "'");
@ -944,7 +944,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"`delay_mode_zero" { FL_FWD; FL_BRK; } // Verilog spec - delays only
"`disable_portfaults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`enable_portfaults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`endcelldefine" { FL_FWD; PARSEP->fileline()->celldefineOn(false); FL_BRK; }
"`endcelldefine" { FL_FWD; PARSEP->lexFileline()->celldefineOn(false); FL_BRK; }
"`endprotect" { FL_FWD; FL_BRK; }
"`expand_vectornets" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`inline" { FL_FWD; FL_BRK; }
@ -960,7 +960,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"`protect" { FL_FWD; FL_BRK; }
"`remove_gatenames" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`remove_netnames" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`resetall" { FL; PARSEP->fileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE, true);
"`resetall" { FL; PARSEP->lexFileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE, true);
return yaT_RESETALL; } // Rest handled by preproc
"`suppress_faults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`timescale"{ws}+[^\n\r]* { FL; PARSEP->lexTimescaleParse(yylval.fl,

View File

@ -291,13 +291,13 @@ static void UNSUPREAL(FileLine* fileline) {
//======================================================================
void yyerror(const char* errmsg) {
PARSEP->fileline()->v3error(errmsg);
PARSEP->bisonLastFileline()->v3error(errmsg);
static const char* const colonmsg = "syntax error, unexpected ::, ";
// tokens;
if (0 == strncmp(errmsg, colonmsg, strlen(colonmsg)) && PARSEP->bisonValIdThenColon()) {
static int warned = false;
if (!warned++) {
std::cerr << PARSEP->fileline()->warnMore()
std::cerr << PARSEP->bisonLastFileline()->warnMore()
<< ("... Perhaps '" + *PARSEP->bisonValPrev().strp
+ "' is a package which needs to be predeclared? (IEEE 1800-2017 26.3)")
<< std::endl;

View File

@ -1,4 +1,4 @@
%Error: t/t_flag_wpedantic_bad.v:8:14: syntax error, unexpected global
%Error: t/t_flag_wpedantic_bad.v:8:8: syntax error, unexpected global
8 | reg global;
| ^
| ^~~~~~
%Error: Exiting due to

View File

@ -1,4 +1,4 @@
%Error: t/t_lint_mod_paren_bad.v:14:7: syntax error, unexpected '(', expecting ';'
14 | output bar
| ^~~~~~
%Error: t/t_lint_mod_paren_bad.v:13:6: syntax error, unexpected '(', expecting ';'
13 | ) (
| ^
%Error: Exiting due to

View File

@ -1,3 +1,3 @@
%Error: t/t_pp_circdef_bad.v:14:21985: Recursive `define or other nested inclusion
%Error: t/t_pp_circdef_bad.v:15:1: syntax error, unexpected $end, expecting TYPE-IDENTIFIER
%Error: t/t_pp_circdef_bad.v:14:3009: syntax error, unexpected $end, expecting TYPE-IDENTIFIER
%Error: Exiting due to

View File

@ -1,7 +1,7 @@
%Error: t/t_pp_defparen_bad.v:10:2: Illegal text before '(' that starts define arguments
10 | ( 1,2)
| ^
%Error: t/t_pp_defparen_bad.v:10:2: syntax error, unexpected '('
%Error: t/t_pp_defparen_bad.v:10:1: syntax error, unexpected '('
10 | ((val 1) + (2))
| ^
| ^
%Error: Exiting due to

View File

@ -1,4 +1,4 @@
%Error: t/t_udp_noname.v:15:9: syntax error, unexpected '(', expecting IDENTIFIER or randomize
%Error: t/t_udp_noname.v:15:8: syntax error, unexpected '(', expecting IDENTIFIER or randomize
15 | udp (o, a);
| ^
| ^
%Error: Exiting due to

View File

@ -5,7 +5,7 @@
%Error: t/t_var_bad_sv.v:9:14: Unexpected 'do': 'do' is a SystemVerilog keyword misused as an identifier.
9 | mod mod (.do(bar));
| ^~
%Error: t/t_var_bad_sv.v:9:17: syntax error, unexpected '(', expecting ')'
%Error: t/t_var_bad_sv.v:9:16: syntax error, unexpected '(', expecting ')'
9 | mod mod (.do(bar));
| ^~~
| ^
%Error: Exiting due to