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)
		}
	}
}
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 ( " " ) } 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 ( " " ) } if last == nil { st . fail ( " " ) } 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 ( " " ) } if last == nil { st . fail ( " " ) } st . advance ( 2 ) next = & Destructor { Name : getLast ( last ) } } case 'S' : next = st . substitution ( true ) case 'I' : if a == nil { st . fail ( " " ) } 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 ( " " ) } if isCast { st . setTemplate ( a , nil ) } return a case 'M' : if a == nil { st . fail ( " " ) } // 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 ( " " ) } } 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
<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