@Override
	protected void parseInternal() throws MDException {
		if (dmang.peek() == '?') {
			switch (dmang.peek(1)) {
				case '?':
					nameNested = new MDNestedName(dmang);
					nameNested.parse();
					break;
				case '$':
					// This is a template, but it will get processed through MDReusableName.
					name = new MDReusableName(dmang);
					name.parse();
					break;
				case 'A': // Anonymous namespace
					// 20140522 found that we should Keep the 'A' as part of the name
					//  (found in a backreferrence to the name), so do not do dmang.increment().
					dmang.parseInfoPush(0, "FragmentName from Anonymous Namespace");
					dmang.increment(); // skip the '?'
					nameAnonymous = new MDReusableName(dmang);
					nameAnonymous.parse();
					dmang.parseInfoPop();
					break;
				case 'I': // Believe this is interface namespace
					// 20140522: See note for 'A' anonymous namespace; for 'I' there is no
					// evidence to include the 'I' in the fragment (investigation seems to have
					// it removed).
					dmang.parseInfoPush(0, "InterfaceName from NameFragment");
					dmang.increment(); // skip the '?'
					dmang.increment(); // skip the 'I'
					nameInterface = new MDReusableName(dmang);
					nameInterface.parse();
					dmang.parseInfoPop();
					break;
				case 'C':
					// Windows 10 seems to have "?C" that we don't know how to process.
					//  Best guess at the moment is to read an MDNameFragment next and
					//  keep the fragment's terminating '@'.  'C' used to be part of the
					//  NumberedNamespace below.
					// MDMANG SPECIALIZATION USED.
					if (dmang.processQualCAsSpecialFragment()) {
						dmang.parseInfoPush(0, "NameC");
						dmang.increment(); // skip the '?'
						dmang.increment(); // skip the 'C'
						MDFragmentName fragName = new MDFragmentName(dmang);
						fragName.keepTerminator(); // keeps the terminating '@'
						fragName.parse();
						nameC = fragName.toString();
						dmang.parseInfoPop();
						break;
					}
					// else fall through to MDNumberedNamespace below.
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					// Whether or not intended (I don't think it was), for the cases other
					//  than those that begin with 'A' or 'I', undname processes all of
					//  these as numbered namespaces.  'A' would normally be 0, but 'I'
					//  could be the beginning of a host of numbered namespaces.
				case 'B':
					// See the possible "case 'C'" above, which fixes other issues, but makes
					//  long test go from 73 to 1308 wrong.
//				case 'C':
				case 'D':
				case 'E':
				case 'F':
				case 'G':
				case 'H':
				case 'J':
				case 'K':
				case 'L':
				case 'M':
				case 'N':
				case 'O':
				case 'P':
					dmang.increment(); // skip the '?'
					nameNumbered = new MDNumberedNamespace(dmang);
					nameNumbered.parse();
					break;
				case 'Q':
					// 20160729 Win10 stuff:
					//  "?__abi_GetIids@?QObject@Platform@@?$Array@P$AAVString@Platform@@$00@2@U$AAGJPAKPAPAVGuid@2@@Z_10006bc0";
					// 20170331: Also seen in this symbol:
					//  "?add@?Q?$IObservableMap@HH@Collections@Foundation@Windows@@MapChanged@?$Map@HHU?$less@H@std@@@2Platform@@UE$AAA?AVEventRegistrationToken@34@PE$AAV?$MapChangedEventHandler@HH@234@@Z"
					dmang.parseInfoPush(0, "InterfaceName from QualifiedName");
					dmang.increment(); // skip the '?'
					dmang.increment(); // skip the 'Q'
					MDQualification qualName = new MDQualification(dmang);
					qualName.parse();
					StringBuilder nameQBuilder = new StringBuilder();
					qualName.insert(nameQBuilder);
					dmang.insertString(nameQBuilder, "[");
					dmang.appendString(nameQBuilder, "]");
					nameQ = nameQBuilder.toString();
					dmang.parseInfoPop();
					break;
				default: // special name
					if (!dmang.isLlvmProcessingMode()) {
						throw new MDException("SpecialName not expected in qualification list");
					}
					// Working around LLVM non-compliance with MSFT mangling standard (See
					//  MDNestedName too).  LLVM does not follow the double question mark ("??")
					// convention, but is only using one "?" (which we got above).  Maybe this
					// is not a nested object, but it has attributes of a nested object other than
					// not adhering to what MSFT does.  There is no test we can do such as checking
					// for lower-case letter because an embedded object name could start with
					// one of the capital letters that have meaning in the above switch cases.
					nameNested = new MDNestedName(dmang);
					nameNested.parse();
					break;
			}
		}
		else {
			name = new MDReusableName(dmang);
			name.parse();
		}
	}
This class represents one component of a namespace qualification (see
MDQualification).
Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/naming/MDQualifier.java