public static MDDataType parseBasicDataType(MDMang dmang, boolean isHighest)
			throws MDException {
		MDDataType dt;
		char code = dmang.getAndIncrement();
		switch (code) {
			case '?':
				// Not sure if this should be here or other place.  I suppose could have a
				//  reference to one of these, so wouldn't want it in "Primary" data types
				dt = new MDCustomType(dmang);
				break;
			case '$':
				dt = parseSpecialExtendedType(dmang, isHighest);
				break;
			case 'C':
				dt = new MDCharDataType(dmang);
				dt.setSigned();
				break;
			case 'D':
				dt = new MDCharDataType(dmang);
				break;
			case 'E':
				dt = new MDCharDataType(dmang);
				dt.setUnsigned();
				break;
			case 'F':
				dt = new MDShortDataType(dmang);
				break;
			case 'G':
				dt = new MDShortDataType(dmang);
				dt.setUnsigned();
				break;
			case 'H':
				dt = new MDIntDataType(dmang);
				break;
			case 'I':
				dt = new MDIntDataType(dmang);
				dt.setUnsigned();
				break;
			case 'J':
				dt = new MDLongDataType(dmang);
				break;
			case 'K':
				dt = new MDLongDataType(dmang);
				dt.setUnsigned();
				break;
			case 'L': // Unknown complex type: UINFO: "segment" type
				dt = new MDComplexType(dmang);
				break;
			case 'M':
				dt = new MDFloatDataType(dmang);
				break;
			case 'N':
				dt = new MDDoubleDataType(dmang);
				break;
			case 'O':
				dt = new MDLongDoubleDataType(dmang);
				break;
			case 'P':
				dt = new MDPointerType(dmang, isHighest, false, false);
				break;
			case 'Q':
				dt = new MDPointerType(dmang, isHighest, true, false);
				break;
			case 'R':
				dt = new MDPointerType(dmang, isHighest, false, true);
				break;
			case 'S':
				dt = new MDPointerType(dmang, isHighest, true, true);
				break;
			case 'T':
				dt = new MDUnionType(dmang);
				break;
			case 'U':
				dt = new MDStructType(dmang);
				break;
			case 'V':
				dt = new MDClassType(dmang);
				break;
			case 'W':
				dt = new MDEnumType(dmang);
				break;
			case 'X': // Purposefully redundant (also found in parsdDataType)
				// The wiki document says 'X' can be void or coclass, but we have never been able
				//  to make coclass manifest itself, so we are factoring out the code that could
				//  have allowed it: This was MDMang.xVoidPermitted(), which read a flag from
				//  MDContext.  The ability is also being factored out of MDContext.
				dt = new MDVoidDataType(dmang);
				break;
			case 'Y':
				dt = new MDCointerfaceType(dmang, 1);
				break;
			case 'Z':
				//There really is no data path to get us to this case 'Z', so will never get cover.
				dt = new MDVarArgsType(dmang);
				break;
			case '_': // Extended types
				code = dmang.getAndIncrement();
				switch (code) {
					case '$':
						dt = new MDW64Type(dmang);
						break;
					case 'D':
						dt = new MDInt8DataType(dmang);
						break;
					case 'E':
						dt = new MDInt8DataType(dmang);
						dt.setUnsigned();
						break;
					case 'F':
						dt = new MDInt16DataType(dmang);
						break;
					case 'G':
						dt = new MDInt16DataType(dmang);
						dt.setUnsigned();
						break;
					case 'H':
						dt = new MDInt32DataType(dmang);
						break;
					case 'I':
						dt = new MDInt32DataType(dmang);
						dt.setUnsigned();
						break;
					case 'J':
						dt = new MDInt64DataType(dmang);
						break;
					case 'K':
						dt = new MDInt64DataType(dmang);
						dt.setUnsigned();
						break;
					case 'L':
						dt = new MDInt128DataType(dmang);
						break;
					case 'M':
						dt = new MDInt128DataType(dmang);
						dt.setUnsigned();
						break;
					case 'N':
						dt = new MDBoolDataType(dmang);
						break;
					case 'O':
						// TODO: possibly change this to ExtendedDataType (currently 'O' ArrayType
						//  is a "ModifiedType")--investigate further
						// 20230731: note that this class uses a CVMod type, which support its
						//  being a MDModifierType.
						dt = new MDArrayBasicType(dmang);
						break;
					case 'P':
						dt = new MDUnknownPExtendedDataType(dmang);
						break;
					case 'Q':
						dt = new MDChar8DataType(dmang);
						break;
					case 'R':
						dt = new MDUnknownRExtendedDataType(dmang);
						break;
					case 'S':
						dt = new MDChar16DataType(dmang);
						break;
					case 'T':
						dt = new MDUnknownTExtendedDataType(dmang);
						break;
					case 'U':
						dt = new MDChar32DataType(dmang);
						break;
					case 'V':
						dt = new MDUnknownVExtendedDataType(dmang);
						break;
					case 'W':
						dt = new MDWcharDataType(dmang);
						break;
					case 'X': // TODO: more unknown about this.
						dt = new MDCoclassType(dmang, 2);
						break;
					case 'Y': // TODO: more unknown about this.
						dt = new MDCointerfaceType(dmang, 2);
						break;
					case '_':
						// 20160728: Windows 10 stuff... stubbing for now to try to help figure
						//  this out.
						// TODO 20170328: MDObjectCPP is wrong here (especially after moving the
						//  parsing of '?' inside of MDObjectCPP.
						//20180404: This is still broken, so exception gets thrown->no coverage.
						MDObjectCPP object = new MDObjectCPP(dmang);
						object.parse();
						dt = new MDDataType(dmang);
						dt.setName(object.toString());
//						dt.insert(dtBuilder);
//						dt.setTypeName(dtBuilder.emit());
//						dt.setTypeName(object.emit());
						// MDQualifiedName qualifiedName = new MDQualifiedName(dmang);
						// dt = new MDComplexType();
//						MDTemplateNameAndArguments tn = new MDTemplateNameAndArguments(dmang);
//						dt.setTypeName("{MDMANG_UNK_EXTENDEDTYPE:" + tn.emit() + "}"); // 20160728 temp
						break;
					case MDMang.DONE:
						throw new MDException("Extended BasicDataType: no data for type code");
					default:
						throw new MDException("Extended BasicDataType: unrecognized code: " + code);
				}
				break;
			case '@':
				// 20160926: Hypothesis: this only occurs for the function return type of
				//  constructors and destructors.
				// Do: grep '@@QEAA@' fixnameout6.txt | grep -v '?0' | grep -v '?1'
				//  --also try variations, leaving out the 2nd or 3rd grep.
				MDVoidDataType dtv = new MDVoidDataType(dmang);
				dtv.setNonPrinting();
				dt = dtv;
				break;
			case MDMang.DONE:
				throw new MDException("BasicDataType: no data for type code");
			default:
				throw new MDException("BasicDataType: unrecognized code: " + code);
		}
		return dt;
	}
This method parses basic and extended data types.
@param dmang - the MDMang driver
@param isHighest - boolean indicating whether something else modifies or names the data
 type to be parsed, which impacts when certain overloaded CV modifiers can be applied.
@return - a type derived from MDDataType
@throws MDException on parsing error
Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/datatype/MDDataTypeParser.java