diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 1bffff1ee..9f2ca053b 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -245,6 +245,22 @@ public: AstRange* rangep() const { return VN_CAST(op2p(), Range); } // op2 = Range of pin }; +class AstClass : public AstNode { + // MEMBERS + string m_name; // Name +public: + AstClass(FileLine* fl, const string& name) + : AstNode(fl) + , m_name(name) {} + ASTNODE_NODE_FUNCS(Class) + virtual string name() const { return m_name; } // * = Var name + virtual void name(const string& name) { m_name = name; } + virtual string verilogKwd() const { return "class"; } + virtual bool maybePointedTo() const { return true; } + AstNode* membersp() const { return op1p(); } // op1 = List of statements + void addMembersp(AstNode* nodep) { addNOp1p(nodep); } +}; + //###################################################################### //==== Data Types @@ -685,6 +701,45 @@ public: virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } }; +class AstClassRefDType : public AstNodeDType { + // Reference to a class +private: + AstClass* m_classp; // data type pointed to, BELOW the AstTypedef + AstPackage* m_packagep; // Package hierarchy +public: + AstClassRefDType(FileLine* fl, AstClass* classp) + : AstNodeDType(fl), m_classp(classp), m_packagep(NULL) { + dtypep(this); + } + ASTNODE_NODE_FUNCS(ClassRefDType) + // METHODS + virtual const char* broken() const { + BROKEN_RTN(m_classp && !m_classp->brokeExists()); return NULL; } + virtual void cloneRelink() { + if (m_classp && m_classp->clonep()) m_classp = m_classp->clonep(); + } + virtual bool same(const AstNode* samep) const { + const AstClassRefDType* asamep = static_cast(samep); + return (m_classp == asamep->m_classp + && m_packagep == asamep->m_packagep); } + virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } + virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_classp), V3Hash(m_packagep)); } + virtual string name() const { return classp() ? classp()->name() : ""; } + virtual AstBasicDType* basicp() const { return NULL; } + virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const { return 0; } + virtual int widthTotalBytes() const { return 0; } + virtual AstNodeDType* virtRefDTypep() const { return NULL; } + virtual void virtRefDTypep(AstNodeDType* nodep) {} + virtual AstNodeDType* subDTypep() const { return NULL; } + AstPackage* packagep() const { return m_packagep; } + void packagep(AstPackage* nodep) { m_packagep = nodep; } + AstClass* classp() const { return m_classp; } + void classp(AstClass* nodep) { m_classp = nodep; } +}; + class AstIfaceRefDType : public AstNodeDType { // Reference to an interface, either for a port, or inside parent cell private: @@ -844,6 +899,7 @@ public: class AstStructDType : public AstNodeUOrStructDType { public: + // AstNumeric below is mispurposed to indicate if packed or not AstStructDType(FileLine* fl, AstNumeric numericUnpack) : AstNodeUOrStructDType(fl, numericUnpack) {} ASTNODE_NODE_FUNCS(StructDType) @@ -853,6 +909,7 @@ public: class AstUnionDType : public AstNodeUOrStructDType { public: //UNSUP: bool isTagged; + // AstNumeric below is mispurposed to indicate if packed or not AstUnionDType(FileLine* fl, AstNumeric numericUnpack) : AstNodeUOrStructDType(fl, numericUnpack) {} ASTNODE_NODE_FUNCS(UnionDType) @@ -1282,37 +1339,6 @@ public: void declRange(const VNumRange& flag) { m_declRange = flag; } }; -class AstMemberSel : public AstNodeMath { - // Parents: math|stmt - // Children: varref|arraysel, math -private: - // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it - string m_name; -public: - AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name) - : AstNodeMath(fl), m_name(name) { - setOp1p(fromp); - dtypep(NULL); // V3Width will resolve - } - AstMemberSel(FileLine* fl, AstNode* fromp, AstMemberDType* dtp) - : AstNodeMath(fl) { - setOp1p(fromp); - dtypep(dtp); - m_name = dtp->name(); - } - ASTNODE_NODE_FUNCS(MemberSel) - virtual string name() const { return m_name; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; /* How can from be a const? */ } - virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially - virtual string emitC() { V3ERROR_NA; return ""; } - virtual bool cleanOut() const { return false; } - virtual bool same(const AstNode* samep) const { return true; } // dtype comparison does it all for us - virtual int instrCount() const { return widthInstrs(); } - AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } -}; - class AstMethodCall : public AstNode { // A reference to a member task (or function) // We do not support generic member calls yet, so this is only enough to @@ -2012,6 +2038,47 @@ public: ASTNODE_NODE_FUNCS(Iface) }; +class AstMemberSel : public AstNodeMath { + // Parents: math|stmt + // Children: varref|arraysel, math +private: + // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it + string m_name; + AstVar* m_varp; // Post link, variable within class that is target of selection +public: + AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name) + : AstNodeMath(fl) + , m_name(name) + , m_varp(NULL) { + setOp1p(fromp); + dtypep(NULL); // V3Width will resolve + } + AstMemberSel(FileLine* fl, AstNode* fromp, AstNodeDType* dtp) + : AstNodeMath(fl) + , m_name(dtp->name()) + , m_varp(NULL) { + setOp1p(fromp); + dtypep(dtp); + } + ASTNODE_NODE_FUNCS(MemberSel) + virtual void cloneRelink() { if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); } } + virtual const char* broken() const { + BROKEN_RTN(m_varp && !m_varp->brokeExists()); return NULL; } + virtual string name() const { return m_name; } + virtual V3Hash sameHash() const { return V3Hash(m_name); } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + V3ERROR_NA; /* How can from be a const? */ } + virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially + virtual string emitC() { V3ERROR_NA; return ""; } + virtual bool cleanOut() const { return false; } + virtual bool same(const AstNode* samep) const { return true; } // dtype comparison does it + virtual int instrCount() const { return widthInstrs(); } + AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) + void fromp(AstNode* nodep) { setOp1p(nodep); } + AstVar* varp() const { return m_varp; } + void varp(AstVar* nodep) { m_varp = nodep; } +}; + class AstModportFTaskRef : public AstNode { // An import/export referenced under a modport // The storage for the function itself is inside the @@ -3826,6 +3893,25 @@ public: } }; +class AstNew : public AstNodeMath { + // Parents: math|stmt + // Children: varref|arraysel, math +public: + AstNew(FileLine* fl) + : AstNodeMath(fl) { + dtypep(NULL); // V3Width will resolve + } + ASTNODE_NODE_FUNCS(New) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + V3ERROR_NA; /* How can from be a const? */ } + virtual V3Hash sameHash() const { return V3Hash(); } + virtual string emitVerilog() { return "new"; } + virtual string emitC() { V3ERROR_NA; return ""; } + virtual bool cleanOut() const { return true; } + virtual bool same(const AstNode* samep) const { return true; } + virtual int instrCount() const { return widthInstrs(); } +}; + class AstPragma : public AstNode { private: AstPragmaType m_pragType; // Type of pragma diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 73c691bf2..a2d49c29d 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -70,6 +70,7 @@ struct V3ParseBisonYYSType { AstCase* casep; AstCaseItem* caseitemp; AstCell* cellp; + AstClass* classp; AstConst* constp; AstMemberDType* memberp; AstNodeModule* modulep; @@ -86,6 +87,7 @@ struct V3ParseBisonYYSType { AstPatMember* patmemberp; AstPattern* patternp; AstPin* pinp; + AstRefDType* refdtypep; AstSenTree* sentreep; AstVar* varp; AstVarRef* varrefp; diff --git a/src/verilog.l b/src/verilog.l index 4611b66e9..0a082bd43 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -411,19 +411,21 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "always_comb" { FL; return yALWAYS_COMB; } "always_ff" { FL; return yALWAYS_FF; } "always_latch" { FL; return yALWAYS_LATCH; } - "assume" { FL; return yASSUME; } "assert" { FL; return yASSERT; } + "assume" { FL; return yASSUME; } "bind" { FL; return yBIND; } "bit" { FL; return yBIT; } "break" { FL; return yBREAK; } "byte" { FL; return yBYTE; } "chandle" { FL; return yCHANDLE; } + "class" { FL; return yCLASS; } "clocking" { FL; return yCLOCKING; } "const" { FL; return yCONST__LEX; } "context" { FL; return yCONTEXT; } "continue" { FL; return yCONTINUE; } "cover" { FL; return yCOVER; } "do" { FL; return yDO; } + "endclass" { FL; return yENDCLASS; } "endclocking" { FL; return yENDCLOCKING; } "endinterface" { FL; return yENDINTERFACE; } "endpackage" { FL; return yENDPACKAGE; } @@ -431,6 +433,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "endproperty" { FL; return yENDPROPERTY; } "enum" { FL; return yENUM; } "export" { FL; return yEXPORT; } + "extends" { FL; return yEXTENDS; } "extern" { FL; return yEXTERN; } "final" { FL; return yFINAL; } "forkjoin" { FL; return yFORKJOIN; } @@ -439,15 +442,18 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "inside" { FL; return yINSIDE; } "int" { FL; return yINT; } "interface" { FL; return yINTERFACE; } + "local" { FL; return yLOCAL__LEX; } "logic" { FL; return yLOGIC; } "longint" { FL; return yLONGINT; } "modport" { FL; return yMODPORT; } + "new" { FL; return yNEW__LEX; } "null" { FL; return yNULL; } "package" { FL; return yPACKAGE; } "packed" { FL; return yPACKED; } "priority" { FL; return yPRIORITY; } "program" { FL; return yPROGRAM; } "property" { FL; return yPROPERTY; } + "protected" { FL; return yPROTECTED; } "pure" { FL; return yPURE; } "rand" { FL; return yRAND; } "randc" { FL; return yRANDC; } @@ -460,6 +466,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "static" { FL; return ySTATIC__ETC; } "string" { FL; return ySTRING; } "struct" { FL; return ySTRUCT; } + "super" { FL; return ySUPER; } + "this" { FL; return yTHIS; } "timeprecision" { FL; return yTIMEPRECISION; } "timeunit" { FL; return yTIMEUNIT; } "type" { FL; return yTYPE; } @@ -467,6 +475,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "union" { FL; return yUNION; } "unique" { FL; return yUNIQUE; } "var" { FL; return yVAR; } + "virtual" { FL; return yVIRTUAL__LEX; } "void" { FL; return yVOID; } /* Generic unsupported warnings */ /* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */ @@ -474,36 +483,27 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "before" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "bins" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "binsof" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "class" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "constraint" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "covergroup" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "coverpoint" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "cross" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "dist" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "endclass" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "endgroup" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "endsequence" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "expect" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "extends" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "first_match" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "ignore_bins" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "illegal_bins" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "intersect" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "join_any" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "join_none" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "local" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "matches" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "new" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "protected" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "randomize" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "randsequence" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "sequence" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "solve" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "super" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "tagged" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "this" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "throughout" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "virtual" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "wait_order" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "wildcard" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "with" { ERROR_RSVD_WORD("SystemVerilog 2005"); } @@ -541,7 +541,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* System Verilog 2012 */ { /* Keywords */ - "implements" { ERROR_RSVD_WORD("SystemVerilog 2012"); } + "implements" { FL; return yIMPLEMENTS; } "interconnect" { ERROR_RSVD_WORD("SystemVerilog 2012"); } "nettype" { ERROR_RSVD_WORD("SystemVerilog 2012"); } "soft" { ERROR_RSVD_WORD("SystemVerilog 2012"); } @@ -1012,6 +1012,9 @@ void V3ParseImp::lexToken() { 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"<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 @@ -1061,7 +1080,7 @@ void V3ParseImp::lexToken() { if (VN_IS(scp, Typedef)) token = yaID__aTYPE; else if (VN_IS(scp, TypedefFwd)) token = yaID__aTYPE; else if (VN_IS(scp, Package)) token = yaID__aPACKAGE; - //UNSUP else if (VN_IS(scp, NodeClass)) token = yaID__aCLASS; + else if (VN_IS(scp, Class)) token = yaID__aTYPE; //UNSUP else if (VN_IS(scp, CoverGroup)) token = yaID__aCOVERGROUP; else token = yaID__ETC; } else { // Not found diff --git a/src/verilog.y b/src/verilog.y index c1e828a22..510e67b57 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -345,6 +345,7 @@ class AstSenTree; %token yCASEX "casex" %token yCASEZ "casez" %token yCHANDLE "chandle" +%token yCLASS "class" %token yCLOCKING "clocking" %token yCMOS "cmos" %token yCONST__ETC "const" @@ -362,6 +363,7 @@ class AstSenTree; %token yELSE "else" %token yEND "end" %token yENDCASE "endcase" +%token yENDCLASS "endclass" %token yENDCLOCKING "endclocking" %token yENDFUNCTION "endfunction" %token yENDGENERATE "endgenerate" @@ -377,6 +379,7 @@ class AstSenTree; %token yENUM "enum" %token yEVENT "event" %token yEXPORT "export" +%token yEXTENDS "extends" %token yEXTERN "extern" %token yFINAL "final" %token yFOR "for" @@ -393,6 +396,7 @@ class AstSenTree; %token yGLOBAL__LEX "global-in-lex" %token yIF "if" %token yIFF "iff" +%token yIMPLEMENTS "implements" %token yIMPORT "import" %token yINITIAL "initial" %token yINOUT "inout" @@ -403,12 +407,18 @@ class AstSenTree; %token yINTERFACE "interface" %token yJOIN "join" %token yLOCALPARAM "localparam" +%token yLOCAL__COLONCOLON "local-then-::" +%token yLOCAL__ETC "local" +%token yLOCAL__LEX "local-in-lex" %token yLOGIC "logic" %token yLONGINT "longint" %token yMODPORT "modport" %token yMODULE "module" %token yNAND "nand" %token yNEGEDGE "negedge" +%token yNEW__ETC "new" +%token yNEW__LEX "new-in-lex" +%token yNEW__PAREN "new-then-paren" %token yNMOS "nmos" %token yNOR "nor" %token yNOT "not" @@ -426,6 +436,7 @@ class AstSenTree; %token yPRIORITY "priority" %token yPROGRAM "program" %token yPROPERTY "property" +%token yPROTECTED "protected" %token yPULLDOWN "pulldown" %token yPULLUP "pullup" %token yPURE "pure" @@ -455,10 +466,12 @@ class AstSenTree; %token ySTATIC__ETC "static" %token ySTRING "string" %token ySTRUCT "struct" +%token ySUPER "super" %token ySUPPLY0 "supply0" %token ySUPPLY1 "supply1" %token yTABLE "table" %token yTASK "task" +%token yTHIS "this" %token yTIME "time" %token yTIMEPRECISION "timeprecision" %token yTIMEUNIT "timeunit" @@ -480,6 +493,11 @@ class AstSenTree; %token yUNSIGNED "unsigned" %token yVAR "var" %token yVECTORED "vectored" +%token yVIRTUAL__CLASS "virtual-then-class" +%token yVIRTUAL__ETC "virtual" +%token yVIRTUAL__INTERFACE "virtual-then-interface" +%token yVIRTUAL__LEX "virtual-in-lex" +%token yVIRTUAL__anyID "virtual-then-identifier" %token yVOID "void" %token yWAIT "wait" %token yWAND "wand" @@ -800,7 +818,7 @@ package_or_generate_item_declaration: // ==IEEE: package_or_generate_item //UNSUP checker_declaration { $$ = $1; } | dpi_import_export { $$ = $1; } //UNSUP extern_constraint_declaration { $$ = $1; } - //UNSUP class_declaration { $$ = $1; } + | class_declaration { $$ = $1; } // // class_constructor_declaration is part of function_declaration | local_parameter_declaration ';' { $$ = $1; } | parameter_declaration ';' { $$ = $1; } @@ -917,6 +935,11 @@ parameter_value_assignmentE: // IEEE: [ parameter_value_assignment ] // // '#' delay_value { UNSUP } ; +parameter_value_assignmentClass: // IEEE: [ parameter_value_assignment ] (for classes) + // // Like parameter_value_assignment, but for classes only, which always have #() + '#' '(' cellparamList ')' { $$ = $3; } + ; + parameter_port_listE: // IEEE: parameter_port_list + empty == parameter_value_assignment /* empty */ { $$ = NULL; } | '#' '(' ')' { $$ = NULL; } @@ -1133,7 +1156,7 @@ anonymous_program_itemList: // IEEE: { anonymous_program_item } anonymous_program_item: // ==IEEE: anonymous_program_item task_declaration { $$ = $1; } | function_declaration { $$ = $1; } - //UNSUP class_declaration { $$ = $1; } + | class_declaration { $$ = $1; } //UNSUP covergroup_declaration { $$ = $1; } // // class_constructor_declaration is part of function_declaration | ';' { $$ = NULL; } @@ -1478,13 +1501,20 @@ simple_type: // ==IEEE: simple_type data_type: // ==IEEE: data_type // // This expansion also replicated elsewhere, IE data_type__AndID data_typeNoRef { $$ = $1; } + // + // // REFERENCES + // // // IEEE: [ class_scope | package_scope ] type_identifier { packed_dimension } - | ps_type packed_dimensionListE { $$ = GRAMMARP->createArray($1,$2,true); } - //UNSUP class_scope_type packed_dimensionListE { UNSUP } // // IEEE: class_type - //UNSUP class_typeWithoutId { $$ = $1; } // // IEEE: ps_covergroup_identifier - // // we put covergroups under ps_type, so can ignore this + // // Don't distinguish between types and classes so all these combined + | package_scopeIdFollowsE idRefDType packed_dimensionListE + { $2->packagep($1); + $$ = GRAMMARP->createArray($2, $3, true); } + | package_scopeIdFollowsE idRefDType parameter_value_assignmentClass packed_dimensionListE + { $2->packagep($1); + BBUNSUP($3->fileline(), "Unsupported: Parameter classes"); + $$ = GRAMMARP->createArray($2, $4, true); } ; data_typeBasic: // IEEE: part of data_type @@ -1502,8 +1532,13 @@ data_typeNoRef: // ==IEEE: data_type, excluding class_type etc referenc | ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); } | yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); } | yEVENT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::BIT); BBUNSUP($1, "Unsupported: event data types"); } - //UNSUP yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { UNSUP } - //UNSUP yVIRTUAL__anyID id/*interface*/ { UNSUP } + // // Rules overlap virtual_interface_declaration + // // Parameters here are SV2009 + // // IEEE has ['.' modport] but that will conflict with port + // // declarations which decode '.' modport themselves, so + // // instead see data_typeVar + | yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { $$ = NULL; BBUNSUP($1, "Unsupported: virtual interface"); } + | yVIRTUAL__anyID id/*interface*/ { $$ = NULL; BBUNSUP($1, "Unsupported: virtual data type"); } //UNSUP type_reference { UNSUP } // // IEEE: class_scope: see data_type above // // IEEE: class_type: see data_type above @@ -1521,6 +1556,10 @@ var_data_type: // ==IEEE: var_data_type | yVAR implicit_typeE { $$ = $2; } ; +//UNSUP type_reference: // ==IEEE: type_reference +//UNSUP yTYPE '(' exprOrDataType ')' { UNSUP } +//UNSUP ; + struct_unionDecl: // IEEE: part of data_type // // packedSigningE is NOP for unpacked ySTRUCT packedSigningE '{' { $$ = new AstStructDType($1, $2); SYMP->pushNew($$); } @@ -1568,7 +1607,7 @@ member_decl_assignment: // Derived from IEEE: variable_decl_assignment // // // IEEE: "[ covergroup_variable_identifier ] '=' class_new // // Pushed into variable_declExpr:class_new - //UNSUP '=' class_new { UNSUP } + | '=' class_new { NULL; BBUNSUP($1, "Unsupported: member declaration assignment with new()"); } ; list_of_variable_decl_assignments: // ==IEEE: list_of_variable_decl_assignments @@ -1591,7 +1630,7 @@ variable_decl_assignment: // ==IEEE: variable_decl_assignment // // // IEEE: "[ covergroup_variable_identifier ] '=' class_new // // Pushed into variable_declExpr:class_new - //UNSUP '=' class_new { UNSUP } + | '=' class_new { NULL; BBUNSUP($1, "Unsupported: declaration assignment with new()"); } ; list_of_tf_variable_identifiers: // ==IEEE: list_of_tf_variable_identifiers @@ -1609,8 +1648,8 @@ tf_variable_identifier: // IEEE: part of list_of_tf_variable_identifiers variable_declExpr: // IEEE: part of variable_decl_assignment - rhs of expr expr { $$ = $1; } - //UNSUP dynamic_array_new { $$ = $1; } - //UNSUP class_new { $$ = $1; } + | dynamic_array_new { $$ = $1; } + | class_new { $$ = $1; } ; variable_dimensionListE: // IEEE: variable_dimension + empty @@ -1721,11 +1760,25 @@ data_declaration: // ==IEEE: data_declaration // // Therefore the virtual_interface_declaration term isn't used ; +class_property: // ==IEEE: class_property, which is {property_qualifier} data_declaration + memberQualResetListE data_declarationVarClass { $$ = $2; } + | memberQualResetListE type_declaration { $$ = $2; } + | memberQualResetListE package_import_declaration { $$ = $2; } + // // IEEE: virtual_interface_declaration + // // "yVIRTUAL yID yID" looks just like a data_declaration + // // Therefore the virtual_interface_declaration term isn't used + ; + data_declarationVar: // IEEE: part of data_declaration // // The first declaration has complications between assuming what's the type vs ID declaring data_declarationVarFront list_of_variable_decl_assignments ';' { $$ = $2; } ; +data_declarationVarClass: // IEEE: part of data_declaration (for class_property) + // // The first declaration has complications between assuming what's the type vs ID declaring + data_declarationVarFrontClass list_of_variable_decl_assignments ';' { $$ = $2; } + ; + data_declarationVarFront: // IEEE: part of data_declaration // // Non-ANSI; used inside block followed by ';' // // SEE ALSO port_declaration, tf_port_declaration, port @@ -1748,6 +1801,21 @@ data_declarationVarFront: // IEEE: part of data_declaration // // = class_new is in variable_decl_assignment ; +data_declarationVarFrontClass: // IEEE: part of data_declaration (for class_property) + // // VARRESET called before this rule + // // yCONST is removed, added to memberQual rules + // // implicit_type expanded into /*empty*/ or "signingE rangeList" + yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE($3); } + | yVAR lifetimeE { VARRESET_NONLIST(VAR); } + | yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($1, LOGIC_IMPLICIT, $3), $4,true)); } + // + // // Expanded: "constE lifetimeE data_type" + | data_type { VARRESET_NONLIST(VAR); VARDTYPE($1); } + // // lifetime is removed, added to memberQual rules to avoid conflict + // // yCONST is removed, added to memberQual rules to avoid conflict + // // = class_new is in variable_decl_assignment + ; + implicit_typeE: // IEEE: part of *data_type_or_implicit // // Also expanded in data_declaration /* empty */ { $$ = NULL; } @@ -1767,8 +1835,8 @@ type_declaration: // ==IEEE: type_declaration | yTYPEDEF yENUM idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } | yTYPEDEF ySTRUCT idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } | yTYPEDEF yUNION idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } - //UNSUP yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } - //UNSUP yTYPEDEF yINTERFACE yCLASS idAny ';' { ... } + | yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } + | yTYPEDEF yINTERFACE yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($4, *$4); SYMP->reinsert($$); PARSEP->tagNodep($$); } ; dtypeAttrListE: @@ -1891,8 +1959,8 @@ bind_directive: // ==IEEE: bind_directive + bind_target_scope // // ';' - Note IEEE grammar is wrong, includes extra ';' - it's already in module_instantiation // // We merged the rules - id may be a bind_target_instance or module_identifier or interface_identifier yBIND bind_target_instance bind_instantiation { $$ = new AstBind($2, *$2, $3); } - | yBIND bind_target_instance ':' bind_target_instance_list bind_instantiation { - $$=NULL; BBUNSUP($1, "Unsupported: Bind with instance list"); } + | yBIND bind_target_instance ':' bind_target_instance_list bind_instantiation + { $$ = NULL; BBUNSUP($1, "Unsupported: Bind with instance list"); } ; bind_target_instance_list: // ==IEEE: bind_target_instance_list @@ -2451,8 +2519,8 @@ statement_item: // IEEE: statement_item // // IEEE: blocking_assignment // // 1800-2009 restricts LHS of assignment to new to not have a range // // This is ignored to avoid conflicts - //UNSUP fexprLvalue '=' class_new ';' { UNSUP } - //UNSUP fexprLvalue '=' dynamic_array_new ';' { UNSUP } + | fexprLvalue '=' class_new ';' { $$ = new AstAssign($2, $1, $3); } + | fexprLvalue '=' dynamic_array_new ';' { $$ = new AstAssign($2, $1, $3); } // // // IEEE: nonblocking_assignment | fexprLvalue yP_LTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); } @@ -2522,9 +2590,9 @@ statement_item: // IEEE: statement_item // // Because we've joined class_constructor_declaration into generic functions // // Way over-permissive; // // IEEE: [ ySUPER '.' yNEW [ '(' list_of_arguments ')' ] ';' ] - //UNSUP fexpr '.' class_new ';' { } + | fexpr '.' class_new ';' { $$ = NULL; BBUNSUP($1, "Unsupported: dotted new"); } // - | statementVerilatorPragmas { $$ = $1; } + | statementVerilatorPragmas { $$ = $1; } // // // IEEE: disable_statement | yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable($1,*$2); } @@ -2626,6 +2694,19 @@ finc_or_dec_expression: // ==IEEE: inc_or_dec_expression | yP_MINUSMINUS fexprLvalue { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true),new AstConst($1, AstConst::StringToParse(), "'b1"))); } ; +class_new: // ==IEEE: class_new + // // Special precence so (...) doesn't match expr + yNEW__ETC { $$ = new AstNew($1); } + | yNEW__ETC expr { $$ = new AstNew($1); BBUNSUP($1, "Unsupported: new with expression"); } + // // Grammer abiguity; we assume "new (x)" the () are a argument, not expr + | yNEW__PAREN '(' list_of_argumentsE ')' { $$ = new AstNew($1); BBUNSUP($1, "Unsupported: new with arguments"); } + ; + +dynamic_array_new: // ==IEEE: dynamic_array_new + yNEW__ETC '[' expr ']' { $$ = new AstNew($1); BBUNSUP($1, "Unsupported: Dynamic array new"); } + | yNEW__ETC '[' expr ']' '(' expr ')' { $$ = new AstNew($1); BBUNSUP($1, "Unsupported: Dynamic array new"); } + ; + //************************************************ // Case/If @@ -2831,17 +2912,27 @@ funcRef: // IEEE: part of tf_call task_subroutine_callNoMethod: // function_subroutine_callNoMethod (as task) // // IEEE: tf_call taskRef { $$ = $1; } + //UNSUP funcRef yWITH__PAREN '(' expr ')' { /*UNSUP*/ } | system_t_call { $$ = $1; } // // IEEE: method_call requires a "." so is in expr - //UNSUP randomize_call { $$ = $1; } + // // IEEE: ['std::'] not needed, as normal std package resolution will find it + // // IEEE: randomize_call + // // We implement randomize as a normal funcRef, since randomize isn't a keyword + // // Note yNULL is already part of expressions, so they come for free + //UNSUP funcRef yWITH__CUR constraint_block { } ; function_subroutine_callNoMethod: // IEEE: function_subroutine_call (as function) // // IEEE: tf_call funcRef { $$ = $1; } + //UNSUP funcRef yWITH__PAREN '(' expr ')' { /*UNSUP*/ } | system_f_call { $$ = $1; } // // IEEE: method_call requires a "." so is in expr - //UNSUP randomize_call { $$ = $1; } + // // IEEE: ['std::'] not needed, as normal std package resolution will find it + // // IEEE: randomize_call + // // We implement randomize as a normal funcRef, since randomize isn't a keyword + // // Note yNULL is already part of expressions, so they come for free + //UNSUP funcRef yWITH__CUR constraint_block { } ; system_t_call: // IEEE: system_tf_call (as task) @@ -3039,6 +3130,10 @@ function_declaration: // IEEE: function_declaration + function_body_decl { $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5); SYMP->popScope($$); GRAMMARP->endLabel($7,$$,$7); } + | yFUNCTION lifetimeE funcIdNew funcIsolateE tfGuts yENDFUNCTION endLabelE + { $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5); + SYMP->popScope($$); + GRAMMARP->endLabel($7,$$,$7); } ; function_prototype: // IEEE: function_prototype @@ -3046,6 +3141,11 @@ function_prototype: // IEEE: function_prototype | yFUNCTION funcId { $$=$2; $$->prototype(true); SYMP->popScope($$); } ; +class_constructor_prototype: // ==IEEE: class_constructor_prototype + yFUNCTION funcIdNew '(' tf_port_listE ')' ';' { $$ = $2; $$->addStmtsp($4); $$->prototype(true); SYMP->popScope($$); } + | yFUNCTION funcIdNew ';' { $$ = $2; $$->prototype(true); SYMP->popScope($$); } + ; + funcIsolateE: /* empty */ { $$ = 0; } | yVL_ISOLATE_ASSIGNMENTS { $$ = 1; } @@ -3097,11 +3197,27 @@ funcId: // IEEE: function_data_type_or_implicit + part of function_bod SYMP->pushNewUnder($$, NULL); } ; +funcIdNew: // IEEE: from class_constructor_declaration + yNEW__ETC + { $$ = new AstFunc($1, "new", NULL, NULL); + BBUNSUP($1, "Unsupported: new constructor"); + SYMP->pushNewUnder($$, NULL); } + | yNEW__PAREN + { $$ = new AstFunc($1, "new", NULL, NULL); + BBUNSUP($1, "Unsupported: new constructor"); + SYMP->pushNewUnder($$, NULL); } + | class_scopeWithoutId yNEW__PAREN + { $$ = new AstFunc($2, "new", NULL, NULL); + BBUNSUP($2, "Unsupported: scoped new constructor"); + SYMP->pushNewUnder($$, NULL); } + ; + tfIdScoped: // IEEE: part of function_body_declaration/task_body_declaration // // IEEE: [ interface_identifier '.' | class_scope ] function_identifier id { $$=$1; $$ = $1; } - //UNSUP id/*interface_identifier*/ '.' id { UNSUP } - //UNSUP class_scope_id { UNSUP } + | id/*interface_identifier*/ '.' id { $$=$3; $$ = $3; BBUNSUP($2, "Unsupported: Out of block function declaration"); } + | class_scopeIdFollows id { $$=$2; $$=$1; $$=$2; + BBUNSUP($1, "Unsupported: Out of class block function declaration"); } ; tfGuts: @@ -3368,8 +3484,7 @@ expr: // IEEE: part of expression/constant_expression/primary // // Indistinguishable from function_subroutine_call:method_call // | '$' { $$ = new AstUnbounded($1); } - | yNULL { $$ = new AstConst($1, AstConst::LogicFalse()); - BBUNSUP($1, "Unsupported: null expression"); } + | yNULL { $$ = new AstConst($1, AstConst::LogicFalse()); } // // IEEE: yTHIS // // See exprScope // @@ -3442,15 +3557,17 @@ exprScope: // scope and variable for use to inside an expression // // IEEE: [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select // // Or method_call_body without parenthesis // // See also varRefClassBit, which is the non-expr version of most of this - //UNSUP yTHIS { UNSUP } - idArrayed { $$ = $1; } + yTHIS { $$ = new AstConst($1, AstConst::LogicFalse()); + BBUNSUP($1, "Unsupported: this"); } + | idArrayed { $$ = $1; } | package_scopeIdFollows idArrayed { $$ = AstDot::newIfPkg($2->fileline(), $1, $2); } - //UNSUP class_scopeIdFollows idArrayed { UNSUP } + | class_scopeIdFollows idArrayed { $$ = $2; BBUNSUP($1, "Unsupported: scoped class reference"); } | ~l~expr '.' idArrayed { $$ = new AstDot($2,$1,$3); } // // expr below must be a "yTHIS" - //UNSUP ~l~expr '.' ySUPER { UNSUP } + | ~l~expr '.' ySUPER { $$ = $1; BBUNSUP($3, "Unsupported: super"); } // // Part of implicit_class_handle - //UNSUP ySUPER { UNSUP } + | ySUPER { $$ = new AstConst($1, AstConst::LogicFalse()); + BBUNSUP($1, "Unsupported: super"); } ; fexprScope: // exprScope, For use as first part of statement (disambiguates <=) @@ -3823,6 +3940,11 @@ idAny: // Any kind of identifier | yaID__ETC { $$ = $1; $$=$1; } ; +idRefDType: // IEEE: class_identifier or other type identifier + // Used where reference is needed + yaID__aTYPE { $$ = new AstRefDType($1, *$1); } + ; + idSVKwd: // Warn about non-forward compatible Verilog 2001 code // // yBIT, yBYTE won't work here as causes conflicts yDO { static string s = "do" ; $$ = &s; ERRSVKWD($1,*$$); $$=$1; } @@ -3850,12 +3972,12 @@ variable_lvalueConcList: // IEEE: part of variable_lvalue: '{' variable_l idClassSel: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged variable idDotted { $$ = $1; } // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select - //UNSUP yTHIS '.' idDotted { UNSUP } - //UNSUP ySUPER '.' idDotted { UNSUP } - //UNSUP yTHIS '.' ySUPER '.' idDotted { UNSUP } + | yTHIS '.' idDotted { $$ = $3; BBUNSUP($1, "Unsupported: this"); } + | ySUPER '.' idDotted { $$ = $3; BBUNSUP($1, "Unsupported: super"); } + | yTHIS '.' ySUPER '.' idDotted { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); } // // Expanded: package_scope idDotted - //UNSUP class_scopeIdFollows idDotted { UNSUP } - //UNSUP package_scopeIdFollows idDotted { UNSUP } + | class_scopeIdFollows idDotted { $$ = $2; BBUNSUP($2, "Unsupported: package scoped id"); } + | package_scopeIdFollows idDotted { $$ = $2; BBUNSUP($2, "Unsupported: class scoped id"); } ; idDotted: @@ -3919,7 +4041,7 @@ strAsText: endLabelE: /* empty */ { $$ = NULL; $$=NULL; } | ':' idAny { $$ = $2; $$=$2; } - //UNSUP ':' yNEW__ETC { $$ = $2; $$=$2; } + | ':' yNEW__ETC { static string n = "new"; $$ = &n; $$=$2; } ; //************************************************ @@ -4037,6 +4159,65 @@ property_spec: // IEEE: property_spec //********************************************************************** // Class +class_declaration: // ==IEEE: part of class_declaration + // // IEEE-2012: using this also for interface_class_declaration + // // The classExtendsE rule relys on classFront having the + // // new class scope correct via classFront + classFront parameter_port_listE classExtendsE classImplementsE ';' + class_itemListE yENDCLASS endLabelE + { $$ = $1; $1->addMembersp($2); + $1->addMembersp($4); $1->addMembersp($6); + SYMP->popScope($$); + GRAMMARP->endLabel($7, $1, $8); } + ; + +classFront: // IEEE: part of class_declaration + classVirtualE yCLASS lifetimeE idAny/*class_identifier*/ + { $$ = new AstClass($2, *$4); + SYMP->pushNew($$); + BBUNSUP($2, "Unsupported: classes"); } + // // IEEE: part of interface_class_declaration + | yINTERFACE yCLASS lifetimeE idAny/*class_identifier*/ + { $$ = new AstClass($2, *$4); + SYMP->pushNew($$); + BBUNSUP($2, "Unsupported: interface classes"); } + ; + +classVirtualE: + /* empty */ { } + | yVIRTUAL__CLASS { BBUNSUP($1, "Unsupported: virtual classes"); } + ; + +classExtendsE: // IEEE: part of class_declaration + // // The classExtendsE rule relys on classFront having the + // // new class scope correct via classFront + /* empty */ { $$ = NULL; } + | yEXTENDS classExtendsList { $$ = $2; } + ; + +classExtendsList: // IEEE: part of class_declaration + classExtendsOne { $$ = $1; } + | classExtendsList ',' classExtendsOne { $$ = AstNode::addNextNull($1, $3); } + ; + +classExtendsOne: // IEEE: part of class_declaration + class_typeWithoutId { $$ = NULL; BBUNSUP($1, "Unsupported: extends"); } + // // IEEE: Might not be legal to have more than one set of parameters in an extends + | class_typeWithoutId '(' list_of_argumentsE ')' { $$ = NULL; BBUNSUP($1, "Unsupported: extends"); } + ; + +classImplementsE: // IEEE: part of class_declaration + // // All 1800-2012 + /* empty */ { $$ = NULL; } + | yIMPLEMENTS classImplementsList { $$ = $2; } + ; + +classImplementsList: // IEEE: part of class_declaration + // // All 1800-2012 + class_typeWithoutId { $$ = NULL; BBUNSUP($1, "Unsupported: implements class"); } + | classImplementsList ',' class_typeWithoutId { $$ = AstNode::addNextNull($1, $3); } + ; + //========= // Package scoping - to traverse the symbol table properly, the final identifer // must be included in the rules below. @@ -4049,13 +4230,48 @@ ps_id_etc: // package_scope + general id ps_type: // IEEE: ps_parameter_identifier | ps_type_identifier // Even though we looked up the type and have a AstNode* to it, // we can't fully resolve it because it may have been just a forward definition. - package_scopeIdFollowsE yaID__aTYPE { $$ = new AstRefDType($2, *$2); VN_CAST($$, RefDType)->packagep($1); } + package_scopeIdFollowsE idRefDType { $$ = $2; $2->packagep($1); } // // Simplify typing - from ps_covergroup_identifier - //UNSUP package_scopeIdFollowsE yaID__aCOVERGROUP { $$=$1; $$=$1+$2; } ; //=== Below rules assume special scoping per above +class_typeWithoutId: // as with class_typeWithoutId but allow yaID__aTYPE + // // and we thus don't need to resolve it in specified package + package_scopeIdFollowsE class_typeOneList { $$ = $2; $2->packagep($1); } + ; + +class_scopeWithoutId: // class_type standalone without following id + // // and we thus don't need to resolve it in specified package + class_scopeIdFollows { $$ = $1; } + ; + +class_scopeIdFollows: // IEEE: class_scope + type + // // IEEE: "class_type yP_COLONCOLON" + // // IMPORTANT: The lexer will parse the following ID to be in the found package + // // But class_type:'::' conflicts with class_scope:'::' so expand here + package_scopeIdFollowsE class_typeOneListColonIdFollows + { $$ = NULL; BBUNSUP(CRELINE(), "Unsupported: scoped class reference"); } + ; + +class_typeOneListColonIdFollows: // IEEE: class_type :: but allow yaID__aTYPE + class_typeOneList yP_COLONCOLON { BBUNSUP($2, "Unsupported: Hierarchical class references"); } + ; + +class_typeOneList: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE + // // If you follow the rules down, class_type is really a list via ps_class_identifier + // // Must propagate scp up for next id + class_typeOne { $$ = $1; } + | class_typeOneListColonIdFollows class_typeOne { $$ = $2; /*UNSUP*/ } + ; + +class_typeOne: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE + // // If you follow the rules down, class_type is really a list via ps_class_identifier + // // Not listed in IEEE, but see bug627 any parameter type maybe a class + idRefDType parameter_value_assignmentE + { $$ = $1; if ($2) BBUNSUP($2->fileline(), "Unsupported: Parameterized classes"); } + ; + package_scopeIdFollowsE: // IEEE: [package_scope] // // IMPORTANT: The lexer will parse the following ID to be in the found package // // class_qualifier := [ yLOCAL '::' ] [ implicit_class_handle '.' class_scope ] @@ -4074,6 +4290,81 @@ package_scopeIdFollows: // IEEE: package_scope //UNSUP /*cont*/ yP_COLONCOLON { UNSUP } ; +//^^^========= + +class_itemListE: + /* empty */ { $$ = NULL; } + | class_itemList { $$ = $1; } + ; + +class_itemList: + class_item { $$ = $1; } + | class_itemList class_item { $$ = AstNode::addNextNull($1, $2); } + ; + +class_item: // ==IEEE: class_item + class_property { $$ = $1; } + | class_method { $$ = $1; } + //UNSUP class_constraint { $$ = $1; } + // + | class_declaration { $$ = NULL; BBUNSUP($1, "Unsupported: class within class"); } + | timeunits_declaration { $$ = $1; } + //UNSUP covergroup_declaration { $$ = $1; } + | local_parameter_declaration ';' { $$ = $1; BBUNSUP($2, "Unsupported: class parameters"); } // 1800-2009 + | parameter_declaration ';' { $$ = $1; BBUNSUP($2, "Unsupported: class parameters"); } // 1800-2009 + | ';' { $$ = NULL; } + // + | error ';' { $$ = NULL; } + ; + +class_method: // ==IEEE: class_method + memberQualResetListE task_declaration { $$ = $2; } + | memberQualResetListE function_declaration { $$ = $2; } + | yPURE yVIRTUAL__ETC memberQualResetListE method_prototype ';' + { $$ = NULL; BBUNSUP($1, "Unsupported: pure virtual class method"); } + | yEXTERN memberQualResetListE method_prototype ';' + { $$ = NULL; BBUNSUP($1, "Unsupported: extern class method prototype"); } + // // IEEE: "method_qualifierE class_constructor_declaration" + // // part of function_declaration + | yEXTERN memberQualResetListE class_constructor_prototype + { $$ = NULL; BBUNSUP($1, "Unsupported: extern class"); } + ; + +// IEEE: class_constructor_prototype +// See function_declaration + +class_item_qualifier: // IEEE: class_item_qualifier minus ySTATIC + // // IMPORTANT: yPROTECTED | yLOCAL is in a lex rule + yPROTECTED { $$ = NULL; } // Ignoring protected until implemented + | yLOCAL__ETC { $$ = NULL; BBUNSUP($1, "Unsupported: 'local' class item"); } + | ySTATIC__ETC { $$ = NULL; BBUNSUP($1, "Unsupported: 'static' class item"); } + ; + +memberQualResetListE: // Called from class_property for all qualifiers before yVAR + // // Also before method declarations, to prevent grammar conflict + // // Thus both types of qualifiers (method/property) are here + /*empty*/ { $$ = NULL; } + | memberQualList { $$ = $1; } + ; + +memberQualList: + memberQualOne { $$ = $1; } + | memberQualList memberQualOne { $$ = AstNode::addNextNull($1, $2); } + ; + +memberQualOne: // IEEE: property_qualifier + method_qualifier + // // Part of method_qualifier and property_qualifier + class_item_qualifier { $$ = $1; } + // // Part of method_qualifier only + | yVIRTUAL__ETC { $$ = NULL; BBUNSUP($1, "Unsupported: virtual class member qualifier"); } + // // Part of property_qualifier only + | random_qualifier { $$ = NULL; } + // // Part of lifetime, but here as ySTATIC can be in different positions + | yAUTOMATIC { $$ = NULL; BBUNSUP($1, "Unsupported: automatic class member qualifier"); } + // // Part of data_declaration, but not in data_declarationVarFrontClass + | yCONST__ETC { $$ = NULL; BBUNSUP($1, "Unsupported: const class member qualifier"); } + ; + //********************************************************************** // Constraints diff --git a/test_regress/t/t_flag_wpedantic_bad.out b/test_regress/t/t_flag_wpedantic_bad.out index e59968538..26e8ff0ae 100644 --- a/test_regress/t/t_flag_wpedantic_bad.out +++ b/test_regress/t/t_flag_wpedantic_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_flag_wpedantic_bad.v:7: syntax error, unexpected global, expecting IDENTIFIER or do or final +%Error: t/t_flag_wpedantic_bad.v:7: syntax error, unexpected global, expecting IDENTIFIER or '=' or do or final reg global; ^ %Error: Exiting due to