// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package number

import (
	
	
)

// This file contains a parser for the CLDR number patterns as described in
// https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
//
// The following BNF is derived from this standard.
//
// pattern    := subpattern (';' subpattern)?
// subpattern := affix? number exponent? affix?
// number     := decimal | sigDigits
// decimal    := '#'* '0'* ('.' fraction)? | '#' | '0'
// fraction   := '0'* '#'*
// sigDigits  := '#'* '@' '@'* '#'*
// exponent   := 'E' '+'? '0'* '0'
// padSpec    := '*' \L
//
// Notes:
// - An affix pattern may contain any runes, but runes with special meaning
//   should be escaped.
// - Sequences of digits, '#', and '@' in decimal and sigDigits may have
//   interstitial commas.

// TODO: replace special characters in affixes (-, +, ¤) with control codes.

// Pattern holds information for formatting numbers. It is designed to hold
// information from CLDR number patterns.
//
// This pattern is precompiled  for all patterns for all languages. Even though
// the number of patterns is not very large, we want to keep this small.
//
// This type is only intended for internal use.
type Pattern struct {
	RoundingContext

	Affix       string // includes prefix and suffix. First byte is prefix length.
	Offset      uint16 // Offset into Affix for prefix and suffix
	NegOffset   uint16 // Offset into Affix for negative prefix and suffix or 0.
	PadRune     rune
	FormatWidth uint16

	GroupingSize [2]uint8
	Flags        PatternFlag
}

// A RoundingContext indicates how a number should be converted to digits.
// It contains all information needed to determine the "visible digits" as
// required by the pluralization rules.
type RoundingContext struct {
	// TODO: unify these two fields so that there is a more unambiguous meaning
	// of how precision is handled.
	MaxSignificantDigits int16 // -1 is unlimited
	MaxFractionDigits    int16 // -1 is unlimited

	Increment      uint32
	IncrementScale uint8 // May differ from printed scale.

	Mode RoundingMode

	DigitShift uint8 // Number of decimals to shift. Used for % and ‰.

	// Number of digits.
	MinIntegerDigits uint8

	MaxIntegerDigits     uint8
	MinFractionDigits    uint8
	MinSignificantDigits uint8

	MinExponentDigits uint8
}

// RoundSignificantDigits returns the number of significant digits an
// implementation of Convert may round to or n < 0 if there is no maximum or
// a maximum is not recommended.
func ( *RoundingContext) () ( int) {
	if .MaxFractionDigits == 0 && .MaxSignificantDigits > 0 {
		return int(.MaxSignificantDigits)
	} else if .isScientific() && .MaxIntegerDigits == 1 {
		if .MaxSignificantDigits == 0 ||
			int(.MaxFractionDigits+1) == int(.MaxSignificantDigits) {
			// Note: don't add DigitShift: it is only used for decimals.
			return int(.MaxFractionDigits) + 1
		}
	}
	return -1
}

// RoundFractionDigits returns the number of fraction digits an implementation
// of Convert may round to or n < 0 if there is no maximum or a maximum is not
// recommended.
func ( *RoundingContext) () ( int) {
	if .MinExponentDigits == 0 &&
		.MaxSignificantDigits == 0 &&
		.MaxFractionDigits >= 0 {
		return int(.MaxFractionDigits) + int(.DigitShift)
	}
	return -1
}

// SetScale fixes the RoundingContext to a fixed number of fraction digits.
func ( *RoundingContext) ( int) {
	.MinFractionDigits = uint8()
	.MaxFractionDigits = int16()
}

func ( *RoundingContext) ( int) {
	.MaxSignificantDigits = int16()
}

func ( *RoundingContext) () bool {
	return .MinExponentDigits > 0
}

func ( *Pattern) ( int) bool {
	 :=  - 1
	 := int(.GroupingSize[0])
	if  == 0 ||  == 0 {
		return false
	}
	if  ==  {
		return true
	}
	if  -= ;  < 0 {
		return false
	}
	// TODO: make second groupingsize the same as first if 0 so that we can
	// avoid this check.
	if  := int(.GroupingSize[1]);  != 0 {
		 = 
	}
	return % == 0
}

// A PatternFlag is a bit mask for the flag field of a Pattern.
type PatternFlag uint8

