diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 79c0680ba..89e5de755 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -22,5 +22,233 @@ #include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict //====================================================================== -// The guts came from bison +// The guts come from bison output + #include "V3ParseBison.c" + +//====================================================================== +// V3ParseImp functions requiring bison state + +int V3ParseImp::bisonParse() { + // Use --debugi-bison 9 to enable this + if (PARSEP->debugBison()>=9) yydebug = 1; + return yyparse(); +} + +const char* V3ParseImp::tokenName(int token) { +#if YYDEBUG || YYERROR_VERBOSE + static const char** nameTablep = NULL; + if (!nameTablep) { + int size; + for (size = 0; yytname[size]; ++size) ; + nameTablep = new const char* [size]; + // Workaround bug in bison's which have '!' in yytname but not token values + int iout = 0; + for (int i = 0; yytname[i]; ++i) { + if (yytname[i][0] == '\'') continue; + nameTablep[iout++] = yytname[i]; + } + } + if (token >= 255) { + return nameTablep[token-255]; + } else { + static char ch[2]; ch[0] = token; ch[1] = '\0'; + return ch; + } +#else + return ""; +#endif +} + +void V3ParseImp::parserClear() { + // Clear up any dynamic memory V3Parser required + VARDTYPE(NULL); +} + +//====================================================================== +// V3ParseGrammar functions requiring bison state + +void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) { + // Convert list of expressions to list of arguments + AstNode* outp = NULL; + while (nodep->pinsp()) { + AstNode* exprp = nodep->pinsp()->unlinkFrBack(); + // addNext can handle nulls: + outp = AstNode::addNext(outp, new AstArg(exprp->fileline(), "", exprp)); + } + if (outp) nodep->addPinsp(outp); +} + +AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) { + return new AstAssignW(fileline, new AstVarRef(fileline, name, true), + new AstConst(fileline, AstConst::StringToParse(), + (value ? "'1" : "'0"))); +} + +AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) { + // Remove any UnsizedRange's from list + for (AstNodeRange* nodep = nrangep, *nextp; nodep; nodep = nextp) { + nextp = VN_CAST(nrangep->nextp(), NodeRange); + if (!VN_IS(nodep, Range)) { + nodep->v3error("Unsupported or syntax error: Unsized range in cell or other declaration"); + nodep->unlinkFrBack(); nodep->deleteTree(); VL_DANGLING(nodep); + } + } + return VN_CAST(nrangep, Range); +} + +AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, + AstNodeRange* nrangep, bool isPacked) { + // Split RANGE0-RANGE1-RANGE2 + // into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3), RANGE), RANGE) + AstNodeDType* arrayp = basep; + if (nrangep) { // Maybe no range - return unmodified base type + while (nrangep->nextp()) nrangep = VN_CAST(nrangep->nextp(), NodeRange); + while (nrangep) { + AstNodeRange* prevp = VN_CAST(nrangep->backp(), NodeRange); + if (prevp) nrangep->unlinkFrBack(); + AstRange* rangep = VN_CAST(nrangep, Range); + if (!rangep) { + if (!VN_IS(nrangep, UnsizedRange)) { + nrangep->v3fatalSrc("Expected range or unsized range"); + } + arrayp = new AstUnsizedArrayDType + (nrangep->fileline(), VFlagChildDType(), arrayp); + } else if (isPacked) { + arrayp = new AstPackArrayDType + (rangep->fileline(), VFlagChildDType(), arrayp, rangep); + } else { + arrayp = new AstUnpackArrayDType + (rangep->fileline(), VFlagChildDType(), arrayp, rangep); + } + nrangep = prevp; + } + } + return arrayp; +} + +AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, + AstNodeRange* arrayp, AstNode* attrsp) { + AstNodeDType* dtypep = GRAMMARP->m_varDTypep; + UINFO(5," creVar "<m_varIO == VDirection::NONE + && GRAMMARP->m_varDecl == AstVarType::PORT) { + // Just a port list with variable name (not v2k format); AstPort already created + if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists"); + return NULL; + } + if (GRAMMARP->m_varDecl == AstVarType::WREAL) { + // dtypep might not be null, might be implicit LOGIC before we knew better + dtypep = new AstBasicDType(fileline, AstBasicDTypeKwd::DOUBLE); + } + if (!dtypep) { // Created implicitly + dtypep = new AstBasicDType(fileline, LOGIC_IMPLICIT); + } else { // May make new variables with same type, so clone + dtypep = dtypep->cloneTree(false); + } + //UINFO(0,"CREVAR "<ascii()<<" decl="<m_varDecl.ascii()<<" io="<m_varIO.ascii()<m_varDecl; + if (type == AstVarType::UNKNOWN) { + if (GRAMMARP->m_varIO.isAny()) { + type = AstVarType::PORT; + } else { + fileline->v3fatalSrc("Unknown signal type declared"); + } + } + if (type == AstVarType::GENVAR) { + if (arrayp) fileline->v3error("Genvars may not be arrayed: "<addAttrsp(attrsp); + if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl); + if (GRAMMARP->m_varIO != VDirection::NONE) { + nodep->declDirection(GRAMMARP->m_varIO); + nodep->direction(GRAMMARP->m_varIO); + } + + if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) { + nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0)); + } + if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) { + nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1)); + } + if (VN_IS(dtypep, ParseTypeDType)) { + // Parser needs to know what is a type + AstNode* newp = new AstTypedefFwd(fileline, name); + nodep->addNext(newp); + SYMP->reinsert(newp); + } + // Don't set dtypep in the ranging; + // We need to autosize parameters and integers separately + // + // Propagate from current module tracing state + if (nodep->isGenVar()) nodep->trace(false); + else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false); + else nodep->trace(allTracingOn(nodep->fileline())); + + // Remember the last variable created, so we can attach attributes to it in later parsing + GRAMMARP->m_varAttrp = nodep; + PARSEP->tagNodep(GRAMMARP->m_varAttrp); + return nodep; +} + +string V3ParseGrammar::deQuote(FileLine* fileline, string text) { + // Fix up the quoted strings the user put in, for example "\"" becomes " + // Reverse is V3OutFormatter::quoteNameControls(...) + bool quoted = false; + string newtext; + unsigned char octal_val = 0; + int octal_digits = 0; + for (string::const_iterator cp = text.begin(); cp != text.end(); ++cp) { + if (quoted) { + if (isdigit(*cp)) { + octal_val = octal_val*8 + (*cp-'0'); + if (++octal_digits == 3) { + octal_digits = 0; + quoted = false; + newtext += octal_val; + } + } else { + if (octal_digits) { + // Spec allows 1-3 digits + octal_digits = 0; + quoted = false; + newtext += octal_val; + --cp; // Backup to reprocess terminating character as non-escaped + continue; + } + quoted = false; + if (*cp == 'n') newtext += '\n'; + else if (*cp == 'a') newtext += '\a'; // SystemVerilog 3.1 + else if (*cp == 'f') newtext += '\f'; // SystemVerilog 3.1 + else if (*cp == 'r') newtext += '\r'; + else if (*cp == 't') newtext += '\t'; + else if (*cp == 'v') newtext += '\v'; // SystemVerilog 3.1 + else if (*cp == 'x' && isxdigit(cp[1]) && isxdigit(cp[2])) { // SystemVerilog 3.1 +#define vl_decodexdigit(c) ((isdigit(c)?((c)-'0'):(tolower((c))-'a'+10))) + newtext += (char)(16*vl_decodexdigit(cp[1]) + vl_decodexdigit(cp[2])); + cp += 2; + } + else if (isalnum(*cp)) { + fileline->v3error("Unknown escape sequence: \\"<<*cp); + break; + } + else newtext += *cp; + } + } + else if (*cp == '\\') { + quoted = true; + octal_digits = 0; + } + else if (*cp != '"') { + newtext += *cp; + } + } + return newtext; +} diff --git a/src/verilog.y b/src/verilog.y index c05d2a237..2d51cc7c6 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -4042,217 +4042,7 @@ vltOnFront: //********************************************************************** %% - -int V3ParseImp::bisonParse() { - // Use --debugi-bison 9 to enable this - if (PARSEP->debugBison()>=9) yydebug = 1; - return yyparse(); -} - -const char* V3ParseImp::tokenName(int token) { -#if YYDEBUG || YYERROR_VERBOSE - static const char** nameTablep = NULL; - if (!nameTablep) { - int size; - for (size=0; yytname[size]; ++size) ; - nameTablep = new const char* [size]; - // Workaround bug in bison's which have '!' in yytname but not token values - int iout = 0; - for (int i=0; yytname[i]; ++i) { - if (yytname[i][0] == '\'') continue; - nameTablep[iout++] = yytname[i]; - } - } - if (token >= 255) { - return nameTablep[token-255]; - } else { - static char ch[2]; ch[0]=token; ch[1]='\0'; - return ch; - } -#else - return ""; -#endif -} - -void V3ParseImp::parserClear() { - // Clear up any dynamic memory V3Parser required - VARDTYPE(NULL); -} - -void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) { - // Convert list of expressions to list of arguments - AstNode* outp = NULL; - while (nodep->pinsp()) { - AstNode* exprp = nodep->pinsp()->unlinkFrBack(); - // addNext can handle nulls: - outp = AstNode::addNext(outp, new AstArg(exprp->fileline(), "", exprp)); - } - if (outp) nodep->addPinsp(outp); -} - -AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) { - return new AstAssignW(fileline, new AstVarRef(fileline, name, true), - new AstConst(fileline, AstConst::StringToParse(), - (value ? "'1" : "'0"))); -} - -AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) { - // Remove any UnsizedRange's from list - for (AstNodeRange* nodep = nrangep, *nextp; nodep; nodep=nextp) { - nextp = VN_CAST(nrangep->nextp(), NodeRange); - if (!VN_IS(nodep, Range)) { - nodep->v3error("Unsupported or syntax error: Unsized range in cell or other declaration"); - nodep->unlinkFrBack(); nodep->deleteTree(); VL_DANGLING(nodep); - } - } - return VN_CAST(nrangep, Range); -} - -AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstNodeRange* nrangep, bool isPacked) { - // Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE) - AstNodeDType* arrayp = basep; - if (nrangep) { // Maybe no range - return unmodified base type - while (nrangep->nextp()) nrangep = VN_CAST(nrangep->nextp(), NodeRange); - while (nrangep) { - AstNodeRange* prevp = VN_CAST(nrangep->backp(), NodeRange); - if (prevp) nrangep->unlinkFrBack(); - AstRange* rangep = VN_CAST(nrangep, Range); - if (!rangep) { - if (!VN_IS(nrangep, UnsizedRange)) nrangep->v3fatalSrc("Expected range or unsized range"); - arrayp = new AstUnsizedArrayDType(nrangep->fileline(), VFlagChildDType(), arrayp); - } else if (isPacked) { - arrayp = new AstPackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep); - } else { - arrayp = new AstUnpackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep); - } - nrangep = prevp; - } - } - return arrayp; -} - -AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeRange* arrayp, AstNode* attrsp) { - AstNodeDType* dtypep = GRAMMARP->m_varDTypep; - UINFO(5," creVar "<m_varIO == VDirection::NONE - && GRAMMARP->m_varDecl == AstVarType::PORT) { - // Just a port list with variable name (not v2k format); AstPort already created - if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists"); - return NULL; - } - if (GRAMMARP->m_varDecl == AstVarType::WREAL) { - // dtypep might not be null, might be implicit LOGIC before we knew better - dtypep = new AstBasicDType(fileline,AstBasicDTypeKwd::DOUBLE); - } - if (!dtypep) { // Created implicitly - dtypep = new AstBasicDType(fileline, LOGIC_IMPLICIT); - } else { // May make new variables with same type, so clone - dtypep = dtypep->cloneTree(false); - } - //UINFO(0,"CREVAR "<ascii()<<" decl="<m_varDecl.ascii()<<" io="<m_varIO.ascii()<m_varDecl; - if (type == AstVarType::UNKNOWN) { - if (GRAMMARP->m_varIO.isAny()) { - type = AstVarType::PORT; - } else { - fileline->v3fatalSrc("Unknown signal type declared"); - } - } - if (type == AstVarType::GENVAR) { - if (arrayp) fileline->v3error("Genvars may not be arrayed: "<addAttrsp(attrsp); - if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl); - if (GRAMMARP->m_varIO != VDirection::NONE) { - nodep->declDirection(GRAMMARP->m_varIO); - nodep->direction(GRAMMARP->m_varIO); - } - - if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) { - nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0)); - } - if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) { - nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1)); - } - if (VN_IS(dtypep, ParseTypeDType)) { - // Parser needs to know what is a type - AstNode* newp = new AstTypedefFwd(fileline, name); - nodep->addNext(newp); - SYMP->reinsert(newp); - } - // Don't set dtypep in the ranging; - // We need to autosize parameters and integers separately - // - // Propagate from current module tracing state - if (nodep->isGenVar()) nodep->trace(false); - else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false); - else nodep->trace(allTracingOn(nodep->fileline())); - - // Remember the last variable created, so we can attach attributes to it in later parsing - GRAMMARP->m_varAttrp = nodep; - PARSEP->tagNodep(GRAMMARP->m_varAttrp); - return nodep; -} - -string V3ParseGrammar::deQuote(FileLine* fileline, string text) { - // Fix up the quoted strings the user put in, for example "\"" becomes " - // Reverse is V3OutFormatter::quoteNameControls(...) - bool quoted = false; - string newtext; - unsigned char octal_val = 0; - int octal_digits = 0; - for (string::const_iterator cp=text.begin(); cp!=text.end(); ++cp) { - if (quoted) { - if (isdigit(*cp)) { - octal_val = octal_val*8 + (*cp-'0'); - if (++octal_digits == 3) { - octal_digits = 0; - quoted = false; - newtext += octal_val; - } - } else { - if (octal_digits) { - // Spec allows 1-3 digits - octal_digits = 0; - quoted = false; - newtext += octal_val; - --cp; // Backup to reprocess terminating character as non-escaped - continue; - } - quoted = false; - if (*cp == 'n') newtext += '\n'; - else if (*cp == 'a') newtext += '\a'; // SystemVerilog 3.1 - else if (*cp == 'f') newtext += '\f'; // SystemVerilog 3.1 - else if (*cp == 'r') newtext += '\r'; - else if (*cp == 't') newtext += '\t'; - else if (*cp == 'v') newtext += '\v'; // SystemVerilog 3.1 - else if (*cp == 'x' && isxdigit(cp[1]) && isxdigit(cp[2])) { // SystemVerilog 3.1 -#define vl_decodexdigit(c) ((isdigit(c)?((c)-'0'):(tolower((c))-'a'+10))) - newtext += (char)(16*vl_decodexdigit(cp[1]) + vl_decodexdigit(cp[2])); - cp += 2; - } - else if (isalnum(*cp)) { - fileline->v3error("Unknown escape sequence: \\"<<*cp); - break; - } - else newtext += *cp; - } - } - else if (*cp == '\\') { - quoted = true; - octal_digits = 0; - } - else if (*cp != '"') { - newtext += *cp; - } - } - return newtext; -} +// For implementation functions see V3ParseGrammar.cpp //YACC = /kits/sources/bison-2.4.1/src/bison --report=lookahead // --report=lookahead