OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / internal / number / pattern.go
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 func (r *RoundingContext) scale() int {
81         // scale is 0 when precision is set.
82         if r.MaxSignificantDigits != 0 {
83                 return 0
84         }
85         return int(r.MaxFractionDigits)
86 }
87
88 func (r *RoundingContext) precision() int { return int(r.MaxSignificantDigits) }
89
90 // SetScale fixes the RoundingContext to a fixed number of fraction digits.
91 func (r *RoundingContext) SetScale(scale int) {
92         r.MinFractionDigits = uint8(scale)
93         r.MaxFractionDigits = int16(scale)
94 }
95
96 func (r *RoundingContext) SetPrecision(prec int) {
97         r.MaxSignificantDigits = int16(prec)
98 }
99
100 func (r *RoundingContext) isScientific() bool {
101         return r.MinExponentDigits > 0
102 }
103
104 func (f *Pattern) needsSep(pos int) bool {
105         p := pos - 1
106         size := int(f.GroupingSize[0])
107         if size == 0 || p == 0 {
108                 return false
109         }
110         if p == size {
111                 return true
112         }
113         if p -= size; p < 0 {
114                 return false
115         }
116         // TODO: make second groupingsize the same as first if 0 so that we can
117         // avoid this check.
118         if x := int(f.GroupingSize[1]); x != 0 {
119                 size = x
120         }
121         return p%size == 0
122 }
123
124 // A PatternFlag is a bit mask for the flag field of a Pattern.
125 type PatternFlag uint8
126
127 const (
128         AlwaysSign PatternFlag = 1 << iota
129         ElideSign              // Use space instead of plus sign. AlwaysSign must be true.
130         AlwaysExpSign
131         AlwaysDecimalSeparator
132         ParenthesisForNegative // Common pattern. Saves space.
133
134         PadAfterNumber
135         PadAfterAffix
136
137         PadBeforePrefix = 0 // Default
138         PadAfterPrefix  = PadAfterAffix
139         PadBeforeSuffix = PadAfterNumber
140         PadAfterSuffix  = PadAfterNumber | PadAfterAffix
141         PadMask         = PadAfterNumber | PadAfterAffix
142 )
143
144 type parser struct {
145         *Pattern
146
147         leadingSharps int
148
149         pos            int
150         err            error
151         doNotTerminate bool
152         groupingCount  uint
153         hasGroup       bool
154         buf            []byte
155 }
156
157 func (p *parser) setError(err error) {
158         if p.err == nil {
159                 p.err = err
160         }
161 }
162
163 func (p *parser) updateGrouping() {
164         if p.hasGroup &&
165                 0 < p.groupingCount && p.groupingCount < 255 {
166                 p.GroupingSize[1] = p.GroupingSize[0]
167                 p.GroupingSize[0] = uint8(p.groupingCount)
168         }
169         p.groupingCount = 0
170         p.hasGroup = true
171 }
172
173 var (
174         // TODO: more sensible and localizeable error messages.
175         errMultiplePadSpecifiers = errors.New("format: pattern has multiple pad specifiers")
176         errInvalidPadSpecifier   = errors.New("format: invalid pad specifier")
177         errInvalidQuote          = errors.New("format: invalid quote")
178         errAffixTooLarge         = errors.New("format: prefix or suffix exceeds maximum UTF-8 length of 256 bytes")
179         errDuplicatePercentSign  = errors.New("format: duplicate percent sign")
180         errDuplicatePermilleSign = errors.New("format: duplicate permille sign")
181         errUnexpectedEnd         = errors.New("format: unexpected end of pattern")
182 )
183
184 // ParsePattern extracts formatting information from a CLDR number pattern.
185 //
186 // See http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
187 func ParsePattern(s string) (f *Pattern, err error) {
188         p := parser{Pattern: &Pattern{}}
189
190         s = p.parseSubPattern(s)
191
192         if s != "" {
193                 // Parse negative sub pattern.
194                 if s[0] != ';' {
195                         p.setError(errors.New("format: error parsing first sub pattern"))
196                         return nil, p.err
197                 }
198                 neg := parser{Pattern: &Pattern{}} // just for extracting the affixes.
199                 s = neg.parseSubPattern(s[len(";"):])
200                 p.NegOffset = uint16(len(p.buf))
201                 p.buf = append(p.buf, neg.buf...)
202         }
203         if s != "" {
204                 p.setError(errors.New("format: spurious characters at end of pattern"))
205         }
206         if p.err != nil {
207                 return nil, p.err
208         }
209         if affix := string(p.buf); affix == "\x00\x00" || affix == "\x00\x00\x00\x00" {
210                 // No prefix or suffixes.
211                 p.NegOffset = 0
212         } else {
213                 p.Affix = affix
214         }
215         if p.Increment == 0 {
216                 p.IncrementScale = 0
217         }
218         return p.Pattern, nil
219 }
220
221 func (p *parser) parseSubPattern(s string) string {
222         s = p.parsePad(s, PadBeforePrefix)
223         s = p.parseAffix(s)
224         s = p.parsePad(s, PadAfterPrefix)
225
226         s = p.parse(p.number, s)
227         p.updateGrouping()
228
229         s = p.parsePad(s, PadBeforeSuffix)
230         s = p.parseAffix(s)
231         s = p.parsePad(s, PadAfterSuffix)
232         return s
233 }
234
235 func (p *parser) parsePad(s string, f PatternFlag) (tail string) {
236         if len(s) >= 2 && s[0] == '*' {
237                 r, sz := utf8.DecodeRuneInString(s[1:])
238                 if p.PadRune != 0 {
239                         p.err = errMultiplePadSpecifiers
240                 } else {
241                         p.Flags |= f
242                         p.PadRune = r
243                 }
244                 return s[1+sz:]
245         }
246         return s
247 }
248
249 func (p *parser) parseAffix(s string) string {
250         x := len(p.buf)
251         p.buf = append(p.buf, 0) // placeholder for affix length
252
253         s = p.parse(p.affix, s)
254
255         n := len(p.buf) - x - 1
256         if n > 0xFF {
257                 p.setError(errAffixTooLarge)
258         }
259         p.buf[x] = uint8(n)
260         return s
261 }
262
263 // state implements a state transition. It returns the new state. A state
264 // function may set an error on the parser or may simply return on an incorrect
265 // token and let the next phase fail.
266 type state func(r rune) state
267
268 // parse repeatedly applies a state function on the given string until a
269 // termination condition is reached.
270 func (p *parser) parse(fn state, s string) (tail string) {
271         for i, r := range s {
272                 p.doNotTerminate = false
273                 if fn = fn(r); fn == nil || p.err != nil {
274                         return s[i:]
275                 }
276                 p.FormatWidth++
277         }
278         if p.doNotTerminate {
279                 p.setError(errUnexpectedEnd)
280         }
281         return ""
282 }
283
284 func (p *parser) affix(r rune) state {
285         switch r {
286         case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
287                 '#', '@', '.', '*', ',', ';':
288                 return nil
289         case '\'':
290                 p.FormatWidth--
291                 return p.escapeFirst
292         case '%':
293                 if p.DigitShift != 0 {
294                         p.setError(errDuplicatePercentSign)
295                 }
296                 p.DigitShift = 2
297         case '\u2030': // ‰ Per mille
298                 if p.DigitShift != 0 {
299                         p.setError(errDuplicatePermilleSign)
300                 }
301                 p.DigitShift = 3
302                 // TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤
303         }
304         p.buf = append(p.buf, string(r)...)
305         return p.affix
306 }
307
308 func (p *parser) escapeFirst(r rune) state {
309         switch r {
310         case '\'':
311                 p.buf = append(p.buf, "\\'"...)
312                 return p.affix
313         default:
314                 p.buf = append(p.buf, '\'')
315                 p.buf = append(p.buf, string(r)...)
316         }
317         return p.escape
318 }
319
320 func (p *parser) escape(r rune) state {
321         switch r {
322         case '\'':
323                 p.FormatWidth--
324                 p.buf = append(p.buf, '\'')
325                 return p.affix
326         default:
327                 p.buf = append(p.buf, string(r)...)
328         }
329         return p.escape
330 }
331
332 // number parses a number. The BNF says the integer part should always have
333 // a '0', but that does not appear to be the case according to the rest of the
334 // documentation. We will allow having only '#' numbers.
335 func (p *parser) number(r rune) state {
336         switch r {
337         case '#':
338                 p.groupingCount++
339                 p.leadingSharps++
340         case '@':
341                 p.groupingCount++
342                 p.leadingSharps = 0
343                 return p.sigDigits(r)
344         case ',':
345                 if p.leadingSharps == 0 { // no leading commas
346                         return nil
347                 }
348                 p.updateGrouping()
349         case 'E':
350                 p.MaxIntegerDigits = uint8(p.leadingSharps)
351                 return p.exponent
352         case '.': // allow ".##" etc.
353                 p.updateGrouping()
354                 return p.fraction
355         case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
356                 return p.integer(r)
357         default:
358                 return nil
359         }
360         return p.number
361 }
362
363 func (p *parser) integer(r rune) state {
364         if !('0' <= r && r <= '9') {
365                 var next state
366                 switch r {
367                 case 'E':
368                         if p.leadingSharps > 0 {
369                                 p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
370                         }
371                         next = p.exponent
372                 case '.':
373                         next = p.fraction
374                 case ',':
375                         next = p.integer
376                 }
377                 p.updateGrouping()
378                 return next
379         }
380         p.Increment = p.Increment*10 + uint32(r-'0')
381         p.groupingCount++
382         p.MinIntegerDigits++
383         return p.integer
384 }
385
386 func (p *parser) sigDigits(r rune) state {
387         switch r {
388         case '@':
389                 p.groupingCount++
390                 p.MaxSignificantDigits++
391                 p.MinSignificantDigits++
392         case '#':
393                 return p.sigDigitsFinal(r)
394         case 'E':
395                 p.updateGrouping()
396                 return p.normalizeSigDigitsWithExponent()
397         default:
398                 p.updateGrouping()
399                 return nil
400         }
401         return p.sigDigits
402 }
403
404 func (p *parser) sigDigitsFinal(r rune) state {
405         switch r {
406         case '#':
407                 p.groupingCount++
408                 p.MaxSignificantDigits++
409         case 'E':
410                 p.updateGrouping()
411                 return p.normalizeSigDigitsWithExponent()
412         default:
413                 p.updateGrouping()
414                 return nil
415         }
416         return p.sigDigitsFinal
417 }
418
419 func (p *parser) normalizeSigDigitsWithExponent() state {
420         p.MinIntegerDigits, p.MaxIntegerDigits = 1, 1
421         p.MinFractionDigits = p.MinSignificantDigits - 1
422         p.MaxFractionDigits = p.MaxSignificantDigits - 1
423         p.MinSignificantDigits, p.MaxSignificantDigits = 0, 0
424         return p.exponent
425 }
426
427 func (p *parser) fraction(r rune) state {
428         switch r {
429         case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
430                 p.Increment = p.Increment*10 + uint32(r-'0')
431                 p.IncrementScale++
432                 p.MinFractionDigits++
433                 p.MaxFractionDigits++
434         case '#':
435                 p.MaxFractionDigits++
436         case 'E':
437                 if p.leadingSharps > 0 {
438                         p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
439                 }
440                 return p.exponent
441         default:
442                 return nil
443         }
444         return p.fraction
445 }
446
447 func (p *parser) exponent(r rune) state {
448         switch r {
449         case '+':
450                 // Set mode and check it wasn't already set.
451                 if p.Flags&AlwaysExpSign != 0 || p.MinExponentDigits > 0 {
452                         break
453                 }
454                 p.Flags |= AlwaysExpSign
455                 p.doNotTerminate = true
456                 return p.exponent
457         case '0':
458                 p.MinExponentDigits++
459                 return p.exponent
460         }
461         // termination condition
462         if p.MinExponentDigits == 0 {
463                 p.setError(errors.New("format: need at least one digit"))
464         }
465         return nil
466 }