private static MDParsableItem parse(MDMang dmang) throws MDException {
		MDParsableItem item;

		// We believe this should adequately distinguish between a mangled "type" name vs. a
		//  dot-separated mangled "symbol" name.
		// => This does not work on three of the tests that begin with "?.cctor"
//		if (dmang.getMangledSymbol().substring(1).contains(".")) {
//			// Dot-separated name
//			// TODO: we need to deal with these
//			// item = new MDDotSeparatedItem(dmang); // for research purposes; might not keep
//			item = null;
//		}
		// Moved the check for data type processing up in the set of checks because we failed
		//  (above) to properly distinguish dot-separated names for three tests.  Ultimately,
		//  it might be better to not have a separate MDDotSeparatedItem, but to be able to set
		//  some attributes on a main item.
		if (dmang.peek() == '.' && !dmang.getMangledSymbol().substring(1).contains(".")) {
			dmang.increment();
			item = MDDataTypeParser.parseDataType(dmang, false);
			dmang.pushContext();
			item.parse();
			dmang.popContext();
			return item;
		}

		if (dmang.peek() == '?') {
			if (dmang.peek(1) == '@') {
				item = new MDObjectCodeView(dmang);
				dmang.pushContext();
				item.parse();
				dmang.popContext();
				return item;
			}
			if (dmang.peek(1) == '$') {
				item = new MDTemplateNameAndArguments(dmang);
				//  If we had no exception and there were zero characters remaining, then we
				//  assume that the item is a template.  Otherwise, we fall through and attempt
				//  to process as a CPP object.
				try {
					dmang.pushContext();
					item.parse();
					dmang.popContext();
					if (dmang.getNumCharsRemaining() == 0) {
						return item;
					}
				}
				catch (MDException e) {
					// trying again...
				}
				// Must reset the demangler state in order to attempt to process as a CPP item
				dmang.resetState();
			}
			item = new MDObjectCPP(dmang);
			dmang.pushContext();
			item.parse();
			dmang.popContext();
			return item;
		}

		if ((dmang.peek() == '_') &&
			((dmang.peek(1) == '_') || ((dmang.peek(1) >= 'A') && (dmang.peek(1) <= 'Z')))) {
			item = parseObjectReserved(dmang);
			dmang.pushContext();
			item.parse();
			dmang.popContext();
			return item;
		}
		// Might move the test of types back here once we get the dot-separted symbol processing
		// logic figured out... for now, it was moved up closer to the start of this function
//		if (dmang.peek() == '.' ) {
//			// Dot-separated will not enter here, as they are distinguished earlier.
//			dmang.increment();
//			item = MDDataTypeParser.parseDataType(dmang, false);
//			dmang.pushContext();
//			item.parse();
//			dmang.popContext();
//			return item;
//		}

		item = new MDObjectC(dmang);
		dmang.pushContext();
		item.parse();
		dmang.popContext();
		return item;
	}
This method is only intended to be called with dmang at a fresh state (including index = 0)
Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/object/MDMangObjectParser.java