text: // Package printf implements a parser for fmt.Printf-style format
  // strings.
  //
  // It parses verbs according to the following syntax:
  //     Numeric -> '0'-'9'
  //     Letter -> 'a'-'z' | 'A'-'Z'
  //     Index -> '[' Numeric+ ']'
  //     Star -> '*'
  //     Star -> Index '*'
  //
  //     Precision -> Numeric+ | Star
  //     Width -> Numeric+ | Star
  //
  //     WidthAndPrecision -> Width '.' Precision
  //     WidthAndPrecision -> Width '.'
  //     WidthAndPrecision -> Width
  //     WidthAndPrecision -> '.' Precision
  //     WidthAndPrecision -> '.'
  //
  //     Flag -> '+' | '-' | '#' | ' ' | '0'
  //     Verb -> Letter | '%'
  //
  //     Input -> '%' [ Flag+ ] [ WidthAndPrecision ] [ Index ] Verb
  package printf
  
  import (
  	"errors"
  	"regexp"
  	"strconv"
  	"strings"
  )
  
  // ErrInvalid is returned for invalid format strings or verbs.
  var ErrInvalid = errors.New("invalid format string")
  
  type Verb struct {
  	Letter rune
  	Flags  string
  
  	Width     Argument
  	Precision Argument
  	// Which value in the argument list the verb uses.
  	// -1 denotes the next argument,
  	// values > 0 denote explicit arguments.
  	// The value 0 denotes that no argument is consumed. This is the case for %%.
  	Value int
  
  	Raw string
  }
  
  // Argument is an implicit or explicit width or precision.
  type Argument interface {
  	isArgument()
  }
  
  // The Default value, when no width or precision is provided.
  type Default struct{}
  
  // Zero is the implicit zero value.
  // This value may only appear for precisions in format strings like %6.f
  type Zero struct{}
  
  // Star is a * value, which may either refer to the next argument (Index == -1) or an explicit argument.
  type Star struct{ Index int }
  
  // A Literal value, such as 6 in %6d.
  type Literal int
  
  func (Default) isArgument() {}
  func (Zero) isArgument()    {}
  func (Star) isArgument()    {}
  func (Literal) isArgument() {}
  
  // Parse parses f and returns a list of actions.
  // An action may either be a literal string, or a Verb.
  func Parse(f string) ([]interface{}, error) {
  	var out []interface{}
  	for len(f) > 0 {
  		if f[0] == '%' {
  			v, n, err := ParseVerb(f)
  			if err != nil {
  				return nil, err
  			}
  			f = f[n:]
  			out = append(out, v)
  		} else {
  			n := strings.IndexByte(f, '%')
  			if n > -1 {
  				out = append(out, f[:n])
  				f = f[n:]
  			} else {
  				out = append(out, f)
  				f = ""
  			}
  		}
  	}
  
  	return out, nil
  }
  
  func atoi(s string) int {
  	n, _ := strconv.Atoi(s)
  	return n
  }
  
  // ParseVerb parses the verb at the beginning of f.
  // It returns the verb, how much of the input was consumed, and an error, if any.
  func ParseVerb(f string) (Verb, int, error) {
  	if len(f) < 2 {
  		return Verb{}, 0, ErrInvalid
  	}
  	const (
  		flags = 1
  
  		width      = 2
  		widthStar  = 3
  		widthIndex = 5
  
  		dot       = 6
  		prec      = 7
  		precStar  = 8
  		precIndex = 10
  
  		verbIndex = 11
  		verb      = 12
  	)
  
  	m := re.FindStringSubmatch(f)
  	if m == nil {
  		return Verb{}, 0, ErrInvalid
  	}
  
  	v := Verb{
  		Letter: []rune(m[verb])[0],
  		Flags:  m[flags],
  		Raw:    m[0],
  	}
  
  	if m[width] != "" {
  		// Literal width
  		v.Width = Literal(atoi(m[width]))
  	} else if m[widthStar] != "" {
  		// Star width
  		if m[widthIndex] != "" {
  			v.Width = Star{atoi(m[widthIndex])}
  		} else {
  			v.Width = Star{-1}
  		}
  	} else {
  		// Default width
  		v.Width = Default{}
  	}
  
  	if m[dot] == "" {
  		// default precision
  		v.Precision = Default{}
  	} else {
  		if m[prec] != "" {
  			// Literal precision
  			v.Precision = Literal(atoi(m[prec]))
  		} else if m[precStar] != "" {
  			// Star precision
  			if m[precIndex] != "" {
  				v.Precision = Star{atoi(m[precIndex])}
  			} else {
  				v.Precision = Star{-1}
  			}
  		} else {
  			// Zero precision
  			v.Precision = Zero{}
  		}
  	}
  
  	if m[verb] == "%" {
  		v.Value = 0
  	} else if m[verbIndex] != "" {
  		v.Value = atoi(m[verbIndex])
  	} else {
  		v.Value = -1
  	}
  
  	return v, len(m[0]), nil
  }
  
  const (
  	flags             = `([+#0 -]*)`
  	verb              = `([a-zA-Z%])`
  	index             = `(?:\[([0-9]+)\])`
  	star              = `((` + index + `)?\*)`
  	width1            = `([0-9]+)`
  	width2            = star
  	width             = `(?:` + width1 + `|` + width2 + `)`
  	precision         = width
  	widthAndPrecision = `(?:(?:` + width + `)?(?:(\.)(?:` + precision + `)?)?)`
  )
  
  var re = regexp.MustCompile(`^%` + flags + widthAndPrecision + `?` + index + `?` + verb)
  