Remove symbol table from parser: Support redeclaring type as non-type; major parsing change (#2412).

This commit is contained in:
Wilson Snyder 2025-05-17 22:42:00 -04:00
parent 6bb16d6c52
commit 0c8c7fb03c
20 changed files with 124 additions and 450 deletions

View File

@ -13,6 +13,7 @@ Verilator 5.037 devel
**Other:**
* Support redeclaring type as non-type; major parsing change (#2412).
* Support constrained random for associative arrays (#5985) (#5986). [Yilou Wang]
* Support assignments to concatenations with impure RHS (#6002). [Ryszard Rozak, Antmicro Ltd.]
* Support SARIF JSON diagnostic output with `--diagnostics-sarif`. (#6017)

View File

@ -142,7 +142,6 @@ set(HEADERS
V3Param.h
V3Parse.h
V3ParseImp.h
V3ParseSym.h
V3PchAstMT.h
V3PchAstNoMT.h
V3PreExpr.h

View File

@ -24,7 +24,6 @@
#include "V3HierBlock.h"
#include "V3LinkCells.h"
#include "V3Parse.h"
#include "V3ParseSym.h"
#include "V3Stats.h"
#include "V3ThreadPool.h"
@ -54,9 +53,8 @@ void V3Global::readFiles() {
const VNUser4InUse inuser4;
VInFilter filter{v3Global.opt.pipeFilter()};
V3ParseSym parseSyms{v3Global.rootp()}; // Symbol table must be common across all parsing
V3Parse parser{v3Global.rootp(), &filter, &parseSyms};
V3Parse parser{v3Global.rootp(), &filter};
// Parse the std waivers
if (v3Global.opt.stdWaiver()) {
@ -106,7 +104,7 @@ void V3Global::readFiles() {
if (!v3Global.opt.preprocOnly() || v3Global.opt.preprocResolve()) {
// Resolve all modules cells refer to
V3LinkCells::link(v3Global.rootp(), &filter, &parseSyms);
V3LinkCells::link(v3Global.rootp(), &filter);
}
V3Global::dumpCheckGlobalTree("cells", false, dumpTreeEitherLevel() >= 9);

View File

@ -105,7 +105,6 @@ class LinkCellsVisitor final : public VNVisitor {
// STATE
VInFilter* const m_filterp; // Parser filter
V3ParseSym* m_parseSymp; // Parser symbol table
// Below state needs to be preserved between each module call.
AstNodeModule* m_modp = nullptr; // Current module
@ -141,7 +140,7 @@ class LinkCellsVisitor final : public VNVisitor {
// If file not found, make AstNotFoundModule, rather than error out.
// We'll throw the error when we know the module will really be needed.
const string prettyName = AstNode::prettyName(modName);
V3Parse parser{v3Global.rootp(), m_filterp, m_parseSymp};
V3Parse parser{v3Global.rootp(), m_filterp};
// true below -> other simulators treat modules in link-found files as library cells
parser.parseFile(nodep->fileline(), prettyName, true, "");
V3Error::abortIfErrors();
@ -607,9 +606,8 @@ class LinkCellsVisitor final : public VNVisitor {
public:
// CONSTRUCTORS
LinkCellsVisitor(AstNetlist* nodep, VInFilter* filterp, V3ParseSym* parseSymp)
LinkCellsVisitor(AstNetlist* nodep, VInFilter* filterp)
: m_filterp{filterp}
, m_parseSymp{parseSymp}
, m_mods{nodep} {
if (v3Global.opt.hierChild()) {
const V3HierBlockOptSet& hierBlocks = v3Global.opt.hierBlocks();
@ -631,7 +629,7 @@ public:
//######################################################################
// Link class functions
void V3LinkCells::link(AstNetlist* nodep, VInFilter* filterp, V3ParseSym* parseSymp) {
void V3LinkCells::link(AstNetlist* nodep, VInFilter* filterp) {
UINFO(4, __FUNCTION__ << ": " << endl);
{ LinkCellsVisitor{nodep, filterp, parseSymp}; }
{ LinkCellsVisitor{nodep, filterp}; }
}

View File

@ -28,7 +28,7 @@ class V3ParseSym;
class V3LinkCells final {
public:
static void link(AstNetlist* nodep, VInFilter* filterp, V3ParseSym* parseSymp) VL_MT_DISABLED;
static void link(AstNetlist* nodep, VInFilter* filterp) VL_MT_DISABLED;
};
#endif // Guard

View File

@ -26,7 +26,6 @@
class AstNetlist;
class VInFilter;
class V3ParseImp;
class V3ParseSym;
//============================================================================
@ -38,7 +37,7 @@ class V3Parse final {
public:
// We must allow reading multiple files into one parser
V3Parse(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* symp) VL_MT_DISABLED;
V3Parse(AstNetlist* rootp, VInFilter* filterp) VL_MT_DISABLED;
~V3Parse() VL_MT_DISABLED;
// METHODS

View File

@ -262,7 +262,6 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name,
// Parser needs to know what is a type
AstNode* const newp = new AstTypedefFwd{fileline, name};
AstNode::addNext<AstNode, AstNode>(nodep, newp);
SYMP->reinsert(newp);
}
// Don't set dtypep in the ranging;
// We need to autosize parameters and integers separately

View File

@ -48,8 +48,6 @@ VL_DEFINE_DEBUG_FUNCTIONS;
V3ParseImp* V3ParseImp::s_parsep = nullptr;
int V3ParseSym::s_anonNum = 0;
//######################################################################
// Parser constructor
@ -60,11 +58,6 @@ V3ParseImp::~V3ParseImp() {
m_numberps.clear();
lexDestroy();
parserClear();
if (debug() >= 9) {
UINFO(0, "~V3ParseImp\n");
symp()->dumpSelf(cout, "-vpi: ");
}
}
//######################################################################
@ -695,43 +688,7 @@ void V3ParseImp::tokenPipelineSym() {
int token = yylval.token;
if (token == yaID__LEX || token == yaID__CC || token == yaID__aTYPE) {
importIfInStd(yylval.fl, *(yylval.strp));
}
if (token == yaID__LEX || token == yaID__CC) {
const VSymEnt* foundp;
if (const VSymEnt* const look_underp = V3ParseImp::parsep()->symp()->nextId()) {
UINFO(7, " tokenPipelineSym: next id lookup forced under " << look_underp << endl);
// if (debug() >= 7) V3ParseImp::parsep()->symp()->dumpSelf(cout, " -symtree: ");
foundp = look_underp->findIdFlat(*(yylval.strp));
// "consume" it. Must set again if want another token under temp scope
V3ParseImp::parsep()->symp()->nextId(nullptr);
} else {
UINFO(7, " tokenPipelineSym: find upward "
<< V3ParseImp::parsep()->symp()->symCurrentp() << " for '"
<< *(yylval.strp) << "'" << endl);
// if (debug()>=9) V3ParseImp::parsep()->symp()->symCurrentp()->dumpSelf(cout,
// " -findtree: ", true);
foundp = V3ParseImp::parsep()->symp()->symCurrentp()->findIdFallback(*(yylval.strp));
}
if (!foundp && !m_afterColonColon) { // Check if the symbol can be found in std
// The following keywords from this file are hardcoded for detection in the parser:
// "mailbox", "process", "randomize", "semaphore", "std"
AstPackage* const stdpkgp = v3Global.rootp()->stdPackagep();
if (stdpkgp) {
VSymEnt* const stdsymp = stdpkgp->user4u().toSymEnt();
foundp = stdsymp->findIdFallback(*(yylval.strp));
}
}
if (foundp) {
AstNode* const scp = foundp->nodep();
yylval.scp = scp;
UINFO(7, " tokenPipelineSym: Found " << scp << endl);
if (token == yaID__LEX) { // i.e. not yaID__CC
token = yaID__ETC;
}
} else { // Not found
yylval.scp = nullptr;
if (token == yaID__LEX) token = yaID__ETC;
}
if (token == yaID__LEX) token = yaID__ETC;
}
m_afterColonColon = token == yP_COLONCOLON;
yylval.token = token;
@ -744,7 +701,6 @@ int V3ParseImp::tokenToBison() {
m_bisonLastFileline = yylval.fl;
m_tokenLastBison = yylval;
// yylval.scp = nullptr; // Symbol table not yet needed - no packages
if (debug() >= 6 || debugFlex() >= 6
|| debugBison() >= 6) { // --debugi-flex and --debugi-bison
cout << "tokenToBison " << yylval << endl;
@ -776,8 +732,8 @@ std::ostream& operator<<(std::ostream& os, const V3ParseBisonYYSType& rhs) {
//======================================================================
// V3Parse functions
V3Parse::V3Parse(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* symp) {
m_impp = new V3ParseImp{rootp, filterp, symp};
V3Parse::V3Parse(AstNetlist* rootp, VInFilter* filterp) {
m_impp = new V3ParseImp{rootp, filterp};
}
V3Parse::~V3Parse() { //
VL_DO_CLEAR(delete m_impp, m_impp = nullptr);

View File

@ -20,11 +20,11 @@
#include "config_build.h"
#include "verilatedos.h"
#include "V3Ast.h"
#include "V3Error.h"
#include "V3FileLine.h"
#include "V3Global.h"
#include "V3Parse.h"
#include "V3ParseSym.h"
#include <algorithm>
#include <deque>
@ -108,7 +108,6 @@ struct VMemberQualifiers final {
struct V3ParseBisonYYSType final {
FileLine* fl;
AstNode* scp; // Symbol table scope for future lookups
int token; // Read token, aka tok
VBaseOverride baseOverride;
bool flag = false; // Passed up some rules
@ -142,7 +141,6 @@ class V3ParseImp final {
// MEMBERS
AstNetlist* const m_rootp; // Root of the design
VInFilter* const m_filterp; // Reading filter
V3ParseSym* m_symp; // Symbol table
V3Lexer* m_lexerp = nullptr; // Current FlexLexer
static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based
@ -269,27 +267,13 @@ public:
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf, max_size); }
//==== Symbol tables
V3ParseSym* symp() { return m_symp; }
AstPackage* unitPackage(FileLine* /*fl*/) {
// Find one made earlier?
const VSymEnt* const rootSymp
= symp()->symRootp()->findIdFlat(AstPackage::dollarUnitName());
AstPackage* pkgp;
if (!rootSymp) {
pkgp = parsep()->rootp()->dollarUnitPkgAddp();
symp()->reinsert(pkgp, symp()->symRootp()); // Don't push/pop scope as they're global
} else {
pkgp = VN_AS(rootSymp->nodep(), Package);
}
return pkgp;
}
AstPackage* unitPackage(FileLine* /*fl*/) { return parsep()->rootp()->dollarUnitPkgAddp(); }
public:
// CONSTRUCTORS
V3ParseImp(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* parserSymp)
V3ParseImp(AstNetlist* rootp, VInFilter* filterp)
: m_rootp{rootp}
, m_filterp{filterp}
, m_symp{parserSymp} {
, m_filterp{filterp} {
m_lexKwdLast = stateVerilogRecent();
m_timeLastUnit = v3Global.opt.timeDefaultUnit();
}

View File

@ -1,181 +0,0 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Common header between parser and lex
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2009-2025 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.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
#ifndef VERILATOR_V3PARSESYM_H_
#define VERILATOR_V3PARSESYM_H_
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3FileLine.h"
#include "V3Global.h"
#include "V3SymTable.h"
#include <deque>
#include <vector>
//######################################################################
// Symbol table for parsing
class V3ParseSym final {
// TYPES
using SymStack = std::vector<VSymEnt*>;
private:
// MEMBERS
static int s_anonNum; // Number of next anonymous object (parser use only)
VSymGraph m_syms; // Graph of symbol tree
VSymEnt* m_symTableNextId = nullptr; // Symbol table for next lexer lookup (parser use only)
VSymEnt* m_symCurrentp = nullptr; // Active symbol table for additions/lookups
std::vector<VSymEnt*> m_sympStack; // Stack of upper nodes with pending symbol tables
public:
// CONSTRUCTORS
explicit V3ParseSym(AstNetlist* rootp)
: m_syms{rootp} {
s_anonNum = 0; // Number of next anonymous object
pushScope(findNewTable(rootp));
m_symCurrentp = symCurrentp();
}
~V3ParseSym() = default;
private:
// METHODS
VL_DEFINE_DEBUG_FUNCTIONS;
static VSymEnt* getTable(AstNode* nodep) {
UASSERT_OBJ(nodep->user4p(), nodep, "Current symtable not found");
return nodep->user4u().toSymEnt();
}
public:
VSymEnt* nextId() const { return m_symTableNextId; }
VSymEnt* symCurrentp() const { return m_symCurrentp; }
VSymEnt* symRootp() const { return m_syms.rootp(); }
VSymEnt* findNewTable(AstNode* nodep) {
if (!nodep->user4p()) {
VSymEnt* const symsp = new VSymEnt{&m_syms, nodep};
nodep->user4p(symsp);
}
return getTable(nodep);
}
void nextId(AstNode* entp) {
if (entp) {
UINFO(9, "symTableNextId under " << entp << "-" << entp->type().ascii() << endl);
m_symTableNextId = getTable(entp);
} else {
UINFO(9, "symTableNextId under nullptr" << endl);
m_symTableNextId = nullptr;
}
}
void reinsert(AstNode* nodep, VSymEnt* parentp = nullptr) {
reinsert(nodep, parentp, nodep->name());
}
// cppcheck-suppress passedByValue
void reinsert(AstNode* nodep, VSymEnt* parentp, string name) {
if (!parentp) parentp = symCurrentp();
if (name == "") { // New name with space in name so can't collide with users
name = " anon"s + nodep->type().ascii() + cvtToStr(++s_anonNum);
}
parentp->reinsert(name, findNewTable(nodep));
}
void pushNew(AstNode* nodep) { pushNewUnder(nodep, nullptr); }
void pushNewUnder(AstNode* nodep, VSymEnt* parentp) {
if (!parentp) parentp = symCurrentp();
VSymEnt* const symp
= findNewTable(nodep); // Will set user4p, which is how we connect table to node
symp->fallbackp(parentp);
reinsert(nodep, parentp);
pushScope(symp);
}
void pushNewUnderNodeOrCurrent(AstNode* nodep, AstNode* parentp) {
if (parentp) {
pushNewUnder(nodep, findNewTable(parentp));
} else {
pushNewUnder(nodep, nullptr);
}
}
void pushScope(VSymEnt* symp) {
m_sympStack.push_back(symp);
m_symCurrentp = symp;
}
void popScope(AstNode* nodep) {
if (VL_UNCOVERABLE(symCurrentp()->nodep() != nodep)) { // LCOV_EXCL_START
if (debug()) {
showUpward();
dumpSelf(std::cout, "-mism: ");
}
nodep->v3fatalSrc("Symbols suggest ending " << symCurrentp()->nodep()->prettyTypeName()
<< " but parser thinks ending "
<< nodep->prettyTypeName());
return;
} // LCOV_EXCL_STOP
m_sympStack.pop_back();
UASSERT_OBJ(!m_sympStack.empty(), nodep, "symbol stack underflow");
m_symCurrentp = m_sympStack.back();
}
void showUpward() { // LCOV_EXCL_START
UINFO(1, "ParseSym Stack:\n");
for (VSymEnt* const symp : vlstd::reverse_view(m_sympStack)) {
UINFO(1, " " << symp->nodep() << endl);
}
UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl);
} // LCOV_EXCL_STOP
void dumpSelf(std::ostream& os, const string& indent = "") { m_syms.dumpSelf(os, indent); }
AstNode* findEntUpward(const string& name) const {
// Lookup the given string as an identifier, return type of the id, scanning upward
VSymEnt* const foundp = symCurrentp()->findIdFallback(name);
if (foundp) {
return foundp->nodep();
} else {
return nullptr;
}
}
void importExtends(AstNode* classp) {
// Import from package::id_or_star to this
VSymEnt* const symp = getTable(classp);
UASSERT_OBJ(symp, classp, // Internal problem, because we earlier found it
"Extends class package not found");
// Walk old sym table and reinsert into current table
// We let V3LinkDot report the error instead of us
symCurrentp()->importFromClass(&m_syms, symp);
}
void importItem(AstNode* packagep, const string& id_or_star) {
// Import from package::id_or_star to this
VSymEnt* const symp = getTable(packagep);
UASSERT_OBJ(symp, packagep, // Internal problem, because we earlier found it
"Import package not found");
// Walk old sym table and reinsert into current table
// We let V3LinkDot report the error instead of us
symCurrentp()->importFromPackage(&m_syms, symp, id_or_star);
}
void exportItem(AstNode* packagep, const string& id_or_star) {
// Export from this the remote package::id_or_star
VSymEnt* const symp = getTable(packagep);
UASSERT_OBJ(symp, packagep, // Internal problem, because we earlier found it
"Export package not found");
symCurrentp()->exportFromPackage(&m_syms, symp, id_or_star);
}
void exportStarStar() {
// Export *::* from remote packages
symCurrentp()->exportStarStar(&m_syms);
}
};
#endif // Guard

View File

@ -78,7 +78,6 @@
#include "V3Order.h"
#include "V3Os.h"
#include "V3Param.h"
#include "V3ParseSym.h"
#include "V3PreShell.h"
#include "V3Premit.h"
#include "V3ProtectLib.h"

View File

@ -73,7 +73,6 @@
// Statics (for here only)
#define PARSEP V3ParseImp::parsep()
#define SYMP PARSEP->symp()
#define GRAMMARP V3ParseGrammar::singletonp()
class V3ParseGrammar {
@ -173,7 +172,6 @@ public:
// As nettypes are unsupported, we just alias to logic
AstTypedef* const nodep = new AstTypedef{fl, name, nullptr, VFlagChildDType{},
new AstBasicDType{fl, VFlagLogicPacked{}, 1}};
SYMP->reinsert(nodep);
PARSEP->tagNodep(nodep);
return nodep;
}
@ -181,13 +179,11 @@ public:
AstNodeRange* rangep) {
AstTypedef* const nodep = new AstTypedef{fl, name, attrsp, VFlagChildDType{},
GRAMMARP->createArray(basep, rangep, false)};
SYMP->reinsert(nodep);
PARSEP->tagNodep(nodep);
return nodep;
}
AstNode* createTypedefFwd(FileLine* fl, const string& name) {
AstTypedefFwd* const nodep = new AstTypedefFwd{fl, name};
SYMP->reinsert(nodep);
PARSEP->tagNodep(nodep);
return nodep;
}
@ -1241,7 +1237,6 @@ package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE
{ $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtsp($2);
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>4, $1, $4); }
;
@ -1259,8 +1254,7 @@ packageFront<nodeModulep>:
$$->lifetime($2);
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$); }
PARSEP->rootp()->addModulesp($$); }
;
package_itemListE<nodep>: // IEEE: [{ package_item }]
@ -1338,14 +1332,7 @@ package_import_itemList<nodep>:
package_import_item<nodep>: // ==IEEE: package_import_item
idCC/*package_identifier*/ yP_COLONCOLON package_import_itemObj
{
if (!VN_IS($<scp>1, Package)) {
$$ = nullptr;
$<fl>1->v3error("Importing from missing package '" << *$<strp>1 << "'");
} else {
$$ = new AstPackageImport{$<fl>2, *$<strp>1, *$3};
SYMP->importItem($<scp>1, *$3);
} }
{ $$ = new AstPackageImport{$<fl>1, *$<strp>1, *$3}; }
;
package_import_itemObj<strp>: // IEEE: part of package_import_item
@ -1355,7 +1342,7 @@ package_import_itemObj<strp>: // IEEE: part of package_import_item
package_export_declaration<nodep>: // IEEE: package_export_declaration
yEXPORT '*' yP_COLONCOLON '*' ';'
{ $$ = new AstPackageExportStarStar{$<fl>2}; SYMP->exportStarStar(); }
{ $$ = new AstPackageExportStarStar{$<fl>2}; }
| yEXPORT package_export_itemList ';' { $$ = $2; }
;
@ -1366,8 +1353,7 @@ package_export_itemList<nodep>:
package_export_item<nodep>: // ==IEEE: package_export_item
idCC yP_COLONCOLON package_import_itemObj
{ $$ = new AstPackageExport{$<fl>3, *$<strp>1, *$3};
if ($<scp>1) SYMP->exportItem($<scp>1, *$3); }
{ $$ = new AstPackageExport{$<fl>3, *$<strp>1, *$3}; }
;
//**********************************************************************
@ -1383,7 +1369,6 @@ module_declaration: // ==IEEE: module_declaration
if ($2) $1->addStmtsp($2);
if ($3) $1->addStmtsp($3);
if ($5) $1->addStmtsp($5);
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7, $1, $7); }
| udpFront portsStarE ';'
/*cont*/ module_itemListE yENDPRIMITIVE endLabelE
@ -1391,7 +1376,6 @@ module_declaration: // ==IEEE: module_declaration
if ($2) $1->addStmtsp($2);
if ($4) $1->addStmtsp($4);
GRAMMARP->m_tracingParse = true;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>6, $1, $6); }
//
| yEXTERN modFront parameter_port_listE portsStarE ';'
@ -1408,8 +1392,7 @@ modFront<nodeModulep>:
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
$$->unconnectedDrive(PARSEP->unconnectedDrive());
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$); }
PARSEP->rootp()->addModulesp($$); }
| modFront sigAttrScope { $$ = $1; }
;
@ -1430,8 +1413,7 @@ udpFront<nodeModulep>:
$$->modTrace(false);
$$->addStmtsp(new AstPragma{$<fl>3, VPragmaType::INLINE_MODULE});
GRAMMARP->m_tracingParse = false;
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$); }
PARSEP->rootp()->addModulesp($$); }
;
parameter_value_assignmentInstE<pinp>: // IEEE: [ parameter_value_assignment ] for instance
@ -1673,9 +1655,9 @@ port_declNetE: // IEEE: part of port_declaration, optional net
portSig<nodep>:
id/*port*/
{ $$ = new AstPort{$<fl>1, PINNUMINC(), *$1}; SYMP->reinsert($$); }
{ $$ = new AstPort{$<fl>1, PINNUMINC(), *$1}; }
| idSVKwd
{ $$ = new AstPort{$<fl>1, PINNUMINC(), *$1}; SYMP->reinsert($$); }
{ $$ = new AstPort{$<fl>1, PINNUMINC(), *$1}; }
;
//**********************************************************************
@ -1688,8 +1670,7 @@ interface_declaration: // IEEE: interface_declaration + interface_nonan
{ if ($2) $1->addStmtsp($2);
if ($3) $1->addStmtsp($3);
if ($5) $1->addStmtsp($5);
$1->hasParameterList($<flag>2);
SYMP->popScope($1); }
$1->hasParameterList($<flag>2); }
| yEXTERN intFront parameter_port_listE portsStarE ';'
{ BBUNSUP($<fl>1, "Unsupported: extern interface"); }
;
@ -1699,8 +1680,7 @@ intFront<nodeModulep>:
{ $$ = new AstIface{$<fl>3, *$3};
$$->inLibrary(true);
$$->lifetime($2);
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$); }
PARSEP->rootp()->addModulesp($$); }
| intFront sigAttrScope { $$ = $1; }
;
@ -1777,11 +1757,9 @@ program_declaration: // IEEE: program_declaration + program_nonansi_h
if ($2) $1->addStmtsp($2);
if ($3) $1->addStmtsp($3);
if ($5) $1->addStmtsp($5);
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7, $1, $7); }
| yEXTERN pgmFront parameter_port_listE portsStarE ';'
{ BBUNSUP($<fl>1, "Unsupported: extern program");
SYMP->popScope($2); }
{ BBUNSUP($<fl>1, "Unsupported: extern program"); }
;
pgmFront<nodeModulep>:
@ -1791,8 +1769,7 @@ pgmFront<nodeModulep>:
$$->inLibrary(PARSEP->inLibrary() || $$->fileline()->celldefineOn());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$); }
PARSEP->rootp()->addModulesp($$); }
;
program_itemListE<nodep>: // ==IEEE: [{ program_item }]
@ -2303,13 +2280,13 @@ type_referenceEq<nodeExprp>: // IEEE: type_reference (as an ==/!== ex
struct_unionDecl<nodeUOrStructDTypep>: // IEEE: part of data_type
// // packedSigningE is NOP for unpacked
ySTRUCT packedSigningE '{'
/*mid*/ { $<nodeUOrStructDTypep>$ = new AstStructDType{$1, $2}; SYMP->pushNew($<nodeUOrStructDTypep>$); }
/*mid*/ { $<nodeUOrStructDTypep>$ = new AstStructDType{$1, $2}; }
/*cont*/ struct_union_memberListEnd
{ $$ = $<nodeUOrStructDTypep>4; $$->addMembersp($5); SYMP->popScope($$); }
{ $$ = $<nodeUOrStructDTypep>4; $$->addMembersp($5); }
| yUNION taggedSoftE packedSigningE '{'
/*mid*/ { $<nodeUOrStructDTypep>$ = new AstUnionDType{$1, $2, $3}; SYMP->pushNew($<nodeUOrStructDTypep>$); }
/*mid*/ { $<nodeUOrStructDTypep>$ = new AstUnionDType{$1, $2, $3}; }
/*cont*/ struct_union_memberListEnd
{ $$ = $<nodeUOrStructDTypep>5; $$->addMembersp($6); SYMP->popScope($$); }
{ $$ = $<nodeUOrStructDTypep>5; $$->addMembersp($6); }
;
struct_union_memberListEnd<memberDTypep>: // IEEE: { struct_union_member } '}'
@ -3557,67 +3534,67 @@ seq_block<nodep>: // ==IEEE: seq_block
// // So need AstBegin's even if unnamed to scope variables down
seq_blockFront blockDeclStmtListE yEND endLabelE
{ $$ = $1; $1->addStmtsp($2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
;
seq_blockPreId<nodep>: // IEEE: seq_block, but called with leading ID
seq_blockFrontPreId blockDeclStmtListE yEND endLabelE
{ $$ = $1; $1->addStmtsp($2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
;
par_block<nodep>: // ==IEEE: par_block
par_blockFront blockDeclStmtListE yJOIN endLabelE
{ $$ = $1; $1->joinType(VJoinType::JOIN);
V3ParseGrammar::addForkStmtsp($1, $2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
| par_blockFront blockDeclStmtListE yJOIN_ANY endLabelE
{ $$ = $1; $1->joinType(VJoinType::JOIN_ANY);
V3ParseGrammar::addForkStmtsp($1, $2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
| par_blockFront blockDeclStmtListE yJOIN_NONE endLabelE
{ $$ = $1; $1->joinType(VJoinType::JOIN_NONE);
V3ParseGrammar::addForkStmtsp($1, $2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
;
par_blockPreId<nodep>: // ==IEEE: par_block but called with leading ID
par_blockFrontPreId blockDeclStmtListE yJOIN endLabelE
{ $$ = $1; $1->joinType(VJoinType::JOIN);
V3ParseGrammar::addForkStmtsp($1, $2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
| par_blockFrontPreId blockDeclStmtListE yJOIN_ANY endLabelE
{ $$ = $1; $1->joinType(VJoinType::JOIN_ANY);
V3ParseGrammar::addForkStmtsp($1, $2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
| par_blockFrontPreId blockDeclStmtListE yJOIN_NONE endLabelE
{ $$ = $1; $1->joinType(VJoinType::JOIN_NONE);
V3ParseGrammar::addForkStmtsp($1, $2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
GRAMMARP->endLabel($<fl>4, $1, $4); }
;
seq_blockFront<beginp>: // IEEE: part of seq_block
yBEGIN
{ $$ = new AstBegin{$1, "", nullptr}; SYMP->pushNew($$); }
{ $$ = new AstBegin{$1, "", nullptr}; }
| yBEGIN ':' idAny/*new-block_identifier*/
{ $$ = new AstBegin{$<fl>3, *$3, nullptr}; SYMP->pushNew($$); }
{ $$ = new AstBegin{$<fl>3, *$3, nullptr}; }
;
par_blockFront<forkp>: // IEEE: part of par_block
yFORK
{ $$ = new AstFork{$1, "", nullptr}; SYMP->pushNew($$); }
{ $$ = new AstFork{$1, "", nullptr}; }
| yFORK ':' idAny/*new-block_identifier*/
{ $$ = new AstFork{$<fl>3, *$3, nullptr}; SYMP->pushNew($$); }
{ $$ = new AstFork{$<fl>3, *$3, nullptr}; }
;
seq_blockFrontPreId<beginp>: // IEEE: part of seq_block/stmt with leading id
id/*block_identifier*/ yP_COLON__BEGIN yBEGIN
{ $$ = new AstBegin{$3, *$1, nullptr}; SYMP->pushNew($$); }
{ $$ = new AstBegin{$3, *$1, nullptr}; }
;
par_blockFrontPreId<forkp>: // IEEE: part of par_block/stmt with leading id
id/*block_identifier*/ yP_COLON__FORK yFORK
{ $$ = new AstFork{$3, *$1, nullptr}; SYMP->pushNew($$); }
{ $$ = new AstFork{$3, *$1, nullptr}; }
;
@ -4617,7 +4594,7 @@ list_of_argumentsE<nodeExprp>: // IEEE: [list_of_arguments]
task_declaration<nodeFTaskp>: // ==IEEE: task_declaration
yTASK dynamic_override_specifiersE lifetimeE taskId tfGuts yENDTASK endLabelE
{ $$ = $4; $$->addStmtsp($5); SYMP->popScope($$);
{ $$ = $4; $$->addStmtsp($5);
$$->baseOverride($2);
$$->lifetime($3);
GRAMMARP->endLabel($<fl>7, $$, $7); }
@ -4625,9 +4602,9 @@ task_declaration<nodeFTaskp>: // ==IEEE: task_declaration
task_prototype<nodeFTaskp>: // ==IEEE: task_prototype
yTASK dynamic_override_specifiersE taskId '(' tf_port_listE ')'
{ $$ = $3; $$->addStmtsp($5); $$->prototype(true); SYMP->popScope($$); }
{ $$ = $3; $$->addStmtsp($5); $$->prototype(true); }
| yTASK dynamic_override_specifiersE taskId
{ $$ = $3; $$->prototype(true); SYMP->popScope($$); }
{ $$ = $3; $$->prototype(true); }
;
function_declaration<nodeFTaskp>: // IEEE: function_declaration + function_body_declaration
@ -4635,30 +4612,28 @@ function_declaration<nodeFTaskp>: // IEEE: function_declaration + function
{ $$ = $4; $4->attrIsolateAssign($5); $$->addStmtsp($6);
$$->baseOverride($2);
$$->lifetime($3);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>8, $$, $8); }
| yFUNCTION dynamic_override_specifiersE lifetimeE funcIdNew funcIsolateE tfNewGuts yENDFUNCTION endLabelE
{ $$ = $4; $4->attrIsolateAssign($5); $$->addStmtsp($6);
$$->baseOverride($2);
$$->lifetime($3);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>8, $$, $8); }
;
function_prototype<nodeFTaskp>: // IEEE: function_prototype
yFUNCTION dynamic_override_specifiersE funcId '(' tf_port_listE ')'
{ $$ = $3; $$->addStmtsp($5); $$->prototype(true); SYMP->popScope($$); }
{ $$ = $3; $$->addStmtsp($5); $$->prototype(true); }
| yFUNCTION dynamic_override_specifiersE funcId
{ $$ = $3; $$->prototype(true); SYMP->popScope($$); }
{ $$ = $3; $$->prototype(true); }
;
class_constructor_prototype<nodeFTaskp>: // ==IEEE: class_constructor_prototype
// // IEEE has no dynamic_override_specifiersE,
// // but required to avoid conflicts, so we must check after parsing
yFUNCTION dynamic_override_specifiersE funcIdNew '(' class_constructor_arg_listE ')' ';'
{ $$ = $3; $$->addStmtsp($5); $$->prototype(true); SYMP->popScope($$); }
{ $$ = $3; $$->addStmtsp($5); $$->prototype(true); }
| yFUNCTION dynamic_override_specifiersE funcIdNew ';'
{ $$ = $3; $$->prototype(true); SYMP->popScope($$); }
{ $$ = $3; $$->prototype(true); }
;
funcIsolateE<cint>:
@ -4684,19 +4659,16 @@ lifetime<lifetime>: // ==IEEE: lifetime
taskId<nodeFTaskp>:
id
{ $$ = new AstTask{$<fl>$, *$1, nullptr};
SYMP->pushNewUnderNodeOrCurrent($$, nullptr); }
{ $$ = new AstTask{$<fl>$, *$1, nullptr}; }
//
| id/*interface_identifier*/ '.' idAny
{ $$ = new AstTask{$<fl>$, *$3, nullptr};
BBUNSUP($2, "Unsupported: Out of block function declaration");
SYMP->pushNewUnderNodeOrCurrent($$, nullptr); }
BBUNSUP($2, "Unsupported: Out of block function declaration"); }
//
| packageClassScope id
{ $$ = new AstTask{$<fl>$, *$2, nullptr};
$$->classOrPackagep($1);
$$->classMethod(true);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>1); }
$$->classMethod(true); }
;
funcId<nodeFTaskp>: // IEEE: function_data_type_or_implicit + part of function_body_declaration
@ -4705,30 +4677,24 @@ funcId<nodeFTaskp>: // IEEE: function_data_type_or_implicit + part o
// // implicit_type:empty vs data_type:ID
/**/ fIdScoped
{ $$ = $1;
$$->fvarp(new AstBasicDType{$<fl>1, LOGIC_IMPLICIT});
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>1); }
$$->fvarp(new AstBasicDType{$<fl>1, LOGIC_IMPLICIT}); }
| signingE rangeList fIdScoped
{ $$ = $3;
$$->fvarp(GRAMMARP->addRange(new AstBasicDType{$<fl>3, LOGIC_IMPLICIT, $1}, $2, true));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>3); }
$$->fvarp(GRAMMARP->addRange(new AstBasicDType{$<fl>3, LOGIC_IMPLICIT, $1}, $2, true)); }
| signing fIdScoped
{ $$ = $2;
$$->fvarp(new AstBasicDType{$<fl>2, LOGIC_IMPLICIT, $1});
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>2); }
$$->fvarp(new AstBasicDType{$<fl>2, LOGIC_IMPLICIT, $1}); }
| data_typeNoRef fIdScoped
{ $$ = $2;
$$->fvarp($1);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>2); }
$$->fvarp($1); }
| packageClassScopeE idInstType packed_dimensionListE fIdScoped
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, $1, nullptr};
$$ = $4;
$$->fvarp(GRAMMARP->createArray(refp, $3, true));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>4); }
$$->fvarp(GRAMMARP->createArray(refp, $3, true)); }
| packageClassScopeE idInstType parameter_value_assignmentClass packed_dimensionListE fIdScoped
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, $1, $3};
$$ = $5;
$$->fvarp(GRAMMARP->createArray(refp, $4, true));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>5); }
$$->fvarp(GRAMMARP->createArray(refp, $4, true)); }
// // To verilator tasks are the same as void functions (we separately detect time passing)
| yVOID taskId
{ $$ = $2; }
@ -4737,36 +4703,30 @@ funcId<nodeFTaskp>: // IEEE: function_data_type_or_implicit + part o
funcIdNew<nodeFTaskp>: // IEEE: from class_constructor_declaration
yNEW__ETC
{ $$ = new AstFunc{$<fl>1, "new", nullptr, nullptr};
$$->isConstructor(true);
SYMP->pushNewUnder($$, nullptr); }
$$->isConstructor(true); }
| yNEW__PAREN
{ $$ = new AstFunc{$<fl>1, "new", nullptr, nullptr};
$$->isConstructor(true);
SYMP->pushNewUnder($$, nullptr); }
$$->isConstructor(true); }
| packageClassScopeNoId yNEW__PAREN
{ $$ = new AstFunc{$<fl>2, "new", nullptr, nullptr};
$$->classOrPackagep($1);
$$->isConstructor(true);
$$->classMethod(true);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>1); }
$$->classMethod(true); }
;
fIdScoped<funcp>: // IEEE: part of function_body_declaration/task_body_declaration
// // IEEE: [ interface_identifier '.' | class_scope ] function_identifier
id
{ $<fl>$ = $<fl>1;
$<scp>$ = nullptr;
$$ = new AstFunc{$<fl>$, *$1, nullptr, nullptr}; }
//
| id/*interface_identifier*/ '.' idAny
{ $<fl>$ = $<fl>1;
$<scp>$ = nullptr;
$$ = new AstFunc{$<fl>$, *$1, nullptr, nullptr};
BBUNSUP($2, "Unsupported: Out of block function declaration"); }
//
| packageClassScope id
{ $<fl>$ = $<fl>1;
$<scp>$ = $<scp>1;
$$ = new AstFunc{$<fl>$, *$2, nullptr, nullptr};
$$->classMethod(true);
$$->classOrPackagep($1); }
@ -4908,9 +4868,7 @@ dpi_import_export<nodep>: // ==IEEE: dpi_import_export
$5->dpiContext($3 == iprop_CONTEXT);
$5->dpiPure($3 == iprop_PURE);
$5->dpiImport(true);
GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true);
if ($$->prettyName()[0]=='$') SYMP->reinsert($$, nullptr, $$->prettyName()); // For $SysTF overriding
SYMP->reinsert($$); }
GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true); }
| yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE task_prototype ';'
{ $$ = $5;
if (*$4 != "") $5->cname(*$4);
@ -4918,9 +4876,7 @@ dpi_import_export<nodep>: // ==IEEE: dpi_import_export
$5->dpiPure($3 == iprop_PURE);
$5->dpiImport(true);
$5->dpiTask(true);
GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true);
if ($$->prettyName()[0]=='$') SYMP->reinsert($$, nullptr, $$->prettyName()); // For $SysTF overriding
SYMP->reinsert($$); }
GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true); }
| yEXPORT yaSTRING dpi_importLabelE yFUNCTION idAny ';'
{ $$ = new AstDpiExport{$<fl>5, *$5, *$3};
GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true); }
@ -5478,21 +5434,17 @@ stream_expressionOrDataType<nodep>: // IEEE: from streaming_concatenation
letId<letp>: // IEEE: pert of let_declaration
idAny/*let_identifieer*/
{ $<fl>$ = $<fl>1;
$<scp>$ = nullptr;
$$ = new AstLet{$<fl>$, *$1};
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>$); }
$$ = new AstLet{$<fl>$, *$1}; }
;
let_declaration<letp>: // IEEE: let_declaration
yLET letId '=' expr ';'
{ $$ = $2;
$$->addStmtsp(new AstStmtExpr{$1, $4});
SYMP->popScope($2); }
$$->addStmtsp(new AstStmtExpr{$1, $4}); }
| yLET letId '(' let_port_listE ')' '=' expr ';'
{ $$ = $2;
$$->addStmtsp(new AstStmtExpr{$1, $7});
$$->addStmtsp($4);
SYMP->popScope($2); }
$$->addStmtsp($4); }
;
let_port_listE<nodep>: // IEEE: [ let_port_list ]
@ -6316,7 +6268,6 @@ property_declaration<nodeFTaskp>: // ==IEEE: property_declaration
{ $$ = $1;
$$->addStmtsp($2);
$$->addStmtsp($4);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>6, $$, $6);
GRAMMARP->m_insideProperty = false;
GRAMMARP->m_typedPropertyPort = false; }
@ -6325,8 +6276,7 @@ property_declaration<nodeFTaskp>: // ==IEEE: property_declaration
property_declarationFront<nodeFTaskp>: // IEEE: part of property_declaration
yPROPERTY idAny/*property_identifier*/
{ $$ = new AstProperty{$<fl>2, *$2, nullptr};
GRAMMARP->m_insideProperty = true;
SYMP->pushNewUnderNodeOrCurrent($$, nullptr); }
GRAMMARP->m_insideProperty = true; }
;
property_port_listE<nodep>: // IEEE: [ ( [ property_port_list ] ) ]
@ -6404,15 +6354,13 @@ sequence_declaration<nodeFTaskp>: // ==IEEE: sequence_declaration
{ $$ = $1;
$$->addStmtsp($2);
$$->addStmtsp($4);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>6, $$, $6); }
;
sequence_declarationFront<nodeFTaskp>: // IEEE: part of sequence_declaration
ySEQUENCE idAny/*new_sequence*/
{ BBUNSUP($1, "Unsupported: sequence");
$$ = new AstProperty{$<fl>2, *$2, nullptr};
SYMP->pushNewUnderNodeOrCurrent($$, nullptr); }
$$ = new AstProperty{$<fl>2, *$2, nullptr}; }
;
sequence_port_listE<nodep>: // IEEE: [ ( [ sequence_port_list ] ) ]
@ -6765,28 +6713,24 @@ covergroup_declaration<nodep>: // ==IEEE: covergroup_declaration
/*cont*/ coverage_spec_or_optionListE
/*cont*/ yENDGROUP endLabelE
{ $$ = $1;
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>6, $1, $6); }
| covergroup_declarationFront '(' tf_port_listE ')'
/*cont*/ coverage_eventE ';' coverage_spec_or_optionListE
/*cont*/ yENDGROUP endLabelE
{ $$ = $1;
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>9, $1, $9); }
// // IEEE 1800-2023 added:
| covergroup_declarationFront yEXTENDS idAny/*covergroup_identifier*/
/*cont*/ ';' coverage_spec_or_optionListE
/*cont*/ yENDGROUP endLabelE
{ $$ = $1;
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>7, $1, $7); }
;
covergroup_declarationFront<classp>: // IEEE: part of covergroup_declaration
yCOVERGROUP idAny
{ $$ = new AstClass{$<fl>2, *$2};
BBCOVERIGN($<fl>1, "Ignoring unsupported: covergroup");
SYMP->pushNew($<constraintp>$); }
BBCOVERIGN($<fl>1, "Ignoring unsupported: covergroup"); }
;
cgexpr<nodeExprp>: // IEEE-2012: covergroup_expression, before that just expression
@ -7077,7 +7021,6 @@ rs_productionList<nodep>: // IEEE: rs_production+
rs_production<nodep>: // ==IEEE: rs_production
rs_productionFront ':' rs_ruleList ';'
{ // TODO makes a function, probably want a new Ast type instead
SYMP->popScope($$);
$$ = nullptr; BBUNSUP($<fl>2, "Unsupported: randsequence production"); }
;
@ -7185,7 +7128,6 @@ checker_declaration<nodeModulep>: // ==IEEE: part of checker_declaration
$1->modTrace(GRAMMARP->allTracingOn($1->fileline()));
if ($2) $1->addStmtsp($2);
if ($4) $1->addStmtsp($4);
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>6, $1, $6); }
;
@ -7194,8 +7136,7 @@ checkerFront<nodeModulep>: // IEEE: part of checker_declaration
{ $$ = new AstModule{$<fl>2, *$2, AstModule::Checker{}};
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
$$->unconnectedDrive(PARSEP->unconnectedDrive());
SYMP->pushNew($$); }
$$->unconnectedDrive(PARSEP->unconnectedDrive()); }
| checkerFront sigAttrScope { $$ = $1; }
;
@ -7311,14 +7252,12 @@ class_declaration<nodep>: // ==IEEE: part of class_declaration
classFront parameter_port_listE classExtendsE classImplementsE ';'
/*mid*/ { // Allow resolving types declared in base extends class
$1->hasParameterList($<flag>2);
if ($<scp>3) SYMP->importExtends($<scp>3);
}
/*cont*/ class_itemListEnd endLabelE
{ $$ = $1; $1->addMembersp($2);
$1->addExtendsp($3);
$1->addExtendsp($4);
$1->addMembersp($7);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>8, $1, $8); }
;
@ -7328,14 +7267,12 @@ classFront<classp>: // IEEE: part of class_declaration
{ $$ = new AstClass{$2, *$5};
$$->baseOverride($3);
$$->isVirtual($1);
SYMP->pushNew($<classp>$);
v3Global.setHasClasses(); }
// // IEEE: part of interface_class_declaration
// // IEEE 1800-2023: lifetimeE removed
| yINTERFACE yCLASS idAny/*class_identifier*/
{ $$ = new AstClass{$2, *$3};
$$->isInterfaceClass(true);
SYMP->pushNew($<classp>$);
v3Global.setHasClasses(); }
;
@ -7347,54 +7284,50 @@ classVirtualE<cbool>:
classExtendsE<classExtendsp>: // IEEE: part of class_declaration
// // The classExtendsE rule relies on classFront having the
// // new class scope correct via classFront
/* empty */ { $$ = nullptr; $<scp>$ = nullptr; }
| yEXTENDS classExtendsList { $$ = $2; $<scp>$ = $<scp>2; }
/* empty */ { $$ = nullptr; }
| yEXTENDS classExtendsList { $$ = $2; }
;
classExtendsList<classExtendsp>: // IEEE: part of class_declaration
classExtendsOne { $$ = $1; $<scp>$ = $<scp>1; }
| classExtendsList ',' classExtendsOne { $$ = addNextNull($1, $3); $<scp>$ = $<scp>3; }
classExtendsOne { $$ = $1; }
| classExtendsList ',' classExtendsOne { $$ = addNextNull($1, $3); }
;
classExtendsOne<classExtendsp>: // IEEE: part of class_declaration
class_typeExtImpList
{ $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements};
$<scp>$ = $<scp>1; }
{ $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements}; }
| class_typeExtImpList '(' list_of_argumentsE ')'
{ $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements};
$$->addArgsp($3);
$<scp>$ = $<scp>1; }
$$->addArgsp($3); }
// // IEEE-2023: Added: yEXTENDS class_type '(' yDEFAULT ')'
| class_typeExtImpList '(' yDEFAULT ')'
{ $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements};
BBUNSUP($<fl>2, "Unsupported: 'extends' with 'default'");
$<scp>$ = $<scp>1; }
BBUNSUP($<fl>2, "Unsupported: 'extends' with 'default'"); }
;
classImplementsE<classExtendsp>: // IEEE: part of class_declaration
// // All 1800-2012
/* empty */ { $$ = nullptr; $<scp>$ = nullptr; }
/* empty */ { $$ = nullptr; }
| yIMPLEMENTS
/*mid*/ { GRAMMARP->m_inImplements = true; $<scp>$ = nullptr; }
/*mid*/ { GRAMMARP->m_inImplements = true; }
/*cont*/ classImplementsList
{ $$ = $3; $<scp>$ = $<scp>3;
{ $$ = $3;
GRAMMARP->m_inImplements = false; }
;
classImplementsList<classExtendsp>: // IEEE: part of class_declaration
// // All 1800-2012
classExtendsOne { $$ = $1; $<scp>$ = $<scp>1; }
classExtendsOne { $$ = $1; }
| classImplementsList ',' classExtendsOne
{ $$ = addNextNull($1, $3); $<scp>$ = $<scp>3; }
{ $$ = addNextNull($1, $3); }
;
class_typeExtImpList<nodeExprp>: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]"
// // but allow yaID__aTYPE for extends/implements
// // If you follow the rules down, class_type is really a list via ps_class_identifier
class_typeExtImpOne { $$ = $1; $<scp>$ = $<scp>1; }
class_typeExtImpOne { $$ = $1; }
| class_typeExtImpList yP_COLONCOLON class_typeExtImpOne
{ $$ = new AstDot{$<fl>1, true, $1, $3};
$<scp>$ = $<scp>3; }
{ $$ = new AstDot{$<fl>1, true, $1, $3}; }
;
class_typeExtImpOne<nodeExprp>: // part of IEEE: class_type, where we either get a package_scope component or class
@ -7406,19 +7339,15 @@ class_typeExtImpOne<nodeExprp>: // part of IEEE: class_type, where we either ge
idAny
/*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentClassE
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3};
$<scp>$ = $<scp>1; }
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3}; }
| idCC
/*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentClassE
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3};
$<scp>$ = $<scp>1; }
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $3}; }
//
// // package_sopeIdFollows expanded
| yD_UNIT yP_COLONCOLON
{ $$ = new AstClassOrPackageRef{$<fl>1, "$unit", nullptr, nullptr};
$<scp>$ = nullptr; // No purpose otherwise, every symtab can see root
SYMP->nextId(PARSEP->rootp()); }
{ $$ = new AstClassOrPackageRef{$<fl>1, "$unit", nullptr, nullptr}; }
;
//=========
@ -7429,7 +7358,7 @@ class_typeExtImpOne<nodeExprp>: // part of IEEE: class_type, where we either ge
//=== Below rules assume special scoping per above
packageClassScopeNoId<nodep>: // IEEE: [package_scope] not followed by yaID
packageClassScope { $$ = $1; $<scp>$ = $<scp>1; SYMP->nextId(nullptr); }
packageClassScope { $$ = $1; }
;
packageClassScopeE<nodeExprp>: // IEEE: [package_scope]
@ -7437,8 +7366,8 @@ packageClassScopeE<nodeExprp>: // IEEE: [package_scope]
// // if not needed must use packageClassScopeNoId
// // TODO: To support classes should return generic type, not packagep
// // class_qualifier := [ yLOCAL '::' ] [ implicit_class_handle '.' class_scope ]
/* empty */ { $$ = nullptr; $<scp>$ = nullptr; }
| packageClassScope { $$ = $1; $<scp>$ = $<scp>1; }
/* empty */ { $$ = nullptr; }
| packageClassScope { $$ = $1; }
;
packageClassScope<nodeExprp>: // IEEE: class_scope
@ -7446,12 +7375,11 @@ packageClassScope<nodeExprp>: // IEEE: class_scope
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // In this parser <package_identifier>:: and <class_identifier>:: are indistinguishible
// // This copies <scp> to document it is important
packageClassScopeList { $$ = $1; $<scp>$ = $<scp>1; }
| localNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
packageClassScopeList { $$ = $1; }
| localNextId yP_COLONCOLON { $$ = $1; }
| dollarUnitNextId yP_COLONCOLON { $$ = $1; }
| dollarUnitNextId yP_COLONCOLON packageClassScopeList
{ $$ = new AstDot{$2, true, $1, $3}; $<scp>$ = $<scp>3; }
{ $$ = new AstDot{$2, true, $1, $3}; }
;
packageClassScopeList<nodeExprp>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
@ -7460,9 +7388,9 @@ packageClassScopeList<nodeExprp>: // IEEE: class_type: "id [ parameter_value_a
// // if not needed must use packageClassScopeNoId
// // In this parser <package_identifier>:: and <class_identifier>:: are indistinguishible
// // If you follow the rules down, class_type is really a list via ps_class_identifier
packageClassScopeItem { $$ = $1; $<scp>$ = $<scp>1; }
packageClassScopeItem { $$ = $1; }
| packageClassScopeList packageClassScopeItem
{ $$ = new AstDot{$<fl>2, true, $1, $2}; $<scp>$ = $<scp>2; }
{ $$ = new AstDot{$<fl>2, true, $1, $2}; }
;
packageClassScopeItem<nodeExprp>: // IEEE: package_scope or [package_scope]::[class_scope]
@ -7471,14 +7399,14 @@ packageClassScopeItem<nodeExprp>: // IEEE: package_scope or [package_scope]::[
// // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
// //vv mid rule action needed otherwise we might not have NextId in time to parse the id token
idCC
/*mid*/ { SYMP->nextId($<scp>1); }
/*mid*/ { }
/*cont*/ yP_COLONCOLON
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, nullptr}; $<scp>$ = $<scp>1; }
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, nullptr}; }
//
| idCC parameter_value_assignmentClass
/*mid*/ { SYMP->nextId($<scp>1); } // Change next *after* we handle parameters, not before
/*mid*/ { }
/*cont*/ yP_COLONCOLON
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $2}; $<scp>$ = $<scp>1; }
{ $$ = new AstClassOrPackageRef{$<fl>1, *$1, nullptr, $2}; }
;
dollarUnitNextId<nodeExprp>: // $unit
@ -7486,8 +7414,7 @@ dollarUnitNextId<nodeExprp>: // $unit
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following
yD_UNIT
{ $$ = new AstClassOrPackageRef{$1, "$unit", nullptr, nullptr};
SYMP->nextId(PARSEP->rootp()); }
{ $$ = new AstClassOrPackageRef{$1, "$unit", nullptr, nullptr}; }
;
localNextId<nodeExprp>: // local::
@ -7495,8 +7422,7 @@ localNextId<nodeExprp>: // local::
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following
yLOCAL__COLONCOLON
{ $$ = new AstClassOrPackageRef{$1, "local::", nullptr, nullptr};
/* No SYMP->nextId(...); normal search upward we should find local's vars */ }
{ $$ = new AstClassOrPackageRef{$1, "local::", nullptr, nullptr}; }
;
//^^^=========
@ -7597,22 +7523,21 @@ memberQualOne<qualifiers>: // IEEE: property_qualifier + me
class_constraint<constraintp>: // ==IEEE: class_constraint
// // IEEE: constraint_declaration
constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew constraint_block
{ $$ = $4; $$->isStatic($1); $$->baseOverride($3); $$->addItemsp($5); SYMP->popScope($$); }
{ $$ = $4; $$->isStatic($1); $$->baseOverride($3); $$->addItemsp($5); }
// // IEEE: constraint_prototype + constraint_prototype_qualifier
| constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew ';'
{ $$ = $4; $$->isStatic($1); $$->baseOverride($3);
$$->isExternProto(true); SYMP->popScope($$); }
$$->isExternProto(true); }
| yEXTERN constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew ';'
{ $$ = $5; $$->isStatic($2); $$->baseOverride($4);
$$->isExternProto(true); $$->isExternExplicit(true); SYMP->popScope($$); }
$$->isExternProto(true); $$->isExternExplicit(true); }
| yPURE constraintStaticE yCONSTRAINT constraintIdNew ';'
{ $$ = $4; $$->isKwdPure($1); $$->isStatic($2); SYMP->popScope($4); }
{ $$ = $4; $$->isKwdPure($1); $$->isStatic($2); }
;
constraintIdNew<constraintp>: // IEEE: id part of class_constraint
idAny/*constraint_identifier*/
{ $$ = new AstConstraint{$<fl>1, *$1, nullptr};
SYMP->pushNewUnderNodeOrCurrent($$, nullptr); }
{ $$ = new AstConstraint{$<fl>1, *$1, nullptr}; }
;
constraint_block<nodep>: // ==IEEE: constraint_block
@ -7711,7 +7636,7 @@ dist_item<distItemp>: // ==IEEE: dist_item + dist_weight
extern_constraint_declaration<constraintp>: // ==IEEE: extern_constraint_declaration
constraintStaticE yCONSTRAINT dynamic_override_specifiersE packageClassScopeE constraintIdNew constraint_block
{ $$ = $5; $$->isStatic($1); $$->isExternDef(true);
$$->baseOverride($3); $$->classOrPackagep($4); $$->addItemsp($6); SYMP->popScope($5); }
$$->baseOverride($3); $$->classOrPackagep($4); $$->addItemsp($6); }
;
constraintStaticE<cbool>: // IEEE: part of extern_constraint_declaration

