mirror of
https://github.com/verilator/verilator.git
synced 2025-04-30 12:36:53 +00:00
Internals: Add parse-time symbol table for eventual typedef detection
This commit is contained in:
parent
f7efae93d5
commit
18bebaf5c3
@ -88,7 +88,7 @@ private:
|
|||||||
if (V3SymTable* symsp = nodep->user1p()->castSymTable()) {
|
if (V3SymTable* symsp = nodep->user1p()->castSymTable()) {
|
||||||
return symsp;
|
return symsp;
|
||||||
} else {
|
} else {
|
||||||
V3SymTable* symsp = new V3SymTable(upperVarsp);
|
V3SymTable* symsp = new V3SymTable(nodep, upperVarsp);
|
||||||
m_delSymps.push_back(symsp);
|
m_delSymps.push_back(symsp);
|
||||||
nodep->user1p(symsp);
|
nodep->user1p(symsp);
|
||||||
return symsp;
|
return symsp;
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
// NO EDITS: Don't replace or delete nodes, as the parser symbol table
|
||||||
|
// has pointers into the ast tree.
|
||||||
|
//
|
||||||
// LINK TRANSFORMATIONS:
|
// LINK TRANSFORMATIONS:
|
||||||
// Top-down traversal
|
// Top-down traversal
|
||||||
// Cells:
|
// Cells:
|
||||||
@ -88,6 +91,8 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstModule::user1p() // V3GraphVertex* Vertex describing this module
|
// AstModule::user1p() // V3GraphVertex* Vertex describing this module
|
||||||
|
// Allocated across all readFiles in V3Global::readFiles:
|
||||||
|
// AstNode::user4p() // V3SymTable* Package and typedef symbol names
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
|
|
||||||
V3ParseImp* V3ParseImp::s_parsep = NULL;
|
V3ParseImp* V3ParseImp::s_parsep = NULL;
|
||||||
|
|
||||||
|
int V3ParseSym::s_anonNum = 0;
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Read class functions
|
// Read class functions
|
||||||
|
|
||||||
@ -60,6 +62,8 @@ V3ParseImp::~V3ParseImp() {
|
|||||||
m_numberps.clear();
|
m_numberps.clear();
|
||||||
lexDestroy();
|
lexDestroy();
|
||||||
parserClear();
|
parserClear();
|
||||||
|
|
||||||
|
if (debug()>=9) { UINFO(0,"~V3ParseImp\n"); symp()->dump(cout, "-vpi: "); }
|
||||||
}
|
}
|
||||||
|
|
||||||
int V3ParseImp::ppInputToLex(char* buf, int max_size) {
|
int V3ParseImp::ppInputToLex(char* buf, int max_size) {
|
||||||
|
116
src/V3ParseImp.h
116
src/V3ParseImp.h
@ -45,6 +45,7 @@ typedef enum { uniq_NONE, uniq_UNIQUE, uniq_PRIORITY } V3UniqState;
|
|||||||
|
|
||||||
struct V3ParseBisonYYSType {
|
struct V3ParseBisonYYSType {
|
||||||
FileLine* fl;
|
FileLine* fl;
|
||||||
|
//V3SymTable* scp; // Symbol table scope for future lookups
|
||||||
union {
|
union {
|
||||||
V3Number* nump;
|
V3Number* nump;
|
||||||
string* strp;
|
string* strp;
|
||||||
@ -73,6 +74,115 @@ struct V3ParseBisonYYSType {
|
|||||||
|
|
||||||
#define YYSTYPE V3ParseBisonYYSType
|
#define YYSTYPE V3ParseBisonYYSType
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Symbol table for parsing
|
||||||
|
|
||||||
|
class V3ParseSym {
|
||||||
|
// TYPES
|
||||||
|
typedef vector<V3SymTable*> SymStack;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// MEMBERS
|
||||||
|
static int s_anonNum; // Number of next anonymous object
|
||||||
|
V3SymTable* m_symTableNextId; // Symbol table for next lexer lookup
|
||||||
|
V3SymTable* m_symCurrentp; // Node with active symbol table for additions/lookups
|
||||||
|
SymStack m_sympStack; // Stack of nodes with symbol tables
|
||||||
|
SymStack m_symsp; // All symbol tables, to cleanup
|
||||||
|
|
||||||
|
private:
|
||||||
|
// METHODS
|
||||||
|
static V3SymTable* getTable(AstNode* nodep) {
|
||||||
|
if (!nodep->user4p()) nodep->v3fatalSrc("Current symtable not found");
|
||||||
|
return nodep->user4p()->castSymTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
V3SymTable* nextId() const { return m_symTableNextId; }
|
||||||
|
V3SymTable* symCurrentp() const { return m_symCurrentp; }
|
||||||
|
|
||||||
|
V3SymTable* findNewTable(AstNode* nodep, V3SymTable* parentp) {
|
||||||
|
if (!nodep->user4p()) {
|
||||||
|
V3SymTable* symsp = new V3SymTable(nodep, parentp);
|
||||||
|
nodep->user4p(symsp);
|
||||||
|
m_symsp.push_back(symsp);
|
||||||
|
}
|
||||||
|
return getTable(nodep);
|
||||||
|
}
|
||||||
|
void nextId(AstNode* entp) {
|
||||||
|
if (entp) { UINFO(9,"symTableNextId under "<<entp<<"-"<<entp->type().ascii()<<endl); }
|
||||||
|
else { UINFO(9,"symTableNextId under NULL"<<endl); }
|
||||||
|
m_symTableNextId = getTable(entp);
|
||||||
|
}
|
||||||
|
void reinsert(AstNode* nodep, V3SymTable* parentp=NULL) {
|
||||||
|
if (!parentp) parentp = symCurrentp();
|
||||||
|
string name = nodep->name();
|
||||||
|
if (name == "") { // New name with space in name so can't collide with users
|
||||||
|
name = string(" anon") + nodep->type().ascii() + cvtToStr(++s_anonNum);
|
||||||
|
}
|
||||||
|
parentp->reinsert(name,nodep);
|
||||||
|
}
|
||||||
|
void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); }
|
||||||
|
void pushNewUnder(AstNode* nodep, V3SymTable* parentp) {
|
||||||
|
if (!parentp) parentp = symCurrentp();
|
||||||
|
V3SymTable* symp = findNewTable(nodep, parentp); // Will set user4p, which is how we connect table to node
|
||||||
|
reinsert(nodep, parentp);
|
||||||
|
pushScope(symp);
|
||||||
|
}
|
||||||
|
void pushScope(V3SymTable* symp) {
|
||||||
|
m_sympStack.push_back(symp);
|
||||||
|
m_symCurrentp = symp;
|
||||||
|
}
|
||||||
|
void popScope(AstNode* nodep) {
|
||||||
|
if (symCurrentp()->ownerp() != nodep) {
|
||||||
|
if (debug()) { showUpward(); dump(cout,"-mism: "); }
|
||||||
|
nodep->v3fatalSrc("Symbols suggest ending "<<symCurrentp()->ownerp()->prettyTypeName()
|
||||||
|
<<" but parser thinks ending "<<nodep->prettyTypeName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_sympStack.pop_back();
|
||||||
|
if (m_sympStack.empty()) { nodep->v3fatalSrc("symbol stack underflow"); return; }
|
||||||
|
m_symCurrentp = m_sympStack.back();
|
||||||
|
}
|
||||||
|
void showUpward () {
|
||||||
|
UINFO(1,"ParseSym Stack:\n");
|
||||||
|
for (SymStack::reverse_iterator it=m_sympStack.rbegin(); it!=m_sympStack.rend(); ++it) {
|
||||||
|
V3SymTable* symp = *it;
|
||||||
|
UINFO(1,"\t"<<symp->ownerp()<<endl);
|
||||||
|
}
|
||||||
|
UINFO(1,"ParseSym Current: "<<symCurrentp()->ownerp()<<endl);
|
||||||
|
}
|
||||||
|
void dump(ostream& os, const string& indent="") {
|
||||||
|
os<<"ParseSym Dump:\n";
|
||||||
|
m_sympStack[0]->dump(os, indent, true);
|
||||||
|
}
|
||||||
|
AstNode* findEntUpward (const string& name) {
|
||||||
|
// Lookup the given string as an identifier, return type of the id, scanning upward
|
||||||
|
return symCurrentp()->findIdUpward(name);
|
||||||
|
}
|
||||||
|
void import(AstNode* nodep, const string& pkg, const string& id_or_star) {
|
||||||
|
// Import from package::id_or_star to this
|
||||||
|
AstNode* entp = findEntUpward(pkg);
|
||||||
|
if (!entp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE
|
||||||
|
nodep->v3fatalSrc("Import package not found: "+pkg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Walk old sym table and reinsert into current table
|
||||||
|
nodep->v3fatalSrc("Unimplemented: import");
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CREATORS
|
||||||
|
V3ParseSym(AstNetlist* rootp) {
|
||||||
|
s_anonNum = 0; // Number of next anonymous object
|
||||||
|
pushScope(findNewTable(rootp, NULL));
|
||||||
|
m_symTableNextId = symCurrentp();
|
||||||
|
}
|
||||||
|
~V3ParseSym() {
|
||||||
|
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
|
||||||
|
delete (*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
class V3ParseImp {
|
class V3ParseImp {
|
||||||
@ -82,6 +192,7 @@ class V3ParseImp {
|
|||||||
static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based
|
static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based
|
||||||
FileLine* m_fileline; // Filename/linenumber currently active
|
FileLine* m_fileline; // Filename/linenumber currently active
|
||||||
|
|
||||||
|
V3ParseSym m_sym; // Symbol table
|
||||||
bool m_inCellDefine; // Inside a `celldefine
|
bool m_inCellDefine; // Inside a `celldefine
|
||||||
bool m_inLibrary; // Currently reading a library vs. regular file
|
bool m_inLibrary; // Currently reading a library vs. regular file
|
||||||
int m_inBeginKwd; // Inside a `begin_keywords
|
int m_inBeginKwd; // Inside a `begin_keywords
|
||||||
@ -172,9 +283,12 @@ public:
|
|||||||
int stateVerilogRecent(); // Parser -> lexer communication
|
int stateVerilogRecent(); // Parser -> lexer communication
|
||||||
int flexPpInputToLex(char* buf, int max_size) { return ppInputToLex(buf,max_size); }
|
int flexPpInputToLex(char* buf, int max_size) { return ppInputToLex(buf,max_size); }
|
||||||
|
|
||||||
|
//==== Symbol tables
|
||||||
|
V3ParseSym* symp() { return &m_sym; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
V3ParseImp(AstNetlist* rootp) {
|
V3ParseImp(AstNetlist* rootp) : m_sym(rootp) {
|
||||||
m_rootp = rootp; m_lexerp = NULL;
|
m_rootp = rootp; m_lexerp = NULL;
|
||||||
m_inCellDefine = false;
|
m_inCellDefine = false;
|
||||||
m_inLibrary = false;
|
m_inLibrary = false;
|
||||||
|
@ -41,12 +41,16 @@ class V3SymTable : public AstNUser {
|
|||||||
// MEMBERS
|
// MEMBERS
|
||||||
typedef std::map<string,AstNode*> IdNameMap;
|
typedef std::map<string,AstNode*> IdNameMap;
|
||||||
IdNameMap m_idNameMap; // Hash of variables by name
|
IdNameMap m_idNameMap; // Hash of variables by name
|
||||||
|
AstNode* m_ownerp; // Node that table belongs to
|
||||||
V3SymTable* m_upperp; // Table "above" this one in name scope
|
V3SymTable* m_upperp; // Table "above" this one in name scope
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
V3SymTable(V3SymTable* upperTablep) { m_upperp = upperTablep; }
|
V3SymTable(AstNode* ownerp, V3SymTable* upperTablep) {
|
||||||
V3SymTable() { m_upperp = NULL; }
|
m_ownerp = ownerp; m_upperp = upperTablep; }
|
||||||
|
V3SymTable() {
|
||||||
|
m_ownerp = NULL; m_upperp = NULL; }
|
||||||
~V3SymTable() {}
|
~V3SymTable() {}
|
||||||
|
AstNode* ownerp() const { return m_ownerp; }
|
||||||
void insert(const string& name, AstNode* nodep) {
|
void insert(const string& name, AstNode* nodep) {
|
||||||
//UINFO(9, " SymInsert "<<this<<" '"<<name<<"' "<<nodep<<endl);
|
//UINFO(9, " SymInsert "<<this<<" '"<<name<<"' "<<nodep<<endl);
|
||||||
if (m_idNameMap.find(name) != m_idNameMap.end()) {
|
if (m_idNameMap.find(name) != m_idNameMap.end()) {
|
||||||
@ -57,15 +61,24 @@ class V3SymTable : public AstNUser {
|
|||||||
m_idNameMap.insert(make_pair(name, nodep));
|
m_idNameMap.insert(make_pair(name, nodep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AstNode* findIdFlat(const string& name) {
|
void reinsert(const string& name, AstNode* nodep) {
|
||||||
|
IdNameMap::iterator it = m_idNameMap.find(name);
|
||||||
|
if (it != m_idNameMap.end()) {
|
||||||
|
//UINFO(9, " SymReinsert "<<this<<" '"<<name<<"' "<<nodep<<endl);
|
||||||
|
it->second = nodep; // Replace
|
||||||
|
} else {
|
||||||
|
insert(name,nodep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AstNode* findIdFlat(const string& name) const {
|
||||||
// Find identifier without looking upward through symbol hierarchy
|
// Find identifier without looking upward through symbol hierarchy
|
||||||
//UINFO(9, " SymFind "<<this<<" '"<<name<<"' "<<endl);
|
//UINFO(9, " SymFind "<<this<<" '"<<name<<"' "<<endl);
|
||||||
// First, scan this begin/end block or module for the name
|
// First, scan this begin/end block or module for the name
|
||||||
IdNameMap::iterator iter = m_idNameMap.find(name);
|
IdNameMap::const_iterator iter = m_idNameMap.find(name);
|
||||||
if (iter != m_idNameMap.end()) return (iter->second);
|
if (iter != m_idNameMap.end()) return (iter->second);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AstNode* findIdUpward(const string& name) {
|
AstNode* findIdUpward(const string& name) const {
|
||||||
// Find identifier looking upward through symbol hierarchy
|
// Find identifier looking upward through symbol hierarchy
|
||||||
// First, scan this begin/end block or module for the name
|
// First, scan this begin/end block or module for the name
|
||||||
if (AstNode* nodep = findIdFlat(name)) return nodep;
|
if (AstNode* nodep = findIdFlat(name)) return nodep;
|
||||||
@ -73,6 +86,17 @@ class V3SymTable : public AstNUser {
|
|||||||
if (m_upperp) return m_upperp->findIdUpward(name);
|
if (m_upperp) return m_upperp->findIdUpward(name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
void dump(ostream& os, const string& indent="", bool user4p_is_table=false) const {
|
||||||
|
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
|
||||||
|
os<<indent<<it->first;
|
||||||
|
for (int i=it->first.length(); i<30; ++i) os<<" ";
|
||||||
|
os<<it->second<<endl;
|
||||||
|
if (user4p_is_table) {
|
||||||
|
V3SymTable* belowp = (it->second)->user4p()->castSymTable();
|
||||||
|
belowp->dump(os, indent+" ", user4p_is_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // guard
|
#endif // guard
|
||||||
|
@ -92,6 +92,10 @@ V3Global v3Global;
|
|||||||
// V3 Class -- top level
|
// V3 Class -- top level
|
||||||
|
|
||||||
void V3Global::readFiles() {
|
void V3Global::readFiles() {
|
||||||
|
// NODE STATE
|
||||||
|
// AstNode::user4p() // V3SymTable* Package and typedef symbol names
|
||||||
|
AstUser4InUse inuser4;
|
||||||
|
|
||||||
V3Parse parser (v3Global.rootp());
|
V3Parse parser (v3Global.rootp());
|
||||||
// Read top module
|
// Read top module
|
||||||
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
|
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
|
||||||
|
@ -101,6 +101,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define PARSEP V3ParseImp::parsep()
|
#define PARSEP V3ParseImp::parsep()
|
||||||
|
#define SYMP PARSEP->symp()
|
||||||
#define GRAMMARP V3ParseGrammar::singletonp()
|
#define GRAMMARP V3ParseGrammar::singletonp()
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
@ -521,7 +522,7 @@ module_declaration: // ==IEEE: module_declaration
|
|||||||
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
|
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
|
||||||
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
|
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
|
||||||
if ($5) $1->addStmtp($5);
|
if ($5) $1->addStmtp($5);
|
||||||
}
|
SYMP->popScope($1); }
|
||||||
//
|
//
|
||||||
//UNSUP yEXTERN modFront parameter_port_listE portsStarE ';'
|
//UNSUP yEXTERN modFront parameter_port_listE portsStarE ';'
|
||||||
//UNSUP { UNSUP }
|
//UNSUP { UNSUP }
|
||||||
@ -534,7 +535,7 @@ modFront<modulep>:
|
|||||||
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
|
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
|
||||||
$$->modTrace(v3Global.opt.trace());
|
$$->modTrace(v3Global.opt.trace());
|
||||||
PARSEP->rootp()->addModulep($$);
|
PARSEP->rootp()->addModulep($$);
|
||||||
}
|
SYMP->pushNew($$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
parameter_value_assignmentE<pinp>: // IEEE: [ parameter_value_assignment ]
|
parameter_value_assignmentE<pinp>: // IEEE: [ parameter_value_assignment ]
|
||||||
@ -1383,13 +1384,13 @@ stmtBlock<nodep>: // IEEE: statement + seq_block + par_block
|
|||||||
seq_block<nodep>: // ==IEEE: seq_block
|
seq_block<nodep>: // ==IEEE: seq_block
|
||||||
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
|
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
|
||||||
// // So need begin's even if unnamed to scope variables down
|
// // So need begin's even if unnamed to scope variables down
|
||||||
seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtp($2); }
|
seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtp($2); SYMP->popScope($1); }
|
||||||
| seq_blockFront /**/ yEND endLabelE { $$=$1; }
|
| seq_blockFront /**/ yEND endLabelE { $$=$1; SYMP->popScope($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
seq_blockFront<beginp>: // IEEE: part of par_block
|
seq_blockFront<beginp>: // IEEE: part of par_block
|
||||||
yBEGIN { $$ = new AstBegin($1,"",NULL); }
|
yBEGIN { $$ = new AstBegin($1,"",NULL); SYMP->pushNew($$); }
|
||||||
| yBEGIN ':' idAny/*new-block_identifier*/ { $$ = new AstBegin($1,*$3,NULL); }
|
| yBEGIN ':' idAny/*new-block_identifier*/ { $$ = new AstBegin($1,*$3,NULL); SYMP->pushNew($$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
blockDeclStmtList<nodep>: // IEEE: { block_item_declaration } { statement or null }
|
blockDeclStmtList<nodep>: // IEEE: { block_item_declaration } { statement or null }
|
||||||
@ -1719,16 +1720,16 @@ list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
|
|||||||
|
|
||||||
task_declaration<taskp>: // ==IEEE: task_declaration
|
task_declaration<taskp>: // ==IEEE: task_declaration
|
||||||
yTASK lifetimeE taskId tfGuts yENDTASK endLabelE
|
yTASK lifetimeE taskId tfGuts yENDTASK endLabelE
|
||||||
{ $$ = $3; $$->addStmtsp($4); }
|
{ $$ = $3; $$->addStmtsp($4); SYMP->popScope($$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
function_declaration<funcp>: // IEEE: function_declaration + function_body_declaration
|
function_declaration<funcp>: // IEEE: function_declaration + function_body_declaration
|
||||||
yFUNCTION lifetimeE funcTypeE funcId tfGuts yENDFUNCTION endLabelE
|
yFUNCTION lifetimeE funcTypeE funcId tfGuts yENDFUNCTION endLabelE
|
||||||
{ $$ = $4; $$->addFvarp($3); $$->addStmtsp($5); if ($3) $$->isSigned($3->isSigned());
|
{ $$ = $4; $$->addFvarp($3); $$->addStmtsp($5); if ($3) $$->isSigned($3->isSigned());
|
||||||
}
|
SYMP->popScope($$); }
|
||||||
| yFUNCTION lifetimeE funcTypeE funcId yVL_ISOLATE_ASSIGNMENTS tfGuts yENDFUNCTION endLabelE
|
| yFUNCTION lifetimeE funcTypeE funcId yVL_ISOLATE_ASSIGNMENTS tfGuts yENDFUNCTION endLabelE
|
||||||
{ $$ = $4; $$->addFvarp($3); $$->addStmtsp($6); $$->attrIsolateAssign(true); if ($3) $$->isSigned($3->isSigned());
|
{ $$ = $4; $$->addFvarp($3); $$->addStmtsp($6); $$->attrIsolateAssign(true); if ($3) $$->isSigned($3->isSigned());
|
||||||
}
|
SYMP->popScope($$); }
|
||||||
//UNSUP: Generic function return types
|
//UNSUP: Generic function return types
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1744,17 +1745,24 @@ lifetime: // ==IEEE: lifetime
|
|||||||
;
|
;
|
||||||
|
|
||||||
taskId<taskp>:
|
taskId<taskp>:
|
||||||
id
|
tfIdScoped
|
||||||
{ $$ = new AstTask($<fl>1, *$1, NULL);
|
{ $$ = new AstTask($<fl>1, *$<strp>1, NULL);
|
||||||
}
|
SYMP->pushNewUnder($$, NULL); }
|
||||||
;
|
;
|
||||||
|
|
||||||
funcId<funcp>: // IEEE: function_data_type_or_implicit + part of function_body_declaration
|
funcId<funcp>: // IEEE: function_data_type_or_implicit + part of function_body_declaration
|
||||||
// // IEEE: function_data_type_or_implicit must be expanded here to prevent conflict
|
// // IEEE: function_data_type_or_implicit must be expanded here to prevent conflict
|
||||||
// // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID
|
// // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID
|
||||||
id
|
tfIdScoped
|
||||||
{ $$ = new AstFunc ($<fl>1,*$1,NULL,NULL);
|
{ $$ = new AstFunc ($<fl>1,*$<strp>1,NULL,NULL);
|
||||||
}
|
SYMP->pushNewUnder($$, NULL); }
|
||||||
|
//UNSUP id/*interface_identifier*/ '.' id { UNSUP }
|
||||||
|
//UNSUP class_scope_id { UNSUP }
|
||||||
|
;
|
||||||
|
|
||||||
|
tfIdScoped<strp>: // IEEE: part of function_body_declaration/task_body_declaration
|
||||||
|
// // IEEE: [ interface_identifier '.' | class_scope ] function_identifier
|
||||||
|
id { $<fl>$=$<fl>1; $<strp>$ = $1; }
|
||||||
//UNSUP id/*interface_identifier*/ '.' id { UNSUP }
|
//UNSUP id/*interface_identifier*/ '.' id { UNSUP }
|
||||||
//UNSUP class_scope_id { UNSUP }
|
//UNSUP class_scope_id { UNSUP }
|
||||||
;
|
;
|
||||||
|
Loading…
Reference in New Issue
Block a user