Fix some syntax error context by splitting internal parse and lex filelines
This commit is contained in:
parent
466fd56d18
commit
b469feb44b
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue