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
/* 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
@ -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; \
do { \
FL_FWD; \
yyerrorf("Unsupported: " language " reserved word not implemented: '%s'", yytext); \
FL_BRK; } while(0)
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;
}

View File

@ -15,8 +15,13 @@
//*************************************************************************
// Original code here by Paul Wasson and Duane Galbi
//*************************************************************************
// clang-format off
%{
#ifdef NEVER_JUST_FOR_CLANG_FORMAT
}
#endif
// clang-format on
#include "V3Ast.h"
#include "V3Global.h"
#include "V3Config.h"
@ -31,8 +36,12 @@
// Pick up new lexer
#define yylex PARSEP->lexToBison
#define BBUNSUP(fl,msg) { if (!v3Global.opt.bboxUnsup()) { (fl)->v3error(msg); } }
#define GATEUNSUP(fl,tok) { BBUNSUP((fl), "Unsupported: Verilog 1995 gate primitive: "<<(tok)); }
#define BBUNSUP(fl, msg) \
{ \
if (!v3Global.opt.bboxUnsup()) { (fl)->v3error(msg); } \
}
#define GATEUNSUP(fl, tok) \
{ BBUNSUP((fl), "Unsupported: Verilog 1995 gate primitive: " << (tok)); }
extern void yyerror(const char* errmsg);
extern void yyerrorf(const char* format, ...);
@ -97,7 +106,8 @@ public:
}
AstRange* scrubRange(AstNodeRange* rangep);
AstNodeDType* createArray(AstNodeDType* basep, AstNodeRange* rangep, bool isPacked);
AstVar* createVariable(FileLine* fileline, const string& name, AstNodeRange* arrayp, AstNode* attrsp);
AstVar* createVariable(FileLine* fileline, const string& name, AstNodeRange* arrayp,
AstNode* attrsp);
AstNode* createSupplyExpr(FileLine* fileline, const string& name, int value);
AstText* createTextQuoted(FileLine* fileline, const string& text) {
string newtext = deQuote(fileline, text);
@ -110,8 +120,11 @@ public:
}
AstNode* createGatePin(AstNode* exprp) {
AstRange* rangep = m_gateRangep;
if (!rangep) return exprp;
else return new AstGatePin(rangep->fileline(), exprp, rangep->cloneTree(true));
if (!rangep) {
return exprp;
} else {
return new AstGatePin(rangep->fileline(), exprp, rangep->cloneTree(true));
}
}
void endLabel(FileLine* fl, AstNode* nodep, string* endnamep) {
endLabel(fl, nodep->prettyName(), endnamep);
@ -119,12 +132,13 @@ public:
void endLabel(FileLine* fl, const string& name, string* endnamep) {
if (fl && endnamep && *endnamep != "" && name != *endnamep
&& name != AstNode::prettyName(*endnamep)) {
fl->v3warn(ENDLABEL,"End label '"<<*endnamep<<"' does not match begin label '"<<name<<"'");
fl->v3warn(ENDLABEL, "End label '" << *endnamep << "' does not match begin label '"
<< name << "'");
}
}
void setVarDecl(AstVarType type) { m_varDecl = type; }
void setDType(AstNodeDType* dtypep) {
if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep=NULL); // It was cloned, so this is safe.
if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = NULL);
m_varDTypep = dtypep;
}
AstPackage* unitPackage(FileLine* fl) {
@ -160,8 +174,9 @@ public:
if (AstRange* finalRangep = VN_CAST(finalp, Range)) { // not an UnsizedRange
if (dtypep->implicit()) {
// It's no longer implicit but a wire logic type
AstBasicDType* newp = new AstBasicDType(dtypep->fileline(), AstBasicDTypeKwd::LOGIC,
dtypep->numeric(), dtypep->width(), dtypep->widthMin());
AstBasicDType* newp = new AstBasicDType(
dtypep->fileline(), AstBasicDTypeKwd::LOGIC, dtypep->numeric(),
dtypep->width(), dtypep->widthMin());
VL_DO_DANGLING(dtypep->deleteTree(), dtypep);
dtypep = newp;
}
@ -174,7 +189,7 @@ public:
string deQuote(FileLine* fileline, string text);
void checkDpiVer(FileLine* fileline, const string& str) {
if (str != "DPI-C" && !v3Global.opt.bboxSys()) {
fileline->v3error("Unsupported DPI type '"<<str<<"': Use 'DPI-C'");
fileline->v3error("Unsupported DPI type '" << str << "': Use 'DPI-C'");
}
}
};
@ -187,53 +202,87 @@ int V3ParseGrammar::s_modTypeImpNum = 0;
//======================================================================
// Macro functions
#define CRELINE() (PARSEP->copyOrSameFileLine()) // Only use in empty rules, so lines point at beginnings
#define CRELINE() \
(PARSEP->copyOrSameFileLine()) // Only use in empty rules, so lines point at beginnings
#define FILELINE_OR_CRE(nodep) ((nodep) ? (nodep)->fileline() : CRELINE())
#define VARRESET_LIST(decl) { GRAMMARP->m_pinNum=1; GRAMMARP->m_pinAnsi=false; \
VARRESET(); VARDECL(decl); } // Start of pinlist
#define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; GRAMMARP->m_pinAnsi=false; \
VARRESET(); VARDECL(decl); } // Not in a pinlist
#define VARRESET() { VARDECL(UNKNOWN); VARIO(NONE); VARDTYPE_NDECL(NULL); \
#define VARRESET_LIST(decl) \
{ \
GRAMMARP->m_pinNum = 1; \
GRAMMARP->m_pinAnsi = false; \
VARRESET(); \
VARDECL(decl); \
} // Start of pinlist
#define VARRESET_NONLIST(decl) \
{ \
GRAMMARP->m_pinNum = 0; \
GRAMMARP->m_pinAnsi = false; \
VARRESET(); \
VARDECL(decl); \
} // Not in a pinlist
#define VARRESET() \
{ \
VARDECL(UNKNOWN); \
VARIO(NONE); \
VARDTYPE_NDECL(NULL); \
GRAMMARP->m_varLifetime = VLifetime::NONE; \
GRAMMARP->m_varDeclTyped = false; }
#define VARDECL(type) { GRAMMARP->setVarDecl(AstVarType::type); }
#define VARIO(type) { GRAMMARP->m_varIO = VDirection::type; }
#define VARLIFE(flag) { GRAMMARP->m_varLifetime = flag; }
#define VARDTYPE(dtypep) { GRAMMARP->setDType(dtypep); GRAMMARP->m_varDeclTyped = true; }
#define VARDTYPE_NDECL(dtypep) { GRAMMARP->setDType(dtypep); } // Port that is range or signed only (not a decl)
GRAMMARP->m_varDeclTyped = false; \
}
#define VARDECL(type) \
{ GRAMMARP->setVarDecl(AstVarType::type); }
#define VARIO(type) \
{ GRAMMARP->m_varIO = VDirection::type; }
#define VARLIFE(flag) \
{ GRAMMARP->m_varLifetime = flag; }
#define VARDTYPE(dtypep) \
{ \
GRAMMARP->setDType(dtypep); \
GRAMMARP->m_varDeclTyped = true; \
}
#define VARDTYPE_NDECL(dtypep) \
{ GRAMMARP->setDType(dtypep); } // Port that is range or signed only (not a decl)
#define VARDONEA(fl,name,array,attrs) GRAMMARP->createVariable((fl),(name),(array),(attrs))
#define VARDONEP(portp,array,attrs) GRAMMARP->createVariable((portp)->fileline(),(portp)->name(),(array),(attrs))
#define VARDONEA(fl, name, array, attrs) GRAMMARP->createVariable((fl), (name), (array), (attrs))
#define VARDONEP(portp, array, attrs) \
GRAMMARP->createVariable((portp)->fileline(), (portp)->name(), (array), (attrs))
#define PINNUMINC() (GRAMMARP->m_pinNum++)
#define GATERANGE(rangep) { GRAMMARP->m_gateRangep = rangep; }
#define GATERANGE(rangep) \
{ GRAMMARP->m_gateRangep = rangep; }
#define INSTPREP(modfl,modname,paramsp) { \
#define INSTPREP(modfl, modname, paramsp) \
{ \
GRAMMARP->m_impliedDecl = true; \
GRAMMARP->m_instModuleFl = modfl; GRAMMARP->m_instModule = modname; \
GRAMMARP->m_instParamp = paramsp; }
GRAMMARP->m_instModuleFl = modfl; \
GRAMMARP->m_instModule = modname; \
GRAMMARP->m_instParamp = paramsp; \
}
#define DEL(nodep) { if (nodep) nodep->deleteTree(); }
#define DEL(nodep) \
{ \
if (nodep) nodep->deleteTree(); \
}
static void ERRSVKWD(FileLine* fileline, const string& tokname) {
static int toldonce = 0;
fileline->v3error(string("Unexpected '")+tokname+"': '"+tokname
+"' is a SystemVerilog keyword misused as an identifier."
+(!toldonce++
? "\n"+V3Error::warnMore()
+"... Suggest modify the Verilog-2001 code to avoid SV keywords,"
+" or use `begin_keywords or --language."
fileline->v3error(
string("Unexpected '") + tokname + "': '" + tokname
+ "' is a SystemVerilog keyword misused as an identifier."
+ (!toldonce++ ? "\n" + V3Error::warnMore()
+ "... Suggest modify the Verilog-2001 code to avoid SV keywords,"
+ " or use `begin_keywords or --language."
: ""));
}
static void UNSUPREAL(FileLine* fileline) {
fileline->v3warn(SHORTREAL, "Unsupported: shortreal being promoted to real (suggest use real instead)");
fileline->v3warn(SHORTREAL,
"Unsupported: shortreal being promoted to real (suggest use real instead)");
}
//======================================================================
class AstSenTree;
// clang-format off
%}
// When writing Bison patterns we use yTOKEN instead of "token",