const (
	AlwaysSign PatternFlag = 1 << iota
	ElideSign              // Use space instead of plus sign. AlwaysSign must be true.
	AlwaysExpSign
	AlwaysDecimalSeparator
	ParenthesisForNegative // Common pattern. Saves space.

	PadAfterNumber
	PadAfterAffix

	PadBeforePrefix = 0 // Default
	PadAfterPrefix  = PadAfterAffix
	PadBeforeSuffix = PadAfterNumber
	PadAfterSuffix  = PadAfterNumber | PadAfterAffix
	PadMask         = PadAfterNumber | PadAfterAffix
)

type parser struct {
	*Pattern

	leadingSharps int

	pos            int
	err            error
	doNotTerminate bool
	groupingCount  uint
	hasGroup       bool
	buf            []byte
}

func ( *parser) ( error) {
	if .err == nil {
		.err = 
	}
}

func ( *parser) () {
	if .hasGroup &&
		0 < .groupingCount && .groupingCount < 255 {
		.GroupingSize[1] = .GroupingSize[0]
		.GroupingSize[0] = uint8(.groupingCount)
	}
	.groupingCount = 0
	.hasGroup = true
}

var (
	// TODO: more sensible and localizeable error messages.
	errMultiplePadSpecifiers = errors.New("format: pattern has multiple pad specifiers")
	errInvalidPadSpecifier   = errors.New("format: invalid pad specifier")
	errInvalidQuote          = errors.New("format: invalid quote")
	errAffixTooLarge         = errors.New("format: prefix or suffix exceeds maximum UTF-8 length of 256 bytes")
	errDuplicatePercentSign  = errors.New("format: duplicate percent sign")
	errDuplicatePermilleSign = errors.New("format: duplicate permille sign")
	errUnexpectedEnd         = errors.New("format: unexpected end of pattern")
)

// ParsePattern extracts formatting information from a CLDR number pattern.
//
// See https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
func ( string) ( *Pattern,  error) {
	 := parser{Pattern: &Pattern{}}

	 = .parseSubPattern()

	if  != "" {
		// Parse negative sub pattern.
		if [0] != ';' {
			.setError(errors.New("format: error parsing first sub pattern"))
			return nil, .err
		}
		 := parser{Pattern: &Pattern{}} // just for extracting the affixes.
		 = .parseSubPattern([len(";"):])
		.NegOffset = uint16(len(.buf))
		.buf = append(.buf, .buf...)
	}
	if  != "" {
		.setError(errors.New("format: spurious characters at end of pattern"))
	}
	if .err != nil {
		return nil, .err
	}
	if  := string(.buf);  == "\x00\x00" ||  == "\x00\x00\x00\x00" {
		// No prefix or suffixes.
		.NegOffset = 0
	} else {
		.Affix = 
	}
	if .Increment == 0 {
		.IncrementScale = 0
	}
	return .Pattern, nil
}

func ( *parser) ( string) string {
	 = .parsePad(, PadBeforePrefix)
	 = .parseAffix()
	 = .parsePad(, PadAfterPrefix)

	 = .parse(.number, )
	.updateGrouping()

	 = .parsePad(, PadBeforeSuffix)
	 = .parseAffix()
	 = .parsePad(, PadAfterSuffix)
	return 
}

func ( *parser) ( string,  PatternFlag) ( string) {
	if len() >= 2 && [0] == '*' {
		,  := utf8.DecodeRuneInString([1:])
		if .PadRune != 0 {
			.err = errMultiplePadSpecifiers
		} else {
			.Flags |= 
			.PadRune = 
		}
		return [1+:]
	}
	return 
}

func ( *parser) ( string) string {
	 := len(.buf)
	.buf = append(.buf, 0) // placeholder for affix length

	 = .parse(.affix, )

	 := len(.buf) -  - 1
	if  > 0xFF {
		.setError(errAffixTooLarge)
	}
	.buf[] = uint8()
	return 
}

// state implements a state transition. It returns the new state. A state
// function may set an error on the parser or may simply return on an incorrect
// token and let the next phase fail.
type state func(r rune) state

// parse repeatedly applies a state function on the given string until a
// termination condition is reached.
func ( *parser) ( state,  string) ( string) {
	for ,  := range  {
		.doNotTerminate = false
		if  = ();  == nil || .err != nil {
			return [:]
		}
		.FormatWidth++
	}
	if .doNotTerminate {
		.setError(errUnexpectedEnd)
	}
	return ""
}

