Internals: Reindent and move parser code. No functional change.

This commit is contained in:
Wilson Snyder 2020-06-06 08:44:44 -04:00
parent aae2bf872c
commit d15e3d93c4
5 changed files with 856 additions and 775 deletions

View File

@ -425,6 +425,9 @@ CPPCHECK_CPP = $(wildcard \
CPPCHECK_H = $(wildcard \
$(srcdir)/include/*.h \
$(srcdir)/src/*.h )
CPPCHECK_YL = $(wildcard \
$(srcdir)/src/*.y \
$(srcdir)/src/*.l )
CPPCHECK = src/cppcheck_filtered
CPPCHECK_FLAGS = --enable=all --inline-suppr \
--suppress=unusedScopedObject --suppress=cstyleCast --suppress=useInitializationList \
@ -462,7 +465,7 @@ CLANGFORMAT_FLAGS = -i
clang-format:
@$(CLANGFORMAT) --version | egrep 10.0 > /dev/null \
|| echo "*** You are not using clang-format 10.0, indents may differ from master's ***"
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CPPCHECK_CPP) $(CPPCHECK_H)
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL)
ftp: info

View File

@ -34,6 +34,8 @@
#include "V3PreShell.h"
#include "V3LanguageWords.h"
#include "V3ParseBison.h" // Generated by bison
#include <sstream>
//======================================================================
@ -352,6 +354,151 @@ void V3ParseImp::lexFile(const string& modname) {
if (bisonParse()) v3fatal("Cannot continue\n");
}
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_aheadVal.token;
yylval = m_aheadVal;
} else {
// Parse new token
token = yylexReadTok();
// yylval // Set by yylexReadTok()
}
// If a paren, read another
if (token == '(' //
|| token == yCONST__LEX //
|| token == yGLOBAL__LEX //
|| token == yLOCAL__LEX //
|| token == yNEW__LEX //
|| token == yVIRTUAL__LEX
// Never put yID_* here; below symbol table resolution would break
) {
if (debugFlex() >= 6) {
cout << " lexToken: reading ahead to find possible strength" << endl;
}
V3ParseBisonYYSType curValue = yylval; // Remember value, as about to read ahead
int nexttok = yylexReadTok();
m_ahead = true;
m_aheadVal = yylval;
m_aheadVal.token = nexttok;
yylval = curValue;
// Now potentially munge the current token
if (token == '('
&& (nexttok == ygenSTRENGTH || nexttok == ySUPPLY0 || nexttok == ySUPPLY1)) {
token = yP_PAR__STRENGTH;
} else if (token == yCONST__LEX) {
if (nexttok == yREF) {
token = yCONST__REF;
} else {
token = yCONST__ETC;
}
} else if (token == yGLOBAL__LEX) {
if (nexttok == yCLOCKING) {
token = yGLOBAL__CLOCKING;
} else if (v3Global.opt.pedantic()) {
token = yGLOBAL__ETC;
}
// Avoid 2009 "global" conflicting with old code when we can
else {
token = yaID__LEX;
yylval.strp = V3ParseImp::parsep()->newString("global");
}
} else if (token == yLOCAL__LEX) {
if (nexttok == yP_COLONCOLON) {
token = yLOCAL__COLONCOLON;
} else {
token = yLOCAL__ETC;
}
} else if (token == yNEW__LEX) {
if (nexttok == '(') {
token = yNEW__PAREN;
} else {
token = yNEW__ETC;
}
} else if (token == yVIRTUAL__LEX) {
if (nexttok == yCLASS) {
token = yVIRTUAL__CLASS;
} else if (nexttok == yINTERFACE) {
token = yVIRTUAL__INTERFACE;
} else if (nexttok == yaID__ETC //
|| nexttok == yaID__LEX) {
// || nexttok == yaID__aINTERFACE // but we may not know interfaces yet.
token = yVIRTUAL__anyID;
} else {
token = yVIRTUAL__ETC;
}
}
// If add to above "else if", also add to "if (token" further above
}
// If an id, change the type based on symbol table
// Note above sometimes converts yGLOBAL to a yaID__LEX
if (token == yaID__LEX) {
VSymEnt* foundp;
if (VSymEnt* look_underp = V3ParseImp::parsep()->symp()->nextId()) {
UINFO(7, " lexToken: next id lookup forced under " << look_underp << endl);
foundp = look_underp->findIdFallback(*(yylval.strp));
// "consume" it. Must set again if want another token under temp scope
V3ParseImp::parsep()->symp()->nextId(NULL);
} else {
UINFO(7, " lexToken: find upward " << V3ParseImp::parsep()->symp()->symCurrentp()
<< " for '" << *(yylval.strp) << "'" << endl);
// if (debug()>=9) V3ParseImp::parsep()->symp()->symCurrentp()->dump(cout," -findtree:
// ", true);
foundp = V3ParseImp::parsep()->symp()->symCurrentp()->findIdFallback(*(yylval.strp));
}
if (foundp) {
AstNode* scp = foundp->nodep();
yylval.scp = scp;
UINFO(7, " lexToken: Found " << scp << endl);
if (VN_IS(scp, Typedef)) {
token = yaID__aTYPE;
} else if (VN_IS(scp, TypedefFwd)) {
token = yaID__aTYPE;
} else if (VN_IS(scp, Class)) {
token = yaID__aTYPE;
}
// Packages (and class static references) we could
// alternatively determine by looking for an yaID__LEX followed
// by yP_COLONCOLON (but we can't lookahead after an yaID__LEX
// as described above.)
else if (VN_IS(scp, Package)) {
token = yaID__aPACKAGE;
} else {
token = yaID__ETC;
}
} else { // Not found
yylval.scp = NULL;
token = yaID__ETC;
}
}
yylval.token = token;
// effectively returns yylval
}
int V3ParseImp::lexToBison() {
// Called as global since bison doesn't have our pointer
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) { // --debugi-flex and --debugi-bison
cout << " {" << yylval.fl->filenameLetters() << yylval.fl->asciiLineCol()
<< "} 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 yylval.token;
}
//======================================================================
// V3Parse functions

View File

@ -1,8 +1,3 @@
%option noyywrap align interactive
%option stack
%option noc++
%option prefix="V3PreLex"
%{
/**************************************************************************
* DESCRIPTION: Verilator: Flex verilog preprocessor
*
@ -20,6 +15,16 @@
* Do not use Flex in C++ mode. It has bugs with yyunput() which result in
* lost characters.
**************************************************************************/
/* clang-format off */
%option noyywrap align interactive
%option stack
%option noc++
%option prefix="V3PreLex"
%{
#ifdef NEVER_JUST_FOR_CLANG_FORMAT
}
#endif
#include "V3PreProc.h"
#include "V3PreLex.h"
@ -27,17 +32,22 @@
# include <io.h> // for isatty
#endif
V3PreLex* V3PreLex::s_currentLexp = NULL; // Current lexing point
/* clang-format on */
V3PreLex* V3PreLex::s_currentLexp = NULL; // Current lexing point
#define LEXP V3PreLex::s_currentLexp
#define YY_INPUT(buf,result,max_size) \
#define YY_INPUT(buf, result, max_size) \
do { result = LEXP->inputToLex(buf, max_size); } while (false)
// Accessors, because flex keeps changing the type of yyleng
char* yyourtext() { return yytext; }
size_t yyourleng() { return yyleng; }
void yyourtext(const char* textp, size_t size) { yytext=(char*)textp; yyleng=size; }
void yyourtext(const char* textp, size_t size) {
yytext = (char*)textp;
yyleng = size;
}
// FL_FWD only tracks columns; preproc uses linenoInc() to track lines, so
// insertion of a \n does not mess up line count
@ -46,12 +56,13 @@ void yyourtext(const char* textp, size_t size) { yytext=(char*)textp; yyleng=siz
#define FL_BRK (LEXP->curFilelinep()->startToken())
// Prevent conflicts from perl version
static void linenoInc() {LEXP->linenoInc();}
static void linenoInc() { LEXP->linenoInc(); }
static bool pedantic() { return LEXP->m_pedantic; }
static void yyerror(char* msg) { LEXP->curFilelinep()->v3error(msg); }
static void yyerrorf(const char* msg) { LEXP->curFilelinep()->v3error(msg); }
static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t, l); }
/* clang-format off */
/**********************************************************************/
%}
@ -308,6 +319,7 @@ bom [\357\273\277]
<INITIAL>[\r] { FL_FWDC; FL_BRK; }
<INITIAL>. { FL_FWDC; return VP_TEXT; }
%%
// clang-format on
void V3PreLex::pushStateDefArg(int level) {
// Enter define substitution argument state
@ -336,12 +348,15 @@ void V3PreLex::pushStateIncFilename() {
yymore();
}
void V3PreLex::debug(int level) { yy_flex_debug = level; }
int V3PreLex::debug() { return yy_flex_debug; }
void V3PreLex::debug(int level) {
yy_flex_debug = level; }
int V3PreLex::debug() {
return yy_flex_debug; }
int V3PreLex::lex() {
V3PreLex::s_currentLexp = this; // Tell parser where to get/put data
m_tokFilelinep = curFilelinep(); // Remember token start location, may be updated by the lexer later
// Remember token start location, may be updated by the lexer later
m_tokFilelinep = curFilelinep();
return yylex();
}
@ -354,30 +369,32 @@ size_t V3PreLex::inputToLex(char* buf, size_t max_size) {
//
VPreStream* streamp = curStreamp();
if (debug() >= 10) {
cout<<"- pp:inputToLex ITL s="<<max_size<<" bs="<<streamp->m_buffers.size()<<endl;
cout << "- pp:inputToLex ITL s=" << max_size << " bs=" << streamp->m_buffers.size()
<< endl;
dumpStack();
}
// For testing, use really small chunks
//if (max_size > 13) max_size=13;
again:
// if (max_size > 13) max_size=13;
again:
size_t got = 0;
// Get from this stream
while (got < max_size // Haven't got enough
&& !streamp->m_buffers.empty()) { // And something buffered
string front = curStreamp()->m_buffers.front(); streamp->m_buffers.pop_front();
string front = curStreamp()->m_buffers.front();
streamp->m_buffers.pop_front();
size_t len = front.length();
if (len > (max_size-got)) { // Front string too big
len = (max_size-got);
if (len > (max_size - got)) { // Front string too big
len = (max_size - got);
string remainder = front.substr(len);
front = front.substr(0, len);
streamp->m_buffers.push_front(remainder); // Put back remainder for next time
}
strncpy(buf+got, front.c_str(), len);
strncpy(buf + got, front.c_str(), len);
got += len;
}
if (!got) { // end of stream; try "above" file
bool again = false;
string forceOut = endOfStream(again/*ref*/);
string forceOut = endOfStream(again /*ref*/);
streamp = curStreamp(); // May have been updated
if (forceOut != "") {
if (forceOut.length() > max_size) {
@ -388,13 +405,15 @@ size_t V3PreLex::inputToLex(char* buf, size_t max_size) {
}
} else {
if (streamp->m_eof) {
if (yy_flex_debug) cout<<"- EOF\n";
if (yy_flex_debug) cout << "- EOF\n";
}
got = 0; // 0=EOF/EOS - although got was already 0.
if (again) goto again;
}
}
if (debug() >= 10) { cout<<"- pp::inputToLex got="<<got<<" '"<<string(buf, got)<<"'"<<endl; }
if (debug() >= 10) {
cout << "- pp::inputToLex got=" << got << " '" << string(buf, got) << "'" << endl;
}
return got;
}
@ -402,7 +421,7 @@ string V3PreLex::endOfStream(bool& againr) {
// Switch to file or next unputString
againr = false;
if (yy_flex_debug) {
cout<<"-EOS state="<<curStreamp()->m_termState<<" at "<<curFilelinep()<<endl;
cout << "-EOS state=" << curStreamp()->m_termState << " at " << curFilelinep() << endl;
}
if (curStreamp()->m_eof) return ""; // Don't delete the final "EOF" stream
bool exited_file = curStreamp()->m_file;
@ -424,18 +443,15 @@ string V3PreLex::endOfStream(bool& againr) {
// immediately.
curStreamp()->m_termState = 1;
return "\n"; // Exit old file
}
else if (curStreamp()->m_termState == 1) {
} else if (curStreamp()->m_termState == 1) {
// Now the EOF - can't be sent with other characters
curStreamp()->m_termState = 2;
return ""; // End of file
}
else if (curStreamp()->m_termState == 2) {
} else if (curStreamp()->m_termState == 2) {
// Now ending `line
curStreamp()->m_termState = 3;
return curFilelinep()->lineDirectiveStrg(2); // Exit old file
}
else {
} else {
// Final shutdown phase for a stream, we can finally change the
// current fileline to the new stream
curStreamp()->m_termState = 0;
@ -518,7 +534,7 @@ void V3PreLex::scanBytesBack(const string& str) {
string V3PreLex::currentUnreadChars() {
// WARNING - Peeking at internals
ssize_t left = (yy_n_chars - (yy_c_buf_p -currentBuffer()->yy_ch_buf));
ssize_t left = (yy_n_chars - (yy_c_buf_p - currentBuffer()->yy_ch_buf));
if (left > 0) { // left may be -1 at EOS
*(yy_c_buf_p) = (yy_hold_char);
return string(yy_c_buf_p, left);
@ -536,25 +552,24 @@ int V3PreLex::currentStartState() const {
}
void V3PreLex::lineDirective(const char* textp) {
curFilelinep()->lineDirective(textp, m_enterExit/*ref*/);
curFilelinep()->lineDirective(textp, m_enterExit /*ref*/);
// Make sure we have a dependency on whatever file was specified
V3File::addSrcDepend(curFilelinep()->filename());
}
void V3PreLex::warnBackslashSpace() {
// Make fileline highlight the specific backslash and space
curFilelinep()->v3warn(BSSPACE, "Backslash followed by whitespace, perhaps the whitespace is accidental?");
curFilelinep()->v3warn(
BSSPACE, "Backslash followed by whitespace, perhaps the whitespace is accidental?");
}
void V3PreLex::dumpSummary() {
cout<<"- pp::dumpSummary curBuf="<<cvtToHex(currentBuffer());
cout << "- pp::dumpSummary curBuf=" << cvtToHex(currentBuffer());
#ifdef FLEX_DEBUG // Else peeking at internals may cause portability issues
ssize_t left = (yy_n_chars
- (yy_c_buf_p
-currentBuffer()->yy_ch_buf));
cout<<" left="<<std::dec<<left;
ssize_t left = (yy_n_chars - (yy_c_buf_p - currentBuffer()->yy_ch_buf));
cout << " left=" << std::dec << left;
#endif
cout<<endl;
cout << endl;
}
void V3PreLex::dumpStack() {
@ -563,13 +578,10 @@ void V3PreLex::dumpStack() {
std::stack<VPreStream*> tmpstack = LEXP->m_streampStack;
while (!tmpstack.empty()) {
VPreStream* streamp = tmpstack.top();
cout<<"- bufferStack["<<cvtToHex(streamp)<<"]: "
<<" at="<<streamp->m_curFilelinep
<<" nBuf="<<streamp->m_buffers.size()
<<" size0="<<(streamp->m_buffers.empty() ? 0 : streamp->m_buffers.front().length())
<<(streamp->m_eof?" [EOF]":"")
<<(streamp->m_file?" [FILE]":"");
cout<<endl;
cout << "- bufferStack[" << cvtToHex(streamp) << "]: "
<< " at=" << streamp->m_curFilelinep << " nBuf=" << streamp->m_buffers.size()
<< " size0=" << (streamp->m_buffers.empty() ? 0 : streamp->m_buffers.front().length())
<< (streamp->m_eof ? " [EOF]" : "") << (streamp->m_file ? " [FILE]" : "") << endl;
tmpstack.pop();
}
}

View File

@ -13,10 +13,15 @@
* SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
*
*************************************************************************/
/* clang-format off */
%option interactive c++ stack noyywrap
%{
/* %option nodefault */
#ifdef NEVER_JUST_FOR_CLANG_FORMAT
}
#endif
// clang-format on
#include "V3Number.h"
#include "V3ParseImp.h" // Defines YYTYPE; before including bison header
@ -31,7 +36,7 @@ extern void yyerrorf(const char* format, ...);
#define SYMP PARSEP->symp()
#define YY_INPUT(buf, result, max_size) \
do { result = PARSEP->flexPpInputToLex(buf, max_size); } while (false)
do { result = PARSEP->flexPpInputToLex(buf, max_size); } while (false)
//======================================================================
@ -41,12 +46,18 @@ extern void yyerrorf(const char* format, ...);
#define CRELINE() (PARSEP->copyOrSameFileLine())
#define FL do { FL_FWD; yylval.fl = CRELINE(); } while (false)
#define FL \
do { \
FL_FWD; \
yylval.fl = CRELINE(); \
} while (false)
#define ERROR_RSVD_WORD(language) \
do { FL_FWD; \
yyerrorf("Unsupported: " language " reserved word not implemented: '%s'", yytext); \
FL_BRK; } while(0)
do { \
FL_FWD; \
yyerrorf("Unsupported: " language " reserved word not implemented: '%s'", yytext); \
FL_BRK; \
} while (0)
//======================================================================
@ -80,6 +91,7 @@ void yyerrorf(const char* format, ...) {
yyerror(msg);
}
// clang-format off
/**********************************************************************/
%}
@ -1039,149 +1051,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/* Catch all - absolutely last */
<*>.|\n { FL_FWD; yyerrorf("Missing verilog.l rule: Default rule invoked in state %d: %s", YY_START, yytext); FL_BRK; }
%%
// Avoid code here as cl format misindents
// For implementation functions see V3ParseImp.cpp
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
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_aheadVal.token;
yylval = m_aheadVal;
} else {
// Parse new token
token = yylexReadTok();
// yylval // Set by yylexReadTok()
}
// If a paren, read another
if (token == '(' //
|| token == yCONST__LEX //
|| token == yGLOBAL__LEX //
|| token == yLOCAL__LEX //
|| token == yNEW__LEX //
|| token == yVIRTUAL__LEX
// Never put yID_* here; below symbol table resolution would break
) {
if (debugFlex() >= 6) {
cout << " lexToken: reading ahead to find possible strength" << endl;
}
V3ParseBisonYYSType curValue = yylval; // Remember value, as about to read ahead
int nexttok = yylexReadTok();
m_ahead = true;
m_aheadVal = yylval;
m_aheadVal.token = nexttok;
yylval = curValue;
// Now potentially munge the current token
if (token == '('
&& (nexttok == ygenSTRENGTH || nexttok == ySUPPLY0 || nexttok == ySUPPLY1)) {
token = yP_PAR__STRENGTH;
} else if (token == yCONST__LEX) {
if (nexttok == yREF) {
token = yCONST__REF;
} else {
token = yCONST__ETC;
}
} else if (token == yGLOBAL__LEX) {
if (nexttok == yCLOCKING) {
token = yGLOBAL__CLOCKING;
} else if (v3Global.opt.pedantic()) {
token = yGLOBAL__ETC;
}
// Avoid 2009 "global" conflicting with old code when we can
else {
token = yaID__LEX;
yylval.strp = PARSEP->newString("global");
}
} else if (token == yLOCAL__LEX) {
if (nexttok == yP_COLONCOLON) {
token = yLOCAL__COLONCOLON;
} else {
token = yLOCAL__ETC;
}
} else if (token == yNEW__LEX) {
if (nexttok == '(') {
token = yNEW__PAREN;
} else {
token = yNEW__ETC;
}
} else if (token == yVIRTUAL__LEX) {
if (nexttok == yCLASS) {
token = yVIRTUAL__CLASS;
} else if (nexttok == yINTERFACE) {
token = yVIRTUAL__INTERFACE;
} else if (nexttok == yaID__ETC //
|| nexttok == yaID__LEX) {
// || nexttok == yaID__aINTERFACE // but we may not know interfaces yet.
token = yVIRTUAL__anyID;
} else {
token = yVIRTUAL__ETC;
}
}
// If add to above "else if", also add to "if (token" further above
}
// If an id, change the type based on symbol table
// Note above sometimes converts yGLOBAL to a yaID__LEX
if (token == yaID__LEX) {
VSymEnt* foundp;
if (VSymEnt* look_underp = SYMP->nextId()) {
UINFO(7, " lexToken: next id lookup forced under " << look_underp << endl);
foundp = look_underp->findIdFallback(*(yylval.strp));
// "consume" it. Must set again if want another token under temp scope
SYMP->nextId(NULL);
} else {
UINFO(7, " lexToken: find upward " << SYMP->symCurrentp() << " for '"
<< *(yylval.strp) << "'" << endl);
// if (debug()>=9) SYMP->symCurrentp()->dump(cout," -findtree: ", true);
foundp = SYMP->symCurrentp()->findIdFallback(*(yylval.strp));
}
if (foundp) {
AstNode* scp = foundp->nodep();
yylval.scp = scp;
UINFO(7, " lexToken: Found " << scp << endl);
if (VN_IS(scp, Typedef)) {
token = yaID__aTYPE;
} else if (VN_IS(scp, TypedefFwd)) {
token = yaID__aTYPE;
} else if (VN_IS(scp, Class)) {
token = yaID__aTYPE;
}
// Packages (and class static references) we could
// alternatively determine by looking for an yaID__LEX followed
// by yP_COLONCOLON (but we can't lookahead after an yaID__LEX
// as described above.)
else if (VN_IS(scp, Package)) {
token = yaID__aPACKAGE;
} else {
token = yaID__ETC;
}
} else { // Not found
yylval.scp = NULL;
token = yaID__ETC;
}
}
yylval.token = token;
// effectively returns yylval
}
int V3ParseImp::lexToBison() {
// Called as global since bison doesn't have our pointer
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) { // --debugi-flex and --debugi-bison
cout << " {" << yylval.fl->filenameLetters() << yylval.fl->asciiLineCol()
<< "} 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 yylval.token;
}

File diff suppressed because it is too large Load Diff