github.com/go-xe2/third@v1.0.3/golang.org/x/text/internal/number/pattern.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package number
     6  
     7  import (
     8  	"errors"
     9  	"unicode/utf8"
    10  )
    11  
    12  // This file contains a parser for the CLDR number patterns as described in
    13  // http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
    14  //
    15  // The following BNF is derived from this standard.
    16  //
    17  // pattern    := subpattern (';' subpattern)?
    18  // subpattern := affix? number exponent? affix?
    19  // number     := decimal | sigDigits
    20  // decimal    := '#'* '0'* ('.' fraction)? | '#' | '0'
    21  // fraction   := '0'* '#'*
    22  // sigDigits  := '#'* '@' '@'* '#'*
    23  // exponent   := 'E' '+'? '0'* '0'
    24  // padSpec    := '*' \L
    25  //
    26  // Notes:
    27  // - An affix pattern may contain any runes, but runes with special meaning
    28  //   should be escaped.
    29  // - Sequences of digits, '#', and '@' in decimal and sigDigits may have
    30  //   interstitial commas.
    31  
    32  // TODO: replace special characters in affixes (-, +, ¤) with control codes.
    33  
    34  // Pattern holds information for formatting numbers. It is designed to hold
    35  // information from CLDR number patterns.
    36  //
    37  // This pattern is precompiled  for all patterns for all languages. Even though
    38  // the number of patterns is not very large, we want to keep this small.
    39  //
    40  // This type is only intended for internal use.
    41  type Pattern struct {
    42  	RoundingContext
    43  
    44  	Affix       string // includes prefix and suffix. First byte is prefix length.
    45  	Offset      uint16 // Offset into Affix for prefix and suffix
    46  	NegOffset   uint16 // Offset into Affix for negative prefix and suffix or 0.
    47  	PadRune     rune
    48  	FormatWidth uint16
    49  
    50  	GroupingSize [2]uint8
    51  	Flags        PatternFlag
    52  }
    53  
    54  // A RoundingContext indicates how a number should be converted to digits.
    55  // It contains all information needed to determine the "visible digits" as
    56  // required by the pluralization rules.
    57  type RoundingContext struct {
    58  	// TODO: unify these two fields so that there is a more unambiguous meaning
    59  	// of how precision is handled.
    60  	MaxSignificantDigits int16 // -1 is unlimited
    61  	MaxFractionDigits    int16 // -1 is unlimited
    62  
    63  	Increment      uint32
    64  	IncrementScale uint8 // May differ from printed scale.
    65  
    66  	Mode RoundingMode
    67  
    68  	DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
    69  
    70  	// Number of digits.
    71  	MinIntegerDigits uint8
    72  
    73  	MaxIntegerDigits     uint8
    74  	MinFractionDigits    uint8
    75  	MinSignificantDigits uint8
    76  
    77  	MinExponentDigits uint8
    78  }
    79  
    80  // RoundSignificantDigits returns the number of significant digits an
    81  // implementation of Convert may round to or n < 0 if there is no maximum or
    82  // a maximum is not recommended.
    83  func (r *RoundingContext) RoundSignificantDigits() (n int) {
    84  	if r.MaxFractionDigits == 0 && r.MaxSignificantDigits > 0 {
    85  		return int(r.MaxSignificantDigits)
    86  	} else if r.isScientific() && r.MaxIntegerDigits == 1 {
    87  		if r.MaxSignificantDigits == 0 ||
    88  			int(r.MaxFractionDigits+1) == int(r.MaxSignificantDigits) {
    89  			// Note: don't add DigitShift: it is only used for decimals.
    90  			return int(r.MaxFractionDigits) + 1
    91  		}
    92  	}
    93  	return -1
    94  }
    95  
    96  // RoundFractionDigits returns the number of fraction digits an implementation
    97  // of Convert may round to or n < 0 if there is no maximum or a maximum is not
    98  // recommended.
    99  func (r *RoundingContext) RoundFractionDigits() (n int) {
   100  	if r.MinExponentDigits == 0 &&
   101  		r.MaxSignificantDigits == 0 &&
   102  		r.MaxFractionDigits >= 0 {
   103  		return int(r.MaxFractionDigits) + int(r.DigitShift)
   104  	}
   105  	return -1
   106  }
   107  
   108  // SetScale fixes the RoundingContext to a fixed number of fraction digits.
   109  func (r *RoundingContext) SetScale(scale int) {
   110  	r.MinFractionDigits = uint8(scale)
   111  	r.MaxFractionDigits = int16(scale)
   112  }
   113  
   114  func (r *RoundingContext) SetPrecision(prec int) {
   115  	r.MaxSignificantDigits = int16(prec)
   116  }
   117  
   118  func (r *RoundingContext) isScientific() bool {
   119  	return r.MinExponentDigits > 0
   120  }
   121  
   122  func (f *Pattern) needsSep(pos int) bool {
   123  	p := pos - 1
   124  	size := int(f.GroupingSize[0])
   125  	if size == 0 || p == 0 {
   126  		return false
   127  	}
   128  	if p == size {
   129  		return true
   130  	}
   131  	if p -= size; p < 0 {
   132  		return false
   133  	}
   134  	// TODO: make second groupingsize the same as first if 0 so that we can
   135  	// avoid this check.
   136  	if x := int(f.GroupingSize[1]); x != 0 {
   137  		size = x
   138  	}
   139  	return p%size == 0
   140  }
   141  
   142  // A PatternFlag is a bit mask for the flag field of a Pattern.
   143  type PatternFlag uint8
   144  
   145  const (
   146  	AlwaysSign PatternFlag = 1 << iota
   147  	ElideSign              // Use space instead of plus sign. AlwaysSign must be true.
   148  	AlwaysExpSign
   149  	AlwaysDecimalSeparator
   150  	ParenthesisForNegative // Common pattern. Saves space.
   151  
   152  	PadAfterNumber
   153  	PadAfterAffix
   154  
   155  	PadBeforePrefix = 0 // Default
   156  	PadAfterPrefix  = PadAfterAffix
   157  	PadBeforeSuffix = PadAfterNumber
   158  	PadAfterSuffix  = PadAfterNumber | PadAfterAffix
   159  	PadMask         = PadAfterNumber | PadAfterAffix
   160  )
   161  
   162  type parser struct {
   163  	*Pattern
   164  
   165  	leadingSharps int
   166  
   167  	pos            int
   168  	err            error
   169  	doNotTerminate bool
   170  	groupingCount  uint
   171  	hasGroup       bool
   172  	buf            []byte
   173  }
   174  
   175  func (p *parser) setError(err error) {
   176  	if p.err == nil {
   177  		p.err = err
   178  	}
   179  }
   180  
   181  func (p *parser) updateGrouping() {
   182  	if p.hasGroup &&
   183  		0 < p.groupingCount && p.groupingCount < 255 {
   184  		p.GroupingSize[1] = p.GroupingSize[0]
   185  		p.GroupingSize[0] = uint8(p.groupingCount)
   186  	}
   187  	p.groupingCount = 0
   188  	p.hasGroup = true
   189  }
   190  
   191  var (
   192  	// TODO: more sensible and localizeable error messages.
   193  	errMultiplePadSpecifiers = errors.New("format: pattern has multiple pad specifiers")
   194  	errInvalidPadSpecifier   = errors.New("format: invalid pad specifier")
   195  	errInvalidQuote          = errors.New("format: invalid quote")
   196  	errAffixTooLarge         = errors.New("format: prefix or suffix exceeds maximum UTF-8 length of 256 bytes")
   197  	errDuplicatePercentSign  = errors.New("format: duplicate percent sign")
   198  	errDuplicatePermilleSign = errors.New("format: duplicate permille sign")
   199  	errUnexpectedEnd         = errors.New("format: unexpected end of pattern")
   200  )
   201  
   202  // ParsePattern extracts formatting information from a CLDR number pattern.
   203  //
   204  // See http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
   205  func ParsePattern(s string) (f *Pattern, err error) {
   206  	p := parser{Pattern: &Pattern{}}
   207  
   208  	s = p.parseSubPattern(s)
   209  
   210  	if s != "" {
   211  		// Parse negative sub pattern.
   212  		if s[0] != ';' {
   213  			p.setError(errors.New("format: error parsing first sub pattern"))
   214  			return nil, p.err
   215  		}
   216  		neg := parser{Pattern: &Pattern{}} // just for extracting the affixes.
   217  		s = neg.parseSubPattern(s[len(";"):])
   218  		p.NegOffset = uint16(len(p.buf))
   219  		p.buf = append(p.buf, neg.buf...)
   220  	}
   221  	if s != "" {
   222  		p.setError(errors.New("format: spurious characters at end of pattern"))
   223  	}
   224  	if p.err != nil {
   225  		return nil, p.err
   226  	}
   227  	if affix := string(p.buf); affix == "\x00\x00" || affix == "\x00\x00\x00\x00" {
   228  		// No prefix or suffixes.
   229  		p.NegOffset = 0
   230  	} else {
   231  		p.Affix = affix
   232  	}
   233  	if p.Increment == 0 {
   234  		p.IncrementScale = 0
   235  	}
   236  	return p.Pattern, nil
   237  }
   238  
   239  func (p *parser) parseSubPattern(s string) string {
   240  	s = p.parsePad(s, PadBeforePrefix)
   241  	s = p.parseAffix(s)
   242  	s = p.parsePad(s, PadAfterPrefix)
   243  
   244  	s = p.parse(p.number, s)
   245  	p.updateGrouping()
   246  
   247  	s = p.parsePad(s, PadBeforeSuffix)
   248  	s = p.parseAffix(s)
   249  	s = p.parsePad(s, PadAfterSuffix)
   250  	return s
   251  }
   252  
   253  func (p *parser) parsePad(s string, f PatternFlag) (tail string) {
   254  	if len(s) >= 2 && s[0] == '*' {
   255  		r, sz := utf8.DecodeRuneInString(s[1:])
   256  		if p.PadRune != 0 {
   257  			p.err = errMultiplePadSpecifiers
   258  		} else {
   259  			p.Flags |= f
   260  			p.PadRune = r
   261  		}
   262  		return s[1+sz:]
   263  	}
   264  	return s
   265  }
   266  
   267  func (p *parser) parseAffix(s string) string {
   268  	x := len(p.buf)
   269  	p.buf = append(p.buf, 0) // placeholder for affix length
   270  
   271  	s = p.parse(p.affix, s)
   272  
   273  	n := len(p.buf) - x - 1
   274  	if n > 0xFF {
   275  		p.setError(errAffixTooLarge)
   276  	}
   277  	p.buf[x] = uint8(n)
   278  	return s
   279  }
   280  
   281  // state implements a state transition. It returns the new state. A state
   282  // function may set an error on the parser or may simply return on an incorrect
   283  // token and let the next phase fail.
   284  type state func(r rune) state
   285  
   286  // parse repeatedly applies a state function on the given string until a
   287  // termination condition is reached.
   288  func (p *parser) parse(fn state, s string) (tail string) {
   289  	for i, r := range s {
   290  		p.doNotTerminate = false
   291  		if fn = fn(r); fn == nil || p.err != nil {
   292  			return s[i:]
   293  		}
   294  		p.FormatWidth++
   295  	}
   296  	if p.doNotTerminate {
   297  		p.setError(errUnexpectedEnd)
   298  	}
   299  	return ""
   300  }
   301  
   302  func (p *parser) affix(r rune) state {
   303  	switch r {
   304  	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
   305  		'#', '@', '.', '*', ',', ';':
   306  		return nil
   307  	case '\'':
   308  		p.FormatWidth--
   309  		return p.escapeFirst
   310  	case '%':
   311  		if p.DigitShift != 0 {
   312  			p.setError(errDuplicatePercentSign)
   313  		}
   314  		p.DigitShift = 2
   315  	case '\u2030': // ‰ Per mille
   316  		if p.DigitShift != 0 {
   317  			p.setError(errDuplicatePermilleSign)
   318  		}
   319  		p.DigitShift = 3
   320  		// TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤
   321  	}
   322  	p.buf = append(p.buf, string(r)...)
   323  	return p.affix
   324  }
   325  
   326  func (p *parser) escapeFirst(r rune) state {
   327  	switch r {
   328  	case '\'':
   329  		p.buf = append(p.buf, "\\'"...)
   330  		return p.affix
   331  	default:
   332  		p.buf = append(p.buf, '\'')
   333  		p.buf = append(p.buf, string(r)...)
   334  	}
   335  	return p.escape
   336  }
   337  
   338  func (p *parser) escape(r rune) state {
   339  	switch r {
   340  	case '\'':
   341  		p.FormatWidth--
   342  		p.buf = append(p.buf, '\'')
   343  		return p.affix
   344  	default:
   345  		p.buf = append(p.buf, string(r)...)
   346  	}
   347  	return p.escape
   348  }
   349  
   350  // number parses a number. The BNF says the integer part should always have
   351  // a '0', but that does not appear to be the case according to the rest of the
   352  // documentation. We will allow having only '#' numbers.
   353  func (p *parser) number(r rune) state {
   354  	switch r {
   355  	case '#':
   356  		p.groupingCount++
   357  		p.leadingSharps++
   358  	case '@':
   359  		p.groupingCount++
   360  		p.leadingSharps = 0
   361  		p.MaxFractionDigits = -1
   362  		return p.sigDigits(r)
   363  	case ',':
   364  		if p.leadingSharps == 0 { // no leading commas
   365  			return nil
   366  		}
   367  		p.updateGrouping()
   368  	case 'E':
   369  		p.MaxIntegerDigits = uint8(p.leadingSharps)
   370  		return p.exponent
   371  	case '.': // allow ".##" etc.
   372  		p.updateGrouping()
   373  		return p.fraction
   374  	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   375  		return p.integer(r)
   376  	default:
   377  		return nil
   378  	}
   379  	return p.number
   380  }
   381  
   382  func (p *parser) integer(r rune) state {
   383  	if !('0' <= r && r <= '9') {
   384  		var next state
   385  		switch r {
   386  		case 'E':
   387  			if p.leadingSharps > 0 {
   388  				p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
   389  			}
   390  			next = p.exponent
   391  		case '.':
   392  			next = p.fraction
   393  		case ',':
   394  			next = p.integer
   395  		}
   396  		p.updateGrouping()
   397  		return next
   398  	}
   399  	p.Increment = p.Increment*10 + uint32(r-'0')
   400  	p.groupingCount++
   401  	p.MinIntegerDigits++
   402  	return p.integer
   403  }
   404  
   405  func (p *parser) sigDigits(r rune) state {
   406  	switch r {
   407  	case '@':
   408  		p.groupingCount++
   409  		p.MaxSignificantDigits++
   410  		p.MinSignificantDigits++
   411  	case '#':
   412  		return p.sigDigitsFinal(r)
   413  	case 'E':
   414  		p.updateGrouping()
   415  		return p.normalizeSigDigitsWithExponent()
   416  	default:
   417  		p.updateGrouping()
   418  		return nil
   419  	}
   420  	return p.sigDigits
   421  }
   422  
   423  func (p *parser) sigDigitsFinal(r rune) state {
   424  	switch r {
   425  	case '#':
   426  		p.groupingCount++
   427  		p.MaxSignificantDigits++
   428  	case 'E':
   429  		p.updateGrouping()
   430  		return p.normalizeSigDigitsWithExponent()
   431  	default:
   432  		p.updateGrouping()
   433  		return nil
   434  	}
   435  	return p.sigDigitsFinal
   436  }
   437  
   438  func (p *parser) normalizeSigDigitsWithExponent() state {
   439  	p.MinIntegerDigits, p.MaxIntegerDigits = 1, 1
   440  	p.MinFractionDigits = p.MinSignificantDigits - 1
   441  	p.MaxFractionDigits = p.MaxSignificantDigits - 1
   442  	p.MinSignificantDigits, p.MaxSignificantDigits = 0, 0
   443  	return p.exponent
   444  }
   445  
   446  func (p *parser) fraction(r rune) state {
   447  	switch r {
   448  	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   449  		p.Increment = p.Increment*10 + uint32(r-'0')
   450  		p.IncrementScale++
   451  		p.MinFractionDigits++
   452  		p.MaxFractionDigits++
   453  	case '#':
   454  		p.MaxFractionDigits++
   455  	case 'E':
   456  		if p.leadingSharps > 0 {
   457  			p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
   458  		}
   459  		return p.exponent
   460  	default:
   461  		return nil
   462  	}
   463  	return p.fraction
   464  }
   465  
   466  func (p *parser) exponent(r rune) state {
   467  	switch r {
   468  	case '+':
   469  		// Set mode and check it wasn't already set.
   470  		if p.Flags&AlwaysExpSign != 0 || p.MinExponentDigits > 0 {
   471  			break
   472  		}
   473  		p.Flags |= AlwaysExpSign
   474  		p.doNotTerminate = true
   475  		return p.exponent
   476  	case '0':
   477  		p.MinExponentDigits++
   478  		return p.exponent
   479  	}
   480  	// termination condition
   481  	if p.MinExponentDigits == 0 {
   482  		p.setError(errors.New("format: need at least one digit"))
   483  	}
   484  	return nil
   485  }