Index: src/SymTab/Demangle.cc
===================================================================
--- src/SymTab/Demangle.cc	(revision 7804e2aa5f09879353f29c346128bb9898678da5)
+++ src/SymTab/Demangle.cc	(revision c20fafded4125fd37a79e2d6b54337db4f0303c7)
@@ -324,129 +324,188 @@
 	namespace Mangler {
 		namespace {
-			// strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
-			bool stripMangleName(const std::string & mangleName, std::string & name, std::string & type) {
-				PRINT( std::cerr << "====== " << mangleName.size() << " " << mangleName << std::endl; )
-				if (mangleName.size() < 4+nameSeparator.size()) return false;
-				if (mangleName[0] != '_' || mangleName[1] != '_' || ! isdigit(mangleName.back())) return false;
-
-				// find bounds for name
-				size_t nameStart = 2;
-				size_t nameEnd = mangleName.rfind(nameSeparator);
-				PRINT( std::cerr << nameStart << " " << nameEnd << std::endl; )
-				if (nameEnd == std::string::npos) return false;
-
-				// find bounds for type
-				size_t typeStart = nameEnd+nameSeparator.size();
-				size_t typeEnd = mangleName.size()-1;
-				PRINT( std::cerr << typeStart << " " << typeEnd << std::endl; )
-				PRINT( std::cerr << "[");
-				while (isdigit(mangleName[typeEnd])) {
-					PRINT(std::cerr << ".");
-					typeEnd--;
-				}
-				PRINT( std::cerr << "]" << std::endl );
-				if (mangleName[typeEnd] != '_') return false;
-				PRINT( std::cerr << typeEnd << std::endl; )
-
-				// trim and return
-				name = mangleName.substr(nameStart, nameEnd-nameStart);
-				type = mangleName.substr(typeStart, typeEnd-typeStart);
+			struct StringView {
+			private:
+				std::string str;
+				size_t idx = 0;
+				// typedef Type * (StringView::*parser)(Type::Qualifiers);
+				typedef std::function<Type * (Type::Qualifiers)> parser;
+				std::vector<std::pair<std::string, parser>> parsers;
+			public:
+				StringView(const std::string & str);
+
+				bool done() const { return idx >= str.size(); }
+				char cur() const { assert(! done()); return str[idx]; }
+
+				bool expect(char ch) { return str[idx++] == ch;	}
+				void next(size_t inc = 1) { idx += inc; }
+
+				/// determines if `pref` is a prefix of `str`
+				bool isPrefix(const std::string & pref);
+				bool extractNumber(size_t & out);
+				bool extractName(std::string & out);
+				bool stripMangleName(std::string & name);
+
+				Type * parseFunction(Type::Qualifiers tq);
+				Type * parseTuple(Type::Qualifiers tq);
+				Type * parseVoid(Type::Qualifiers tq);
+				Type * parsePointer(Type::Qualifiers tq);
+				Type * parseStruct(Type::Qualifiers tq);
+
+				Type * parseType();
+				bool parse(std::string & name, Type *& type);
+			};
+
+			StringView::StringView(const std::string & str) : str(str) {
+				// basic types
+				for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
+					parsers.emplace_back(Encoding::basicTypes[k], [this, k](Type::Qualifiers tq) {
+						PRINT( std::cerr << "basic type: " << k << std::endl; )
+						return new BasicType(tq, (BasicType::Kind)k);
+					});
+				}
+				// everything else
+				parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
+				parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
+				parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
+				parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
+				parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
+			}
+
+			bool StringView::extractNumber(size_t & out) {
+				std::stringstream numss;
+				while (isdigit(str[idx])) {
+					numss << str[idx];
+					++idx;
+					if (idx >= str.size()) return false;
+				}
+				if (! (numss >> out)) return false;
 				return true;
 			}
 
-			/// determines if `pref` is a prefix of `str`
-			static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int idx ) {
+			bool StringView::extractName(std::string & out) {
+				size_t len;
+				if (! extractNumber(len)) return false;
+				if (idx+len >= str.size()) return false;
+				out = str.substr(idx, len);
+				idx += len;
+				return true;
+			}
+
+			bool StringView::isPrefix(const std::string & pref) {
 				if ( pref.size() > str.size()-idx ) return false;
 				auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
-				return its.first == pref.end();
-			}
-
-			Type * parseType(const std::string & typeString, unsigned int & idx) {
-				if (idx >= typeString.size()) return nullptr;
+				if (its.first == pref.end()) {
+					idx += pref.size();
+					return true;
+				}
+				return false;
+			}
+
+			// strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
+			bool StringView::stripMangleName(std::string & name) {
+				PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
+				if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
+				if (! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back())) return false;
+
+				// get name
+				if (! extractName(name)) return false;
+
+				// find bounds for type
+				PRINT( std::cerr << idx << " " << str.size() << std::endl; )
+				PRINT( std::cerr << "[");
+				while (isdigit(str.back())) {
+					PRINT(std::cerr << ".");
+					str.pop_back();
+					if (str.size() <= idx) return false;
+				}
+				PRINT( std::cerr << "]" << std::endl );
+				if (str.back() != '_') return false;
+				str.pop_back();
+				PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
+				return str.size() > idx;
+			}
+
+			Type * StringView::parseFunction(Type::Qualifiers tq) {
+				PRINT( std::cerr << "function..." << std::endl; )
+				if (done()) return nullptr;
+				FunctionType * ftype = new FunctionType( tq, false );
+				Type * retVal = parseType();
+				if (! retVal) return nullptr;
+				PRINT( std::cerr << "with return type: " << retVal << std::endl; )
+				ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
+				if (done() || ! expect('_')) return nullptr;
+				while (! done()) {
+					PRINT( std::cerr << "got ch: " << cur() << std::endl; )
+					if (cur() == '_') return ftype;
+					Type * param = parseType();
+					if (! param) return nullptr;
+					PRINT( std::cerr << "with parameter : " << param << std::endl; )
+					ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
+				}
+				return nullptr;
+			}
+
+			Type * StringView::parseTuple(Type::Qualifiers tq) {
+				PRINT( std::cerr << "tuple..." << std::endl; )
+				std::list< Type * > types;
+				size_t ncomponents;
+				if (! extractNumber(ncomponents)) return nullptr;
+				for (size_t i = 0; i < ncomponents; ++i) {
+					if (done()) return nullptr;
+					PRINT( std::cerr << "got ch: " << cur() << std::endl; )
+					Type * t = parseType();
+					if (! t) return nullptr;
+					PRINT( std::cerr << "with type : " << t << std::endl; )
+					types.push_back(t);
+				}
+				return new TupleType( tq, types );
+			}
+
+			Type * StringView::parseVoid(Type::Qualifiers tq) {
+				return new VoidType( tq );
+			}
+
+			Type * StringView::parsePointer(Type::Qualifiers tq) {
+				PRINT( std::cerr << "pointer..." << std::endl; )
+				Type * t = parseType();
+				if (! t) return nullptr;
+				return new PointerType( tq, t );
+			}
+
+			Type * StringView::parseStruct(Type::Qualifiers tq) {
+				PRINT( std::cerr << "struct..." << std::endl; )
+				std::string name;
+				if (! extractName(name)) return nullptr;
+				return new StructInstType(tq, name);
+			}
+
+			Type * StringView::parseType() {
+				if (done()) return nullptr;
 
 				// qualifiers
 				Type::Qualifiers tq;
 				while (true) {
-					auto qual = std::find_if(qualifierLetter.begin(), qualifierLetter.end(), [&idx, &typeString](decltype(qualifierLetter)::value_type val) {
-						if (isPrefix(typeString, val.second, idx)) {
-							PRINT( std::cerr << "found qualifier: " << val.second << std::endl; )
-							idx += std::string(val.second).size();
-							return true;
-						}
-						return false;
+					auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
+						return isPrefix(val.second);
 					});
-					if (qual == qualifierLetter.end()) break;
+					if (qual == Encoding::qualifiers.end()) break;
 					tq |= qual->first;
 				}
 
-				// basic types
-				const char ** letter = std::find_if(&btLetter[0], &btLetter[numBtLetter], [&idx, &typeString](const std::string & letter) {
-					if (isPrefix(typeString, letter, idx)) {
-						idx += letter.size();
-						return true;
-					}
-					return false;
+				// find the correct type parser and use it
+				auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
+					return isPrefix(p.first);
 				});
-				if (letter != &btLetter[numBtLetter]) {
-					PRINT( std::cerr << "basic type: " << (letter-btLetter) << std::endl; )
-					BasicType::Kind k = (BasicType::Kind)(letter-btLetter);
-					return new BasicType( tq, k );
-				} // BasicType?
-
-				// everything else
-				switch(typeString[idx++]) {
-					case 'F': {
-						PRINT( std::cerr << "function..." << std::endl; )
-						if (idx >= typeString.size()) return nullptr;
-						FunctionType * ftype = new FunctionType( tq, false );
-						Type * retVal = parseType(typeString, idx);
-						if (! retVal) return nullptr;
-						PRINT( std::cerr << "with return type: " << retVal << std::endl; )
-						ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
-						if (idx >= typeString.size() || typeString[idx++] != '_') return nullptr;
-						while (idx < typeString.size()) {
-							PRINT( std::cerr << "got ch: " << typeString[idx] << std::endl; )
-							if (typeString[idx] == '_') break;
-							Type * param = parseType(typeString, idx);
-							if (! param) return nullptr;
-							PRINT( std::cerr << "with parameter : " << param << std::endl; )
-							ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
-						}
-						if (idx >= typeString.size() || typeString[idx] != '_') return nullptr;
-						++idx;
-						return ftype;
-					}
-					case 'v':
-						return new VoidType( tq );
-					case 'T': {
-						PRINT( std::cerr << "tuple..." << std::endl; )
-						std::list< Type * > types;
-						while (idx < typeString.size()) {
-							PRINT( std::cerr << "got ch: " << typeString[idx] << std::endl; )
-							if (typeString[idx] == '_') break;
-							Type * t = parseType(typeString, idx);
-							if (! t) return nullptr;
-							PRINT( std::cerr << "with type : " << t << std::endl; )
-							types.push_back(t);
-						}
-						if (idx >= typeString.size() || typeString[idx] != '_') return nullptr;
-						++idx;
-						return new TupleType( tq, types );
-					}
-					case 'P': {
-						PRINT( std::cerr << "pointer..." << std::endl; )
-						Type * t = parseType(typeString, idx);
-						if (! t) return nullptr;
-						return new PointerType( tq, t );
-					}
-
-					default: assertf(false, "Unhandled type letter: %c at index: %u", typeString[idx], idx);
-				}
-				return nullptr;
-			}
-
-			Type * parseType(const std::string & typeString) {
-				unsigned int idx = 0;
-				return parseType(typeString, idx);
+				assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
+				return iter->second(tq);
+			}
+
+			bool StringView::parse(std::string & name, Type *& type) {
+				if (! stripMangleName(name)) return false;
+				PRINT( std::cerr << "stripped name: " << name << std::endl; )
+				Type * t = parseType();
+				if (! t) return false;
+				type = t;
+				return true;
 			}
 		} // namespace
@@ -456,10 +515,9 @@
 extern "C" {
 	std::string cforall_demangle(const std::string & mangleName) {
-		std::string name, type;
-		if (! SymTab::Mangler::stripMangleName(mangleName, name, type)) return mangleName;
-		PRINT( std::cerr << name << " " << type << std::endl; )
-		Type * t = SymTab::Mangler::parseType(type);
-		if (! t) return mangleName;
-		return genDemangleType(t, name);
+		SymTab::Mangler::StringView view(mangleName);
+		std::string name;
+		Type * type = nullptr;
+		if (! view.parse(name, type)) return mangleName;
+		return genDemangleType(type, name);
 	} // extern "C"
 }
