demangle.go
func (st *state) name() AST {
	if len(st.str) < 1 {
		st.fail("expected name")
	}
	switch st.str[0] {
	case 'N':
		return st.nestedName()
	case 'Z':
		return st.localName()
	case 'U':
		a, isCast := st.unqualifiedName()
		if isCast {
			st.setTemplate(a, nil)
		}
		return a
	case 'S':
		if len(st.str) < 2 {
			st.advance(1)
			st.fail("expected substitution index")
		}
		var a AST
		isCast := false
		subst := false
		if st.str[1] == 't' {
			st.advance(2)
			a, isCast = st.unqualifiedName()
			a = &Qualified{Scope: &Name{Name: "std"}, Name: a, LocalName: false}
		} else {
			a = st.substitution(false)
			subst = true
		}
		if len(st.str) > 0 && st.str[0] == 'I' {
			// This can only happen if we saw
			// <unscoped-template-name> and are about to see
			// <template-args>.  <unscoped-template-name> is a
			// substitution candidate if it did not come from a
			// substitution.
			if !subst {
				st.subs.add(a)
			}
			args := st.templateArgs()
			tmpl := &Template{Name: a, Args: args}
			if isCast {
				st.setTemplate(a, tmpl)
				st.clearTemplateArgs(args)
				isCast = false
			}
			a = tmpl
		}
		if isCast {
			st.setTemplate(a, nil)
		}
		return a

	default:
		a, isCast := st.unqualifiedName()
		if len(st.str) > 0 && st.str[0] == 'I' {
			st.subs.add(a)
			args := st.templateArgs()
			tmpl := &Template{Name: a, Args: args}
			if isCast {
				st.setTemplate(a, tmpl)
				st.clearTemplateArgs(args)
				isCast = false
			}
			a = tmpl
		}
		if isCast {
			st.setTemplate(a, nil)
		}
		return a
	}
}
func (st *state) name() AST {
	if len(st.str) < 1 {
		st.fail("expected name")
	}
	switch st.str[0] {
	case 'N':
		return st.nestedName()
	case 'Z':
		return st.localName()
	case 'U':
		a, isCast := st.unqualifiedName()
		if isCast {
			st.setTemplate(a, nil)
		}
		return a
	case 'S':
		if len(st.str) < 2 {
			st.advance(1)
			st.fail("expected substitution index")
		}
		var a AST
		isCast := false
		subst := false
		if st.str[1] == 't' {
			st.advance(2)
			a, isCast = st.unqualifiedName()
			a = &Qualified{Scope: &Name{Name: "std"}, Name: a, LocalName: false}
		} else {
			a = st.substitution(false)
			subst = true
		}
		if len(st.str) > 0 && st.str[0] == 'I' {
			// This can only happen if we saw
			// <unscoped-template-name> and are about to see
			// <template-args>.  <unscoped-template-name> is a
			// substitution candidate if it did not come from a
			// substitution.
			if !subst {
				st.subs.add(a)
			}
			args := st.templateArgs()
			tmpl := &Template{Name: a, Args: args}
			if isCast {
				st.setTemplate(a, tmpl)
				st.clearTemplateArgs(args)
				isCast = false
			}
			a = tmpl
		}
		if isCast {
			st.setTemplate(a, nil)
		}
		return a

	default:
		a, isCast := st.unqualifiedName()
		if len(st.str) > 0 && st.str[0] == 'I' {
			st.subs.add(a)
			args := st.templateArgs()
			tmpl := &Template{Name: a, Args: args}
			if isCast {
				st.setTemplate(a, tmpl)
				st.clearTemplateArgs(args)
				isCast = false
			}
			a = tmpl
		}
		if isCast {
			st.setTemplate(a, nil)
		}
		return a
	}
}
func ( st * state ) name ( ) AST { if len ( st . str ) < 1 { st . fail ( " " ) } switch st . str [ 0 ] { case 'N' : return st . nestedName ( ) case 'Z' : return st . localName ( ) case 'U' : a , isCast := st . unqualifiedName ( ) if isCast { st . setTemplate ( a , nil ) } return a case 'S' : if len ( st . str ) < 2 { st . advance ( 1 ) st . fail ( " " ) } var a AST isCast := false subst := false if st . str [ 1 ] == 't' { st . advance ( 2 ) a , isCast = st . unqualifiedName ( ) a = & Qualified { Scope : & Name { Name : " " } , Name : a , LocalName : false } } else { a = st . substitution ( false ) subst = true } if len ( st . str ) > 0 && st . str [ 0 ] == 'I' { // This can only happen if we saw // <unscoped-template-name> and are about to see // <template-args>.  <unscoped-template-name> is a // substitution candidate if it did not come from a // substitution. if ! subst { st . subs . add ( a ) } args := st . templateArgs ( ) tmpl := & Template { Name : a , Args : args } if isCast { st . setTemplate ( a , tmpl ) st . clearTemplateArgs ( args ) isCast = false } a = tmpl } if isCast { st . setTemplate ( a , nil ) } return a default : a , isCast := st . unqualifiedName ( ) if len ( st . str ) > 0 && st . str [ 0 ] == 'I' { st . subs . add ( a ) args := st . templateArgs ( ) tmpl := & Template { Name : a , Args : args } if isCast { st . setTemplate ( a , tmpl ) st . clearTemplateArgs ( args ) isCast = false } a = tmpl } if isCast { st . setTemplate ( a , nil ) } return a } }
// <name> ::= <nested-name>
//        ::= <unscoped-name>
//        ::= <unscoped-template-name> <template-args>
//        ::= <local-name>
//
// <unscoped-name> ::= <unqualified-name>
//                 ::= St <unqualified-name>
//
// <unscoped-template-name> ::= <unscoped-name>
//                          ::= <substitution>
<name > :: = <nested - name > :: = <unscoped - name > :: = <unscoped - template - name > <template - args > :: = <local - name > <unscoped - name > :: = <unqualified - name > :: = St <unqualified - name > <unscoped - template - name > :: = <unscoped - name > :: = <substitution >