func ( *parser) ( rune) state {
	switch  {
	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
		'#', '@', '.', '*', ',', ';':
		return nil
	case '\'':
		.FormatWidth--
		return .escapeFirst
	case '%':
		if .DigitShift != 0 {
			.setError(errDuplicatePercentSign)
		}
		.DigitShift = 2
	case '\u2030': // ‰ Per mille
		if .DigitShift != 0 {
			.setError(errDuplicatePermilleSign)
		}
		.DigitShift = 3
		// TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤
	}
	.buf = append(.buf, string()...)
	return .
}

func ( *parser) ( rune) state {
	switch  {
	case '\'':
		.buf = append(.buf, "\\'"...)
		return .affix
	default:
		.buf = append(.buf, '\'')
		.buf = append(.buf, string()...)
	}
	return .escape
}

func ( *parser) ( rune) state {
	switch  {
	case '\'':
		.FormatWidth--
		.buf = append(.buf, '\'')
		return .affix
	default:
		.buf = append(.buf, string()...)
	}
	return .
}

// number parses a number. The BNF says the integer part should always have
// a '0', but that does not appear to be the case according to the rest of the
// documentation. We will allow having only '#' numbers.
func ( *parser) ( rune) state {
	switch  {
	case '#':
		.groupingCount++
		.leadingSharps++
	case '@':
		.groupingCount++
		.leadingSharps = 0
		.MaxFractionDigits = -1
		return .sigDigits()
	case ',':
		if .leadingSharps == 0 { // no leading commas
			return nil
		}
		.updateGrouping()
	case 'E':
		.MaxIntegerDigits = uint8(.leadingSharps)
		return .exponent
	case '.': // allow ".##" etc.
		.updateGrouping()
		return .fraction
	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		return .integer()
	default:
		return nil
	}
	return .
}

func ( *parser) ( rune) state {
	if !('0' <=  &&  <= '9') {
		var  state
		switch  {
		case 'E':
			if .leadingSharps > 0 {
				.MaxIntegerDigits = uint8(.leadingSharps) + .MinIntegerDigits
			}
			 = .exponent
		case '.':
			 = .fraction
		case ',':
			 = .
		}
		.updateGrouping()
		return 
	}
	.Increment = .Increment*10 + uint32(-'0')
	.groupingCount++
	.MinIntegerDigits++
	return .
}

func ( *parser) ( rune) state {
	switch  {
	case '@':
		.groupingCount++
		.MaxSignificantDigits++
		.MinSignificantDigits++
	case '#':
		return .sigDigitsFinal()
	case 'E':
		.updateGrouping()
		return .normalizeSigDigitsWithExponent()
	default:
		.updateGrouping()
		return nil
	}
	return .
}

func ( *parser) ( rune) state {
	switch  {
	case '#':
		.groupingCount++
		.MaxSignificantDigits++
	case 'E':
		.updateGrouping()
		return .normalizeSigDigitsWithExponent()
	default:
		.updateGrouping()
		return nil
	}
	return .
}

func ( *parser) () state {
	.MinIntegerDigits, .MaxIntegerDigits = 1, 1
	.MinFractionDigits = .MinSignificantDigits - 1
	.MaxFractionDigits = .MaxSignificantDigits - 1
	.MinSignificantDigits, .MaxSignificantDigits = 0, 0
	return .exponent
}

func ( *parser) ( rune) state {
	switch  {
	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		.Increment = .Increment*10 + uint32(-'0')
		.IncrementScale++
		.MinFractionDigits++
		.MaxFractionDigits++
	case '#':
		.MaxFractionDigits++
	case 'E':
		if .leadingSharps > 0 {
			.MaxIntegerDigits = uint8(.leadingSharps) + .MinIntegerDigits
		}
		return .exponent
	default:
		return nil
	}
	return .
}

func ( *parser) ( rune) state {
	switch  {
	case '+':
		// Set mode and check it wasn't already set.
		if .Flags&AlwaysExpSign != 0 || .MinExponentDigits > 0 {
			break
		}
		.Flags |= AlwaysExpSign
		.doNotTerminate = true
		return .
	case '0':
		.MinExponentDigits++
		return .
	}
	// termination condition
	if .MinExponentDigits == 0 {
		.setError(errors.New("format: need at least one digit"))
	}
	return nil
}