demangle.go
func (st *state) prefix() AST {
	var a AST

	// The last name seen, for a constructor/destructor.
	var last AST

	getLast := func(a AST) AST {
		for {
			if t, ok := a.(*Template); ok {
				a = t.Name
			} else if q, ok := a.(*Qualified); ok {
				a = q.Name
			} else if t, ok := a.(*TaggedName); ok {
				a = t.Name
			} else {
				return a
			}
		}
	}

	isCast := false
	for {
		if len(st.str) == 0 {
			st.fail("expected prefix")
		}
		var next AST

		c := st.str[0]
		if isDigit(c) || isLower(c) || c == 'U' || c == 'L' {
			un, isUnCast := st.unqualifiedName()
			next = un
			if isUnCast {
				isCast = true
			}
		} else {
			switch st.str[0] {
			case 'C':
				inheriting := false
				st.advance(1)
				if len(st.str) > 0 && st.str[0] == 'I' {
					inheriting = true
					st.advance(1)
				}
				if len(st.str) < 1 {
					st.fail("expected constructor type")
				}
				if last == nil {
					st.fail("constructor before name is seen")
				}
				st.advance(1)
				if inheriting {
					last = st.demangleType(false)
				}
				next = &Constructor{Name: getLast(last)}
			case 'D':
				if len(st.str) > 1 && (st.str[1] == 'T' || st.str[1] == 't') {
					next = st.demangleType(false)
				} else {
					if len(st.str) < 2 {
						st.fail("expected destructor type")
					}
					if last == nil {
						st.fail("destructor before name is seen")
					}
					st.advance(2)
					next = &Destructor{Name: getLast(last)}
				}
			case 'S':
				next = st.substitution(true)
			case 'I':
				if a == nil {
					st.fail("unexpected template arguments")
				}
				var args []AST
				args = st.templateArgs()
				tmpl := &Template{Name: a, Args: args}
				if isCast {
					st.setTemplate(a, tmpl)
					st.clearTemplateArgs(args)
					isCast = false
				}
				a = nil
				next = tmpl
			case 'T':
				next = st.templateParam()
			case 'E':
				if a == nil {
					st.fail("expected prefix")
				}
				if isCast {
					st.setTemplate(a, nil)
				}
				return a
			case 'M':
				if a == nil {
					st.fail("unexpected lambda initializer")
				}
				// This is the initializer scope for a
				// lambda.  We don't need to record
				// it.  The normal code will treat the
				// variable has a type scope, which
				// gives appropriate output.
				st.advance(1)
				continue
			default:
				st.fail("unrecognized letter in prefix")
			}
		}
		last = next
		if a == nil {
			a = next
		} else {
			a = &Qualified{Scope: a, Name: next, LocalName: false}
		}

		if c != 'S' && (len(st.str) == 0 || st.str[0] != 'E') {
			st.subs.add(a)
		}
	}
}
func (st *state) prefix() AST {
	var a AST

	// The last name seen, for a constructor/destructor.
	var last AST

	getLast := func(a AST) AST {
		for {
			if t, ok := a.(*Template); ok {
				a = t.Name
			} else if q, ok := a.(*Qualified); ok {
				a = q.Name
			} else if t, ok := a.(*TaggedName); ok {
				a = t.Name
			} else {
				return a
			}
		}
	}

	isCast := false
	for {
		if len(st.str) == 0 {
			st.fail("expected prefix")
		}
		var next AST

		c := st.str[0]
		if isDigit(c) || isLower(c) || c == 'U' || c == 'L' {
			un, isUnCast := st.unqualifiedName()
			next = un
			if isUnCast {
				isCast = true
			}
		} else {
			switch st.str[0] {
			case 'C':
				inheriting := false
				st.advance(1)
				if len(st.str) > 0 && st.str[0] == 'I' {
					inheriting = true
					st.advance(1)
				}
				if len(st.str) < 1 {
					st.fail("expected constructor type")
				}
				if last == nil {
					st.fail("constructor before name is seen")
				}
				st.advance(1)
				if inheriting {
					last = st.demangleType(false)
				}
				next = &Constructor{Name: getLast(last)}
			case 'D':
				if len(st.str) > 1 && (st.str[1] == 'T' || st.str[1] == 't') {
					next = st.demangleType(false)
				} else {
					if len(st.str) < 2 {
						st.fail("expected destructor type")
					}
					if last == nil {
						st.fail("destructor before name is seen")
					}
					st.advance(2)
					next = &Destructor{Name: getLast(last)}
				}
			case 'S':
				next = st.substitution(true)
			case 'I':
				if a == nil {
					st.fail("unexpected template arguments")
				}
				var args []AST
				args = st.templateArgs()
				tmpl := &Template{Name: a, Args: args}
				if isCast {
					st.setTemplate(a, tmpl)
					st.clearTemplateArgs(args)
					isCast = false
				}
				a = nil
				next = tmpl
			case 'T':
				next = st.templateParam()
			case 'E':
				if a == nil {
					st.fail("expected prefix")
				}
				if isCast {
					st.setTemplate(a, nil)
				}
				return a
			case 'M':
				if a == nil {
					st.fail("unexpected lambda initializer")
				}
				// This is the initializer scope for a
				// lambda.  We don't need to record
				// it.  The normal code will treat the
				// variable has a type scope, which
				// gives appropriate output.
				st.advance(1)
				continue
			default:
				st.fail("unrecognized letter in prefix")
			}
		}
		last = next
		if a == nil {
			a = next
		} else {
			a = &Qualified{Scope: a, Name: next, LocalName: false}
		}

		if c != 'S' && (len(st.str) == 0 || st.str[0] != 'E') {
			st.subs.add(a)
		}
	}
}
// <prefix> ::= <prefix> <unqualified-name>
//          ::= <template-prefix> <template-args>
//          ::= <template-param>
//          ::= <decltype>
//          ::=
//          ::= <substitution>
//
// <template-prefix> ::= <prefix> <(template) unqualified-name>
//                   ::= <template-param>
//                   ::= <substitution>
//
// <decltype> ::= Dt <expression> E
//            ::= DT <expression> E