View File

@ -1,5 +1,5 @@
%Error: t/t_class_scope_import_bad.v:11:14: Import statement directly within a class scope is illegal
%Error: t/t_class_scope_import_bad.v:11:11: Import statement directly within a class scope is illegal
11 | import pkg::*;
| ^~
| ^~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -1,8 +1,8 @@
%Error: t/t_lint_import_name2_bad.v:7:8: Importing from missing package 'missing'
%Error: t/t_lint_import_name2_bad.v:7:8: Import package not found: 'missing'
7 | import missing::sigs;
| ^~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_lint_import_name2_bad.v:9:8: Importing from missing package 'missing'
%Error: t/t_lint_import_name2_bad.v:9:8: Import package not found: 'missing'
9 | import missing::*;
| ^~~~~~~
%Error: Exiting due to

View File

@ -1,5 +1,5 @@
%Error: t/t_lint_import_name_bad.v:11:12: Import object not found: 'defs'
%Error: t/t_lint_import_name_bad.v:11:8: Import object not found: 'defs'
11 | import defs::sigs;
| ^~
| ^~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -1,6 +1,6 @@
%Warning-IMPORTSTAR: t/t_lint_importstar_bad.v:11:12: Import::* in $unit scope may pollute global namespace
%Warning-IMPORTSTAR: t/t_lint_importstar_bad.v:11:8: Import::* in $unit scope may pollute global namespace
11 | import defs::*;
| ^~
| ^~~~
... For warning description see https://verilator.org/warn/IMPORTSTAR?v=latest
... Use "/* verilator lint_off IMPORTSTAR */" and lint_on around source to disable this message.
%Error: Exiting due to

View File

@ -1,4 +1,4 @@
%Error: t/t_no_std_bad.v:9:11: Importing from missing package 'std'
%Error: t/t_no_std_bad.v:9:11: Import package not found: 'std'
9 | import std::*;
| ^~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.

View File

@ -1,4 +1,4 @@
%Error: t/t_package_import_bad2.v:12:11: Importing from missing package 'Pkg1b'
%Error: t/t_package_import_bad2.v:12:11: Import package not found: 'Pkg1b'
12 | import Pkg1b::*;
| ^~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.

View File

@ -9,7 +9,4 @@
%Error-UNSUPPORTED: t/t_property_var_unsup.v:24:31: Unsupported: property variable default value
24 | property with_def(int nine = 9);
| ^
%Error: Internal Error: t/t_property_var_unsup.v:7:8: ../V3ParseSym.h:#: Symbols suggest ending PROPERTY 'prop' but parser thinks ending MODULE 't'
7 | module t (
| ^
... This fatal error may be caused by the earlier error(s); resolve those first.
%Error: Exiting due to

View File

@ -1,4 +1,4 @@
%Error: t/t_vlt_match_error.v:17:12: Importing from missing package 'hi'
%Error: t/t_vlt_match_error.v:17:12: Import package not found: 'hi'
17 | import hi::*;
| ^~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.