From 1103aa1edb41d01af5396352ef8f1cb048be9c01 Mon Sep 17 00:00:00 2001 From: Todd Date: Tue, 19 Sep 2017 16:21:01 -0400 Subject: [PATCH] format: add support for fraction formatting --- spreadsheet/format/format.go | 432 ++++--- spreadsheet/format/format_test.go | 6 +- spreadsheet/format/lexer.go | 1778 +++++++++++++++++++++-------- spreadsheet/format/lexer.rl | 30 +- 4 files changed, 1597 insertions(+), 649 deletions(-) diff --git a/spreadsheet/format/format.go b/spreadsheet/format/format.go index 7417ca33a7..e42705ae53 100644 --- a/spreadsheet/format/format.go +++ b/spreadsheet/format/format.go @@ -12,28 +12,37 @@ import ( "log" "math" "strconv" + "strings" "time" ) +// constants used when formatting generic values to determine when to start +// rounding const maxGeneric = 1e11 const minGeneric = 1e-10 +// Format is a parsed number format. type Format struct { - Whole []PlaceHolder - Fractional []PlaceHolder - Exponent []PlaceHolder + Whole []Token + Fractional []Token + Exponent []Token IsExponential bool + isFraction bool isPercent bool isGeneral bool hasThousands bool skipNext bool seenDecimal bool + + denom int64 } +// FmtType is the type of a format token. //go:generate stringer -type=FmtType type FmtType byte +// Format type constants. const ( FmtTypeLiteral FmtType = iota FmtTypeDigit @@ -46,15 +55,18 @@ const ( FmtTypeUnderscore FmtTypeDate FmtTypeTime + FmtTypeFraction ) -type PlaceHolder struct { +// Token is a format token in the Excel format string. +type Token struct { Type FmtType Literal byte DateTime string } -func (f *Format) AddPlaceholder(t FmtType, l []byte) { +// AddToken adds a format token to the format. +func (f *Format) AddToken(t FmtType, l []byte) { if f.skipNext { f.skipNext = false return @@ -65,7 +77,7 @@ func (f *Format) AddPlaceholder(t FmtType, l []byte) { case FmtTypeUnderscore: f.skipNext = true case FmtTypeDate, FmtTypeTime: - f.Whole = append(f.Whole, PlaceHolder{Type: t, DateTime: string(l)}) + f.Whole = append(f.Whole, Token{Type: t, DateTime: string(l)}) case FmtTypePercent: f.isPercent = true t = FmtTypeLiteral @@ -79,15 +91,22 @@ func (f *Format) AddPlaceholder(t FmtType, l []byte) { } for _, c := range l { if f.IsExponential { - f.Exponent = append(f.Exponent, PlaceHolder{Type: t, Literal: c}) + f.Exponent = append(f.Exponent, Token{Type: t, Literal: c}) } else if !f.seenDecimal { - f.Whole = append(f.Whole, PlaceHolder{Type: t, Literal: c}) + f.Whole = append(f.Whole, Token{Type: t, Literal: c}) } else { - f.Fractional = append(f.Fractional, PlaceHolder{Type: t, Literal: c}) + f.Fractional = append(f.Fractional, Token{Type: t, Literal: c}) } } case FmtTypeDigitOptThousands: f.hasThousands = true + case FmtTypeFraction: + sp := strings.Split(string(l), "/") + if len(sp) == 2 { + f.isFraction = true + f.denom, _ = strconv.ParseInt(sp[1], 10, 64) + // TODO: if anyone cares, parse and use the numerator format. + } default: log.Printf("unsupported ph type in parse %v", t) } @@ -111,6 +130,8 @@ func Number(v float64, f string) string { return number(v, fmts[0], false) } +// String returns the string formatted according to the type. +// TODO: implement if anyone needs this. func String(v string, f string) string { return v } @@ -124,9 +145,6 @@ func reverse(b []byte) []byte { } func number(vOrig float64, f Format, isNeg bool) string { - epoch := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC) - t := epoch.Add(time.Duration(vOrig * float64(24*time.Hour))) - t = asLocal(t) if f.isGeneral { return NumberGeneric(vOrig) } @@ -134,10 +152,7 @@ func number(vOrig float64, f Format, isNeg bool) string { wasNeg := math.Signbit(vOrig) v := math.Abs(vOrig) - // percent symbol implies multiplying the value by 100 - if f.isPercent { - v *= 100 - } + fractNum := int64(0) exp := int64(0) if f.IsExponential { for v >= 10 { @@ -148,6 +163,14 @@ func number(vOrig float64, f Format, isNeg bool) string { exp-- v *= 10 } + } else if f.isPercent { + // percent symbol implies multiplying the value by 100 + v *= 100 + } else if f.isFraction { + fractNum = int64(v*float64(f.denom) + 0.5) + if len(f.Whole) > 0 { + fractNum = fractNum % f.denom + } } // round up now as this avoids rounding up on just the decimal portion which @@ -162,199 +185,234 @@ func number(vOrig float64, f Format, isNeg bool) string { // split into whole and decimal portions pre, post := math.Modf(v) + buf = append(buf, formatWholeNumber(pre, vOrig, f)...) + buf = append(buf, formatFractional(post, vOrig, f)...) + buf = append(buf, formatExponential(exp, f)...) + + // fractions are special, the whole number portion is handled above (if + // len(f.whole) > 0). This is for the fractional portion, or in the case if + // no whole portion, the numerator will be greater than the denominator. + if f.isFraction { + buf = strconv.AppendInt(buf, fractNum, 10) + buf = append(buf, '/') + buf = strconv.AppendInt(buf, f.denom, 10) + } + // if the number was negative, but this isn't a 'negative' format, then + // we need to prepend a negative sign + if !isNeg && wasNeg { + return "-" + string(buf) + } + return string(buf) +} - if len(f.Whole) > 0 { - raw := strconv.AppendFloat(nil, pre, 'f', -1, 64) - op := make([]byte, 0, len(raw)) - consumed := 0 - lastIdx := 1 - lfor: - for i := len(f.Whole) - 1; i >= 0; i-- { - bidx := len(raw) - 1 - consumed - ph := f.Whole[i] - switch ph.Type { - // '0' consumes a digit or prints a '0' if there is no digit - case FmtTypeDigit: - if bidx >= 0 { - op = append(op, raw[bidx]) - consumed++ - lastIdx = i - } else { - op = append(op, '0') - } - // '#' consumes a digit or prints nothing - case FmtTypeDigitOpt: - if bidx >= 0 { - op = append(op, raw[bidx]) - consumed++ - lastIdx = i - } else { - // we don't skip everything, just #/,/?. This is used so - // that formats like (#,###) with '1' turn into '(1)' and - // not '1)' - for j := i; j >= 0; j-- { - c := f.Whole[j] - if c.Type == FmtTypeLiteral { - op = append(op, c.Literal) - } +func formatWholeNumber(pre, vOrig float64, f Format) []byte { + if len(f.Whole) == 0 { + return nil + } + epoch := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC) + t := epoch.Add(time.Duration(vOrig * float64(24*time.Hour))) + t = asLocal(t) + + raw := strconv.AppendFloat(nil, pre, 'f', -1, 64) + op := make([]byte, 0, len(raw)) + consumed := 0 + lastIdx := 1 +lfor: + for i := len(f.Whole) - 1; i >= 0; i-- { + bidx := len(raw) - 1 - consumed + ph := f.Whole[i] + switch ph.Type { + // '0' consumes a digit or prints a '0' if there is no digit + case FmtTypeDigit: + if bidx >= 0 { + op = append(op, raw[bidx]) + consumed++ + lastIdx = i + } else { + op = append(op, '0') + } + // '#' consumes a digit or prints nothing + case FmtTypeDigitOpt: + if bidx >= 0 { + op = append(op, raw[bidx]) + consumed++ + lastIdx = i + } else { + // we don't skip everything, just #/,/?. This is used so + // that formats like (#,###) with '1' turn into '(1)' and + // not '1)' + for j := i; j >= 0; j-- { + c := f.Whole[j] + if c.Type == FmtTypeLiteral { + op = append(op, c.Literal) } - break lfor - } - case FmtTypeDollar: - for i := consumed; i < len(raw); i++ { - op = append(op, raw[len(raw)-1-i]) - consumed++ } - op = append(op, '$') - case FmtTypeComma: - if !f.hasThousands { - op = append(op, ',') - } - case FmtTypeLiteral: - op = append(op, ph.Literal) - case FmtTypeDate: - op = append(op, reverse(dDate(t, ph.DateTime))...) - case FmtTypeTime: - op = append(op, reverse(dTime(t, vOrig, ph.DateTime))...) - default: - log.Printf("unsupported type in whole %v", ph) + break lfor + } + case FmtTypeDollar: + for i := consumed; i < len(raw); i++ { + op = append(op, raw[len(raw)-1-i]) + consumed++ + } + op = append(op, '$') + case FmtTypeComma: + if !f.hasThousands { + op = append(op, ',') } + case FmtTypeLiteral: + op = append(op, ph.Literal) + case FmtTypeDate: + op = append(op, reverse(dDate(t, ph.DateTime))...) + case FmtTypeTime: + op = append(op, reverse(dTime(t, vOrig, ph.DateTime))...) + default: + log.Printf("unsupported type in whole %v", ph) } - buf = append(buf, reverse(op)...) - - // didn't consume all of the number characters, so insert the rest where - // we were last inserting - if consumed < len(raw) && (consumed != 0 || f.seenDecimal) { - rem := len(raw) - consumed - o := make([]byte, len(buf)+rem) - copy(o, buf[0:lastIdx]) - copy(o[lastIdx:], raw[0:]) - copy(o[lastIdx+rem:], buf[lastIdx:]) - buf = o + } + + buf := reverse(op) + // didn't consume all of the number characters, so insert the rest where + // we were last inserting + if consumed < len(raw) && (consumed != 0 || f.seenDecimal) { + rem := len(raw) - consumed + o := make([]byte, len(buf)+rem) + copy(o, buf[0:lastIdx]) + copy(o[lastIdx:], raw[0:]) + copy(o[lastIdx+rem:], buf[lastIdx:]) + buf = o + } + if f.hasThousands { + b := bytes.Buffer{} + nonTerm := 0 + for i := len(buf) - 1; i >= 0; i-- { + if !(buf[i] >= '0' && buf[i] <= '9') { + nonTerm++ + } else { + break + } } - if f.hasThousands { - b := bytes.Buffer{} - nonTerm := 0 - for i := len(buf) - 1; i >= 0; i-- { - if !(buf[i] >= '0' && buf[i] <= '9') { - nonTerm++ - } else { - break - } + for i := 0; i < len(buf); i++ { + idx := (len(buf) - i - nonTerm) + if idx%3 == 0 && idx != 0 && i != 0 { + b.WriteByte(',') } - for i := 0; i < len(buf); i++ { - idx := (len(buf) - i - nonTerm) - if idx%3 == 0 && idx != 0 && i != 0 { - b.WriteByte(',') - } - b.WriteByte(buf[i]) + b.WriteByte(buf[i]) - } - buf = b.Bytes() } + buf = b.Bytes() } + return buf +} - if len(f.Fractional) != 0 { - buf = append(buf, '.') - raw := strconv.AppendFloat(nil, post, 'f', -1, 64) - if len(raw) > 2 { - raw = raw[2:] // skip the decimal portion (ie. '0.') - } else { - raw = nil - } - op := make([]byte, 0, len(raw)) - consumed := 0 - lforPost: - for i := 0; i < len(f.Fractional); i++ { - bidx := i - ph := f.Fractional[i] - switch ph.Type { - // '0' consumes a digit or prints a '0' if there is no digit - case FmtTypeDigit: - if bidx < len(raw) { - op = append(op, raw[bidx]) - consumed++ - } else { - op = append(op, '0') - } - // '#' consumes a digit or prints nothing - case FmtTypeDigitOpt: - if bidx >= 0 { - op = append(op, raw[bidx]) - consumed++ - } else { - break lforPost - } - case FmtTypeLiteral: - op = append(op, ph.Literal) - default: - log.Printf("unsupported type in fractional %v", ph) +func formatFractional(post, vOrig float64, f Format) []byte { + if len(f.Fractional) == 0 { + return nil + } + + raw := strconv.AppendFloat(nil, post, 'f', -1, 64) + if len(raw) > 2 { + raw = raw[2:] // skip the decimal portion (ie. '0.') + } else { + raw = nil + } + + op := make([]byte, 0, len(raw)) + op = append(op, '.') + consumed := 0 +lforPost: + for i := 0; i < len(f.Fractional); i++ { + bidx := i + ph := f.Fractional[i] + switch ph.Type { + // '0' consumes a digit or prints a '0' if there is no digit + case FmtTypeDigit: + if bidx < len(raw) { + op = append(op, raw[bidx]) + consumed++ + } else { + op = append(op, '0') } + // '#' consumes a digit or prints nothing + case FmtTypeDigitOpt: + if bidx >= 0 { + op = append(op, raw[bidx]) + consumed++ + } else { + break lforPost + } + case FmtTypeLiteral: + op = append(op, ph.Literal) + default: + log.Printf("unsupported type in fractional %v", ph) } - // remaining digits are truncated - buf = append(buf, op...) } + // remaining digits are truncated + return op +} - if f.IsExponential { - if len(f.Exponent) > 0 { - buf = append(buf, 'E') - if exp >= 0 { - buf = append(buf, '+') +func absi64(i int64) int64 { + if i < 0 { + return -i + } + return i +} + +func formatExponential(exp int64, f Format) []byte { + if !f.IsExponential || len(f.Exponent) == 0 { + return nil + } + + raw := strconv.AppendInt(nil, absi64(exp), 10) + + op := make([]byte, 0, len(raw)+2) + op = append(op, 'E') + if exp >= 0 { + op = append(op, '+') + } else { + op = append(op, '-') + exp *= -1 + } + consumed := 0 +lexfor: + for i := len(f.Exponent) - 1; i >= 0; i-- { + bidx := len(raw) - 1 - consumed + ph := f.Exponent[i] + switch ph.Type { + // '0' consumes a digit or prints a '0' if there is no digit + case FmtTypeDigit: + if bidx >= 0 { + op = append(op, raw[bidx]) + consumed++ } else { - buf = append(buf, '-') - exp *= -1 + op = append(op, '0') } - raw := strconv.AppendInt(nil, exp, 10) - op := make([]byte, 0, len(raw)) - consumed := 0 - - lexfor: - for i := len(f.Exponent) - 1; i >= 0; i-- { - bidx := len(raw) - 1 - consumed - ph := f.Exponent[i] - switch ph.Type { - // '0' consumes a digit or prints a '0' if there is no digit - case FmtTypeDigit: - if bidx >= 0 { - op = append(op, raw[bidx]) - consumed++ - } else { - op = append(op, '0') - } - // '#' consumes a digit or prints nothing - case FmtTypeDigitOpt: - if bidx >= 0 { - op = append(op, raw[bidx]) - consumed++ - } else { - for j := i; j >= 0; j-- { - c := f.Exponent[j] - if c.Type == FmtTypeLiteral { - op = append(op, c.Literal) - } - } - break lexfor + // '#' consumes a digit or prints nothing + case FmtTypeDigitOpt: + if bidx >= 0 { + op = append(op, raw[bidx]) + consumed++ + } else { + for j := i; j >= 0; j-- { + c := f.Exponent[j] + if c.Type == FmtTypeLiteral { + op = append(op, c.Literal) } - case FmtTypeLiteral: - op = append(op, ph.Literal) - default: - log.Printf("unsupported type in exp %v", ph) } + break lexfor } - // remaining non-consumed digits in the exponent - if consumed < len(raw) { - op = append(op, raw[len(raw)-consumed-1:consumed-1]...) - } - buf = append(buf, reverse(op)...) - + case FmtTypeLiteral: + op = append(op, ph.Literal) + default: + log.Printf("unsupported type in exp %v", ph) } } - // if the number was negative, but this isn't a 'negative' format, then - // we need to prepend a negative sign - if !isNeg && wasNeg { - return "-" + string(buf) + // remaining non-consumed digits in the exponent + if consumed < len(raw) { + op = append(op, raw[len(raw)-consumed-1:consumed-1]...) } - return string(buf) + + reverse(op[2:]) + return op } // NumberGeneric formats the number with the generic format which attemps to @@ -440,6 +498,7 @@ func performCarries(b []byte) []byte { return b } +// dDate formats a time with an Excel format date string. func dDate(t time.Time, f string) []byte { ret := []byte{} beg := 0 @@ -505,6 +564,7 @@ func dDate(t time.Time, f string) []byte { return ret } +// dTime formats a time with an Excel format time string. func dTime(t time.Time, v float64, f string) []byte { ret := []byte{} beg := 0 diff --git a/spreadsheet/format/format_test.go b/spreadsheet/format/format_test.go index b1190bbccc..7123b4f4c9 100644 --- a/spreadsheet/format/format_test.go +++ b/spreadsheet/format/format_test.go @@ -93,7 +93,11 @@ func TestCellFormattingNumber(t *testing.T) { {-4, "#,##0_);[Red](#,##0)", "(4)"}, // fractions - // {1.5, `0/100`, "150/100"}, + {1.5, `0/100`, "150/100"}, + {0.5, "0/1000", "500/1000"}, + {1.25, "0 0/100", "1 25/100"}, + {0.5, "0/10", "5/10"}, + {0.25, "0/10", "3/10"}, // dates & times {42996.6996269676, "d-mmm-yy", "18-Sep-17"}, diff --git a/spreadsheet/format/lexer.go b/spreadsheet/format/lexer.go index 5ef3b7647e..5553321730 100644 --- a/spreadsheet/format/lexer.go +++ b/spreadsheet/format/lexer.go @@ -15,11 +15,11 @@ import ( ) //line lexer.go:20 -const format_start int = 16 -const format_first_final int = 16 +const format_start int = 34 +const format_first_final int = 34 const format_error int = -1 -const format_en_main int = 16 +const format_en_main int = 34 //line lexer.rl:96 func (l *Lexer) Lex(r io.Reader) { @@ -69,339 +69,458 @@ func (l *Lexer) Lex(r io.Reader) { goto _test_eof } switch cs { - case 16: - goto st_case_16 - case 17: - goto st_case_17 + case 34: + goto st_case_34 + case 35: + goto st_case_35 case 0: goto st_case_0 - case 18: - goto st_case_18 - case 19: - goto st_case_19 + case 36: + goto st_case_36 + case 37: + goto st_case_37 case 1: goto st_case_1 - case 20: - goto st_case_20 case 2: goto st_case_2 - case 21: - goto st_case_21 + case 38: + goto st_case_38 case 3: goto st_case_3 case 4: goto st_case_4 + case 39: + goto st_case_39 case 5: goto st_case_5 case 6: goto st_case_6 case 7: goto st_case_7 - case 22: - goto st_case_22 case 8: goto st_case_8 - case 23: - goto st_case_23 - case 24: - goto st_case_24 - case 25: - goto st_case_25 - case 26: - goto st_case_26 - case 27: - goto st_case_27 + case 40: + goto st_case_40 case 9: goto st_case_9 + case 41: + goto st_case_41 case 10: goto st_case_10 + case 42: + goto st_case_42 case 11: goto st_case_11 + case 43: + goto st_case_43 + case 44: + goto st_case_44 + case 45: + goto st_case_45 case 12: goto st_case_12 + case 46: + goto st_case_46 case 13: goto st_case_13 - case 28: - goto st_case_28 case 14: goto st_case_14 - case 29: - goto st_case_29 case 15: goto st_case_15 + case 16: + goto st_case_16 + case 47: + goto st_case_47 + case 17: + goto st_case_17 + case 48: + goto st_case_48 + case 18: + goto st_case_18 + case 19: + goto st_case_19 + case 20: + goto st_case_20 + case 49: + goto st_case_49 + case 50: + goto st_case_50 + case 21: + goto st_case_21 + case 22: + goto st_case_22 + case 23: + goto st_case_23 + case 24: + goto st_case_24 + case 25: + goto st_case_25 + case 51: + goto st_case_51 + case 26: + goto st_case_26 + case 52: + goto st_case_52 + case 53: + goto st_case_53 + case 54: + goto st_case_54 + case 55: + goto st_case_55 + case 56: + goto st_case_56 + case 57: + goto st_case_57 + case 27: + goto st_case_27 + case 28: + goto st_case_28 + case 29: + goto st_case_29 case 30: goto st_case_30 case 31: goto st_case_31 + case 58: + goto st_case_58 case 32: goto st_case_32 + case 59: + goto st_case_59 + case 33: + goto st_case_33 + case 60: + goto st_case_60 + case 61: + goto st_case_61 + case 62: + goto st_case_62 } goto st_out tr0: //line NONE:1 switch act { + case 2: + { + p = (te) - 1 + l.fmt.AddToken(FmtTypeDigit, nil) + } + case 3: + { + p = (te) - 1 + l.fmt.AddToken(FmtTypeDigitOpt, nil) + } + case 4: + { + p = (te) - 1 + } + case 7: + { + p = (te) - 1 + l.fmt.AddToken(FmtTypePercent, nil) + } case 12: { p = (te) - 1 - l.fmt.AddPlaceholder(FmtTypeDate, data[ts:te]) + l.fmt.AddToken(FmtTypeFraction, data[ts:te]) } case 13: { p = (te) - 1 - l.fmt.AddPlaceholder(FmtTypeTime, data[ts:te]) + l.fmt.AddToken(FmtTypeDate, data[ts:te]) } case 14: { p = (te) - 1 - l.fmt.AddPlaceholder(FmtTypeTime, data[ts:te]) + l.fmt.AddToken(FmtTypeTime, data[ts:te]) } - case 16: + case 15: { p = (te) - 1 + l.fmt.AddToken(FmtTypeTime, data[ts:te]) } - case 18: + case 17: { p = (te) - 1 - l.fmt.AddPlaceholder(FmtTypeLiteral, data[ts:te]) } case 19: { p = (te) - 1 - l.fmt.AddPlaceholder(FmtTypeLiteral, data[ts+1:te-1]) + l.fmt.AddToken(FmtTypeLiteral, data[ts:te]) + } + case 20: + { + p = (te) - 1 + l.fmt.AddToken(FmtTypeLiteral, data[ts+1:te-1]) } } - goto st16 - tr3: + goto st34 + tr9: +//line lexer.rl:82 + p = (te) - 1 + { + l.fmt.AddToken(FmtTypeFraction, data[ts:te]) + } + goto st34 + tr19: //line lexer.rl:73 p = (te) - 1 { - l.fmt.AddPlaceholder(FmtTypeDigitOpt, nil) + l.fmt.AddToken(FmtTypeDigitOpt, nil) } - goto st16 - tr4: + goto st34 + tr20: //line lexer.rl:71 te = p + 1 { - l.fmt.AddPlaceholder(FmtTypeDigitOptThousands, nil) + l.fmt.AddToken(FmtTypeDigitOptThousands, nil) } - goto st16 - tr5: + goto st34 + tr21: +//line lexer.rl:77 + p = (te) - 1 + { + l.fmt.AddToken(FmtTypePercent, nil) + } + goto st34 + tr26: //line lexer.rl:84 p = (te) - 1 { - l.fmt.AddPlaceholder(FmtTypeDate, data[ts:te]) + l.fmt.AddToken(FmtTypeDate, data[ts:te]) } - goto st16 - tr12: + goto st34 + tr28: +//line lexer.rl:72 + p = (te) - 1 + { + l.fmt.AddToken(FmtTypeDigit, nil) + } + goto st34 + tr37: //line lexer.rl:85 p = (te) - 1 { - l.fmt.AddPlaceholder(FmtTypeTime, data[ts:te]) + l.fmt.AddToken(FmtTypeTime, data[ts:te]) } - goto st16 - tr14: + goto st34 + tr39: //line lexer.rl:91 p = (te) - 1 { - l.fmt.AddPlaceholder(FmtTypeLiteral, data[ts:te]) + l.fmt.AddToken(FmtTypeLiteral, data[ts:te]) } - goto st16 - tr19: + goto st34 + tr44: //line lexer.rl:81 te = p + 1 { l.fmt.isGeneral = true } - goto st16 - tr23: + goto st34 + tr48: //line lexer.rl:91 te = p + 1 { - l.fmt.AddPlaceholder(FmtTypeLiteral, data[ts:te]) + l.fmt.AddToken(FmtTypeLiteral, data[ts:te]) } - goto st16 - tr26: + goto st34 + tr51: //line lexer.rl:78 te = p + 1 { - l.fmt.AddPlaceholder(FmtTypeDollar, nil) - } - goto st16 - tr27: -//line lexer.rl:77 - te = p + 1 - { - l.fmt.AddPlaceholder(FmtTypePercent, nil) + l.fmt.AddToken(FmtTypeDollar, nil) } - goto st16 - tr28: + goto st34 + tr53: //line lexer.rl:76 te = p + 1 { - l.fmt.AddPlaceholder(FmtTypeComma, nil) + l.fmt.AddToken(FmtTypeComma, nil) } - goto st16 - tr29: + goto st34 + tr54: //line lexer.rl:75 te = p + 1 { - l.fmt.AddPlaceholder(FmtTypeDecimal, nil) - } - goto st16 - tr30: -//line lexer.rl:72 - te = p + 1 - { - l.fmt.AddPlaceholder(FmtTypeDigit, nil) + l.fmt.AddToken(FmtTypeDecimal, nil) } - goto st16 - tr31: + goto st34 + tr57: //line lexer.rl:80 te = p + 1 { l.nextFmt() } - goto st16 - tr32: -//line lexer.rl:74 - te = p + 1 - { - } - goto st16 - tr38: + goto st34 + tr64: //line lexer.rl:79 te = p + 1 { - l.fmt.AddPlaceholder(FmtTypeUnderscore, nil) + l.fmt.AddToken(FmtTypeUnderscore, nil) } - goto st16 - tr42: + goto st34 + tr68: //line lexer.rl:91 te = p p-- { - l.fmt.AddPlaceholder(FmtTypeLiteral, data[ts:te]) + l.fmt.AddToken(FmtTypeLiteral, data[ts:te]) } - goto st16 - tr43: + goto st34 + tr69: //line lexer.rl:92 te = p p-- { - l.fmt.AddPlaceholder(FmtTypeLiteral, data[ts+1:te-1]) + l.fmt.AddToken(FmtTypeLiteral, data[ts+1:te-1]) } - goto st16 - tr44: + goto st34 + tr70: //line lexer.rl:73 te = p p-- { - l.fmt.AddPlaceholder(FmtTypeDigitOpt, nil) + l.fmt.AddToken(FmtTypeDigitOpt, nil) } - goto st16 - tr46: + goto st34 + tr72: +//line lexer.rl:82 + te = p + p-- + { + l.fmt.AddToken(FmtTypeFraction, data[ts:te]) + } + goto st34 + tr77: +//line lexer.rl:77 + te = p + p-- + { + l.fmt.AddToken(FmtTypePercent, nil) + } + goto st34 + tr78: //line lexer.rl:84 te = p p-- { - l.fmt.AddPlaceholder(FmtTypeDate, data[ts:te]) + l.fmt.AddToken(FmtTypeDate, data[ts:te]) } - goto st16 - tr48: + goto st34 + tr80: +//line lexer.rl:72 + te = p + p-- + { + l.fmt.AddToken(FmtTypeDigit, nil) + } + goto st34 + tr81: //line lexer.rl:85 te = p p-- { - l.fmt.AddPlaceholder(FmtTypeTime, data[ts:te]) + l.fmt.AddToken(FmtTypeTime, data[ts:te]) } - goto st16 - tr52: + goto st34 + tr85: +//line lexer.rl:74 + te = p + p-- + { + } + goto st34 + tr86: //line lexer.rl:87 te = p + 1 { l.fmt.IsExponential = true } - goto st16 - tr55: + goto st34 + tr89: //line lexer.rl:90 te = p + 1 { - l.fmt.AddPlaceholder(FmtTypeLiteral, data[ts+1:te]) + l.fmt.AddToken(FmtTypeLiteral, data[ts+1:te]) } - goto st16 - st16: + goto st34 + st34: //line NONE:1 ts = 0 if p++; p == pe { - goto _test_eof16 + goto _test_eof34 } - st_case_16: + st_case_34: //line NONE:1 ts = p -//line lexer.go:296 +//line lexer.go:395 switch data[p] { case 34: - goto tr24 + goto tr49 case 35: - goto tr25 + goto tr50 case 36: - goto tr26 + goto tr51 case 37: - goto tr27 + goto tr52 case 44: - goto tr28 + goto tr53 case 46: - goto tr29 + goto tr54 case 47: - goto tr6 + goto tr27 case 48: - goto tr30 + goto tr55 case 58: - goto tr9 + goto tr34 case 59: - goto tr31 + goto tr57 case 63: - goto tr32 + goto tr58 case 65: - goto tr33 + goto tr59 case 69: - goto st26 + goto st56 case 71: - goto tr35 + goto tr61 case 91: - goto tr36 + goto tr62 case 92: - goto st30 + goto st60 case 95: - goto tr38 + goto tr64 case 100: - goto tr6 + goto tr27 case 104: - goto tr9 + goto tr34 case 109: - goto tr39 + goto tr65 case 115: - goto tr40 + goto tr66 case 121: - goto st32 + goto st62 } - goto tr23 - tr24: + if 49 <= data[p] && data[p] <= 57 { + goto tr56 + } + goto tr48 + tr49: //line NONE:1 te = p + 1 //line lexer.rl:91 - act = 18 - goto st17 - st17: + act = 19 + goto st35 + st35: if p++; p == pe { - goto _test_eof17 + goto _test_eof35 } - st_case_17: -//line lexer.go:356 + st_case_35: +//line lexer.go:458 if data[p] == 34 { goto tr2 } @@ -420,99 +539,111 @@ func (l *Lexer) Lex(r io.Reader) { te = p + 1 //line lexer.rl:92 - act = 19 - goto st18 - st18: + act = 20 + goto st36 + st36: if p++; p == pe { - goto _test_eof18 + goto _test_eof36 } - st_case_18: -//line lexer.go:382 + st_case_36: +//line lexer.go:484 if data[p] == 34 { goto st0 } - goto tr43 - tr25: + goto tr69 + tr50: //line NONE:1 te = p + 1 - goto st19 - st19: +//line lexer.rl:73 + act = 3 + goto st37 + st37: if p++; p == pe { - goto _test_eof19 + goto _test_eof37 } - st_case_19: -//line lexer.go:397 - if data[p] == 44 { + st_case_37: +//line lexer.go:501 + switch data[p] { + case 35: + goto st1 + case 37: + goto st1 + case 44: + goto st12 + case 47: + goto st2 + case 48: + goto st1 + case 63: goto st1 } - goto tr44 + goto tr70 st1: if p++; p == pe { goto _test_eof1 } st_case_1: - if data[p] == 35 { - goto tr4 - } - goto tr3 - tr6: -//line NONE:1 - te = p + 1 - - goto st20 - st20: - if p++; p == pe { - goto _test_eof20 - } - st_case_20: -//line lexer.go:421 switch data[p] { + case 35: + goto st1 + case 37: + goto st1 case 47: - goto tr6 - case 100: - goto tr6 - case 109: - goto tr6 - case 121: goto st2 + case 48: + goto st1 + case 63: + goto st1 } - goto tr46 + goto tr0 st2: if p++; p == pe { goto _test_eof2 } st_case_2: - if data[p] == 121 { - goto tr6 + switch data[p] { + case 35: + goto tr5 + case 37: + goto st8 + case 48: + goto tr7 + case 63: + goto tr5 } - goto tr5 - tr9: + if 49 <= data[p] && data[p] <= 57 { + goto tr8 + } + goto tr0 + tr5: //line NONE:1 te = p + 1 -//line lexer.rl:85 - act = 13 - goto st21 - st21: + goto st38 + st38: if p++; p == pe { - goto _test_eof21 + goto _test_eof38 } - st_case_21: -//line lexer.go:454 + st_case_38: +//line lexer.go:564 switch data[p] { - case 58: - goto tr9 + case 35: + goto tr5 + case 37: + goto tr5 + case 44: + goto tr5 + case 46: + goto tr5 + case 48: + goto tr5 + case 63: + goto tr5 case 65: goto st3 - case 104: - goto tr9 - case 109: - goto tr9 - case 115: - goto tr40 } - goto tr48 + goto tr72 st3: if p++; p == pe { goto _test_eof3 @@ -524,16 +655,31 @@ func (l *Lexer) Lex(r io.Reader) { case 77: goto st5 } - goto tr0 + goto tr9 st4: if p++; p == pe { goto _test_eof4 } st_case_4: if data[p] == 80 { - goto tr9 + goto tr12 } - goto tr0 + goto tr9 + tr12: +//line NONE:1 + te = p + 1 + + goto st39 + st39: + if p++; p == pe { + goto _test_eof39 + } + st_case_39: +//line lexer.go:613 + if data[p] == 65 { + goto st3 + } + goto tr72 st5: if p++; p == pe { goto _test_eof5 @@ -542,7 +688,7 @@ func (l *Lexer) Lex(r io.Reader) { if data[p] == 47 { goto st6 } - goto tr0 + goto tr9 st6: if p++; p == pe { goto _test_eof6 @@ -551,339 +697,924 @@ func (l *Lexer) Lex(r io.Reader) { if data[p] == 80 { goto st7 } - goto tr0 + goto tr9 st7: if p++; p == pe { goto _test_eof7 } st_case_7: if data[p] == 77 { - goto tr9 + goto tr12 } - goto tr0 - tr40: -//line NONE:1 - te = p + 1 + goto tr9 + st8: + if p++; p == pe { + goto _test_eof8 + } + st_case_8: + switch data[p] { + case 35: + goto tr15 + case 37: + goto st10 + case 63: + goto tr15 + } + if 48 <= data[p] && data[p] <= 57 { + goto tr17 + } + goto tr0 + tr15: +//line NONE:1 + te = p + 1 + + goto st40 + st40: + if p++; p == pe { + goto _test_eof40 + } + st_case_40: +//line lexer.go:672 + switch data[p] { + case 35: + goto tr5 + case 37: + goto st9 + case 44: + goto tr5 + case 46: + goto tr5 + case 48: + goto tr5 + case 63: + goto tr5 + case 65: + goto st3 + } + goto tr72 + st9: + if p++; p == pe { + goto _test_eof9 + } + st_case_9: + switch data[p] { + case 35: + goto tr18 + case 44: + goto tr18 + case 46: + goto tr18 + case 48: + goto tr18 + case 63: + goto tr18 + } + goto tr9 + tr18: +//line NONE:1 + te = p + 1 + + goto st41 + st41: + if p++; p == pe { + goto _test_eof41 + } + st_case_41: +//line lexer.go:718 + switch data[p] { + case 35: + goto tr18 + case 44: + goto tr18 + case 46: + goto tr18 + case 48: + goto tr18 + case 63: + goto tr18 + case 65: + goto st3 + } + goto tr72 + st10: + if p++; p == pe { + goto _test_eof10 + } + st_case_10: + if data[p] == 37 { + goto st10 + } + if 48 <= data[p] && data[p] <= 57 { + goto tr17 + } + goto tr0 + tr17: +//line NONE:1 + te = p + 1 + +//line lexer.rl:82 + act = 12 + goto st42 + st42: + if p++; p == pe { + goto _test_eof42 + } + st_case_42: +//line lexer.go:758 + switch data[p] { + case 35: + goto tr5 + case 37: + goto st11 + case 44: + goto tr5 + case 46: + goto tr5 + case 48: + goto tr76 + case 63: + goto tr5 + case 65: + goto st3 + } + if 49 <= data[p] && data[p] <= 57 { + goto tr17 + } + goto tr72 + st11: + if p++; p == pe { + goto _test_eof11 + } + st_case_11: + switch data[p] { + case 35: + goto tr18 + case 37: + goto st10 + case 44: + goto tr18 + case 46: + goto tr18 + case 63: + goto tr18 + } + if 48 <= data[p] && data[p] <= 57 { + goto tr17 + } + goto tr9 + tr76: +//line NONE:1 + te = p + 1 + + goto st43 + st43: + if p++; p == pe { + goto _test_eof43 + } + st_case_43: +//line lexer.go:810 + switch data[p] { + case 35: + goto tr5 + case 37: + goto tr76 + case 44: + goto tr5 + case 46: + goto tr5 + case 48: + goto tr76 + case 63: + goto tr5 + case 65: + goto st3 + } + if 49 <= data[p] && data[p] <= 57 { + goto tr17 + } + goto tr72 + tr7: +//line NONE:1 + te = p + 1 + + goto st44 + st44: + if p++; p == pe { + goto _test_eof44 + } + st_case_44: +//line lexer.go:841 + switch data[p] { + case 35: + goto tr5 + case 37: + goto tr76 + case 44: + goto tr5 + case 46: + goto tr5 + case 48: + goto tr7 + case 63: + goto tr5 + case 65: + goto st3 + } + if 49 <= data[p] && data[p] <= 57 { + goto tr8 + } + goto tr72 + tr8: +//line NONE:1 + te = p + 1 + + goto st45 + st45: + if p++; p == pe { + goto _test_eof45 + } + st_case_45: +//line lexer.go:872 + switch data[p] { + case 35: + goto tr5 + case 37: + goto tr17 + case 44: + goto tr5 + case 46: + goto tr5 + case 48: + goto tr7 + case 63: + goto tr5 + case 65: + goto st3 + } + if 49 <= data[p] && data[p] <= 57 { + goto tr8 + } + goto tr72 + st12: + if p++; p == pe { + goto _test_eof12 + } + st_case_12: + if data[p] == 35 { + goto tr20 + } + goto tr19 + tr52: +//line NONE:1 + te = p + 1 + +//line lexer.rl:77 + act = 7 + goto st46 + st46: + if p++; p == pe { + goto _test_eof46 + } + st_case_46: +//line lexer.go:914 + switch data[p] { + case 35: + goto st13 + case 37: + goto st14 + case 48: + goto st16 + case 63: + goto st13 + } + if 49 <= data[p] && data[p] <= 57 { + goto st15 + } + goto tr77 + st13: + if p++; p == pe { + goto _test_eof13 + } + st_case_13: + switch data[p] { + case 35: + goto st13 + case 47: + goto st2 + case 48: + goto st13 + case 63: + goto st13 + } + goto tr21 + st14: + if p++; p == pe { + goto _test_eof14 + } + st_case_14: + if data[p] == 37 { + goto st14 + } + if 48 <= data[p] && data[p] <= 57 { + goto st15 + } + goto tr0 + st15: + if p++; p == pe { + goto _test_eof15 + } + st_case_15: + switch data[p] { + case 37: + goto st14 + case 47: + goto st2 + } + if 48 <= data[p] && data[p] <= 57 { + goto st15 + } + goto tr0 + st16: + if p++; p == pe { + goto _test_eof16 + } + st_case_16: + switch data[p] { + case 35: + goto st13 + case 37: + goto st14 + case 47: + goto st2 + case 48: + goto st16 + case 63: + goto st13 + } + if 49 <= data[p] && data[p] <= 57 { + goto st15 + } + goto tr21 + tr27: +//line NONE:1 + te = p + 1 + + goto st47 + st47: + if p++; p == pe { + goto _test_eof47 + } + st_case_47: +//line lexer.go:1003 + switch data[p] { + case 47: + goto tr27 + case 100: + goto tr27 + case 109: + goto tr27 + case 121: + goto st17 + } + goto tr78 + st17: + if p++; p == pe { + goto _test_eof17 + } + st_case_17: + if data[p] == 121 { + goto tr27 + } + goto tr26 + tr55: +//line NONE:1 + te = p + 1 + +//line lexer.rl:72 + act = 2 + goto st48 + st48: + if p++; p == pe { + goto _test_eof48 + } + st_case_48: +//line lexer.go:1036 + switch data[p] { + case 35: + goto st1 + case 37: + goto st18 + case 47: + goto st2 + case 48: + goto st19 + case 63: + goto st1 + } + if 49 <= data[p] && data[p] <= 57 { + goto st20 + } + goto tr80 + st18: + if p++; p == pe { + goto _test_eof18 + } + st_case_18: + switch data[p] { + case 35: + goto st1 + case 37: + goto st18 + case 47: + goto st2 + case 48: + goto st18 + case 63: + goto st1 + } + if 49 <= data[p] && data[p] <= 57 { + goto st15 + } + goto tr28 + st19: + if p++; p == pe { + goto _test_eof19 + } + st_case_19: + switch data[p] { + case 35: + goto st1 + case 37: + goto st18 + case 47: + goto st2 + case 48: + goto st19 + case 63: + goto st1 + } + if 49 <= data[p] && data[p] <= 57 { + goto st20 + } + goto tr28 + st20: + if p++; p == pe { + goto _test_eof20 + } + st_case_20: + switch data[p] { + case 37: + goto st15 + case 47: + goto st2 + } + if 48 <= data[p] && data[p] <= 57 { + goto st20 + } + goto tr0 + tr56: +//line NONE:1 + te = p + 1 + +//line lexer.rl:91 + act = 19 + goto st49 + st49: + if p++; p == pe { + goto _test_eof49 + } + st_case_49: +//line lexer.go:1122 + switch data[p] { + case 37: + goto st15 + case 47: + goto st2 + } + if 48 <= data[p] && data[p] <= 57 { + goto st20 + } + goto tr68 + tr34: +//line NONE:1 + te = p + 1 //line lexer.rl:85 - act = 13 - goto st22 + act = 14 + goto st50 + st50: + if p++; p == pe { + goto _test_eof50 + } + st_case_50: +//line lexer.go:1145 + switch data[p] { + case 58: + goto tr34 + case 65: + goto st21 + case 104: + goto tr34 + case 109: + goto tr34 + case 115: + goto tr66 + } + goto tr81 + st21: + if p++; p == pe { + goto _test_eof21 + } + st_case_21: + switch data[p] { + case 47: + goto st22 + case 77: + goto st23 + } + goto tr0 st22: if p++; p == pe { goto _test_eof22 } st_case_22: -//line lexer.go:528 + if data[p] == 80 { + goto tr34 + } + goto tr0 + st23: + if p++; p == pe { + goto _test_eof23 + } + st_case_23: + if data[p] == 47 { + goto st24 + } + goto tr0 + st24: + if p++; p == pe { + goto _test_eof24 + } + st_case_24: + if data[p] == 80 { + goto st25 + } + goto tr0 + st25: + if p++; p == pe { + goto _test_eof25 + } + st_case_25: + if data[p] == 77 { + goto tr34 + } + goto tr0 + tr66: +//line NONE:1 + te = p + 1 + +//line lexer.rl:85 + act = 14 + goto st51 + st51: + if p++; p == pe { + goto _test_eof51 + } + st_case_51: +//line lexer.go:1219 switch data[p] { case 46: - goto st8 + goto st26 case 58: - goto tr9 + goto tr34 case 65: - goto st3 + goto st21 case 104: - goto tr9 + goto tr34 case 109: - goto tr9 + goto tr34 case 115: - goto tr40 + goto tr66 } - goto tr48 - st8: + goto tr81 + st26: if p++; p == pe { - goto _test_eof8 + goto _test_eof26 } - st_case_8: + st_case_26: if data[p] == 48 { - goto tr13 + goto tr38 } - goto tr12 - tr13: + goto tr37 + tr38: //line NONE:1 te = p + 1 //line lexer.rl:85 - act = 13 - goto st23 - st23: + act = 14 + goto st52 + st52: if p++; p == pe { - goto _test_eof23 + goto _test_eof52 } - st_case_23: -//line lexer.go:565 + st_case_52: +//line lexer.go:1256 switch data[p] { case 48: - goto tr51 + goto tr84 case 58: - goto tr9 + goto tr34 case 65: - goto st3 + goto st21 + case 104: + goto tr34 + case 109: + goto tr34 + case 115: + goto tr66 + } + goto tr81 + tr84: +//line NONE:1 + te = p + 1 + +//line lexer.rl:85 + act = 14 + goto st53 + st53: + if p++; p == pe { + goto _test_eof53 + } + st_case_53: +//line lexer.go:1284 + switch data[p] { + case 48: + goto tr34 + case 58: + goto tr34 + case 65: + goto st21 case 104: - goto tr9 + goto tr34 case 109: - goto tr9 + goto tr34 case 115: - goto tr40 + goto tr66 } - goto tr48 - tr51: + goto tr81 + tr58: //line NONE:1 te = p + 1 -//line lexer.rl:85 - act = 13 - goto st24 - st24: +//line lexer.rl:74 + act = 4 + goto st54 + st54: if p++; p == pe { - goto _test_eof24 + goto _test_eof54 } - st_case_24: -//line lexer.go:593 + st_case_54: +//line lexer.go:1312 switch data[p] { + case 35: + goto st1 + case 37: + goto st1 + case 47: + goto st2 case 48: - goto tr9 - case 58: - goto tr9 - case 65: - goto st3 - case 104: - goto tr9 - case 109: - goto tr9 - case 115: - goto tr40 + goto st1 + case 63: + goto st1 } - goto tr48 - tr33: + goto tr85 + tr59: //line NONE:1 te = p + 1 //line lexer.rl:91 - act = 18 - goto st25 - st25: + act = 19 + goto st55 + st55: if p++; p == pe { - goto _test_eof25 + goto _test_eof55 } - st_case_25: -//line lexer.go:621 + st_case_55: +//line lexer.go:1338 switch data[p] { case 47: - goto st4 + goto st22 case 77: - goto st5 + goto st23 } - goto tr42 - st26: + goto tr68 + st56: if p++; p == pe { - goto _test_eof26 + goto _test_eof56 } - st_case_26: + st_case_56: switch data[p] { case 43: - goto tr52 + goto tr86 case 45: - goto tr52 + goto tr86 } - goto tr42 - tr35: + goto tr68 + tr61: //line NONE:1 te = p + 1 - goto st27 - st27: + goto st57 + st57: if p++; p == pe { - goto _test_eof27 + goto _test_eof57 } - st_case_27: -//line lexer.go:651 + st_case_57: +//line lexer.go:1368 if data[p] == 101 { - goto st9 + goto st27 } - goto tr42 - st9: + goto tr68 + st27: if p++; p == pe { - goto _test_eof9 + goto _test_eof27 } - st_case_9: + st_case_27: if data[p] == 110 { - goto st10 + goto st28 } - goto tr14 - st10: + goto tr39 + st28: if p++; p == pe { - goto _test_eof10 + goto _test_eof28 } - st_case_10: + st_case_28: if data[p] == 101 { - goto st11 + goto st29 } - goto tr14 - st11: + goto tr39 + st29: if p++; p == pe { - goto _test_eof11 + goto _test_eof29 } - st_case_11: + st_case_29: if data[p] == 114 { - goto st12 + goto st30 } - goto tr14 - st12: + goto tr39 + st30: if p++; p == pe { - goto _test_eof12 + goto _test_eof30 } - st_case_12: + st_case_30: if data[p] == 97 { - goto st13 + goto st31 } - goto tr14 - st13: + goto tr39 + st31: if p++; p == pe { - goto _test_eof13 + goto _test_eof31 } - st_case_13: + st_case_31: if data[p] == 108 { - goto tr19 + goto tr44 } - goto tr14 - tr36: + goto tr39 + tr62: //line NONE:1 te = p + 1 //line lexer.rl:91 - act = 18 - goto st28 - st28: + act = 19 + goto st58 + st58: if p++; p == pe { - goto _test_eof28 + goto _test_eof58 } - st_case_28: -//line lexer.go:713 + st_case_58: +//line lexer.go:1430 switch data[p] { case 104: - goto st15 + goto st33 case 109: - goto st15 + goto st33 case 115: - goto st15 + goto st33 } - goto st14 - st14: + goto st32 + st32: if p++; p == pe { - goto _test_eof14 + goto _test_eof32 } - st_case_14: + st_case_32: if data[p] == 93 { - goto tr21 + goto tr46 } - goto st14 - tr21: + goto st32 + tr46: //line NONE:1 te = p + 1 //line lexer.rl:88 - act = 16 - goto st29 - tr22: + act = 17 + goto st59 + tr47: //line NONE:1 te = p + 1 //line lexer.rl:86 - act = 14 - goto st29 - st29: + act = 15 + goto st59 + st59: if p++; p == pe { - goto _test_eof29 + goto _test_eof59 } - st_case_29: -//line lexer.go:751 + st_case_59: +//line lexer.go:1468 if data[p] == 93 { - goto tr21 + goto tr46 } - goto st14 - st15: + goto st32 + st33: if p++; p == pe { - goto _test_eof15 + goto _test_eof33 } - st_case_15: + st_case_33: if data[p] == 93 { - goto tr22 + goto tr47 } - goto st14 - st30: + goto st32 + st60: if p++; p == pe { - goto _test_eof30 + goto _test_eof60 } - st_case_30: - goto tr55 - tr39: + st_case_60: + goto tr89 + tr65: //line NONE:1 te = p + 1 //line lexer.rl:84 - act = 12 - goto st31 - st31: + act = 13 + goto st61 + st61: if p++; p == pe { - goto _test_eof31 + goto _test_eof61 } - st_case_31: -//line lexer.go:783 + st_case_61: +//line lexer.go:1500 switch data[p] { case 47: - goto tr6 + goto tr27 case 58: - goto tr9 + goto tr34 case 65: - goto st3 + goto st21 case 100: - goto tr6 + goto tr27 case 104: - goto tr9 + goto tr34 case 109: - goto tr39 + goto tr65 case 115: - goto tr40 + goto tr66 case 121: - goto st2 + goto st17 } - goto tr46 - st32: + goto tr78 + st62: if p++; p == pe { - goto _test_eof32 + goto _test_eof62 } - st_case_32: + st_case_62: if data[p] == 121 { - goto tr6 + goto tr27 } - goto tr42 + goto tr68 st_out: - _test_eof16: - cs = 16 + _test_eof34: + cs = 34 goto _test_eof - _test_eof17: - cs = 17 + _test_eof35: + cs = 35 goto _test_eof _test_eof0: cs = 0 goto _test_eof - _test_eof18: - cs = 18 + _test_eof36: + cs = 36 goto _test_eof - _test_eof19: - cs = 19 + _test_eof37: + cs = 37 goto _test_eof _test_eof1: cs = 1 goto _test_eof - _test_eof20: - cs = 20 - goto _test_eof _test_eof2: cs = 2 goto _test_eof - _test_eof21: - cs = 21 + _test_eof38: + cs = 38 goto _test_eof _test_eof3: cs = 3 @@ -891,6 +1622,9 @@ func (l *Lexer) Lex(r io.Reader) { _test_eof4: cs = 4 goto _test_eof + _test_eof39: + cs = 39 + goto _test_eof _test_eof5: cs = 5 goto _test_eof @@ -900,12 +1634,84 @@ func (l *Lexer) Lex(r io.Reader) { _test_eof7: cs = 7 goto _test_eof - _test_eof22: - cs = 22 - goto _test_eof _test_eof8: cs = 8 goto _test_eof + _test_eof40: + cs = 40 + goto _test_eof + _test_eof9: + cs = 9 + goto _test_eof + _test_eof41: + cs = 41 + goto _test_eof + _test_eof10: + cs = 10 + goto _test_eof + _test_eof42: + cs = 42 + goto _test_eof + _test_eof11: + cs = 11 + goto _test_eof + _test_eof43: + cs = 43 + goto _test_eof + _test_eof44: + cs = 44 + goto _test_eof + _test_eof45: + cs = 45 + goto _test_eof + _test_eof12: + cs = 12 + goto _test_eof + _test_eof46: + cs = 46 + goto _test_eof + _test_eof13: + cs = 13 + goto _test_eof + _test_eof14: + cs = 14 + goto _test_eof + _test_eof15: + cs = 15 + goto _test_eof + _test_eof16: + cs = 16 + goto _test_eof + _test_eof47: + cs = 47 + goto _test_eof + _test_eof17: + cs = 17 + goto _test_eof + _test_eof48: + cs = 48 + goto _test_eof + _test_eof18: + cs = 18 + goto _test_eof + _test_eof19: + cs = 19 + goto _test_eof + _test_eof20: + cs = 20 + goto _test_eof + _test_eof49: + cs = 49 + goto _test_eof + _test_eof50: + cs = 50 + goto _test_eof + _test_eof21: + cs = 21 + goto _test_eof + _test_eof22: + cs = 22 + goto _test_eof _test_eof23: cs = 23 goto _test_eof @@ -915,118 +1721,196 @@ func (l *Lexer) Lex(r io.Reader) { _test_eof25: cs = 25 goto _test_eof + _test_eof51: + cs = 51 + goto _test_eof _test_eof26: cs = 26 goto _test_eof - _test_eof27: - cs = 27 + _test_eof52: + cs = 52 goto _test_eof - _test_eof9: - cs = 9 + _test_eof53: + cs = 53 goto _test_eof - _test_eof10: - cs = 10 + _test_eof54: + cs = 54 goto _test_eof - _test_eof11: - cs = 11 + _test_eof55: + cs = 55 goto _test_eof - _test_eof12: - cs = 12 + _test_eof56: + cs = 56 goto _test_eof - _test_eof13: - cs = 13 + _test_eof57: + cs = 57 + goto _test_eof + _test_eof27: + cs = 27 goto _test_eof _test_eof28: cs = 28 goto _test_eof - _test_eof14: - cs = 14 - goto _test_eof _test_eof29: cs = 29 goto _test_eof - _test_eof15: - cs = 15 - goto _test_eof _test_eof30: cs = 30 goto _test_eof _test_eof31: cs = 31 goto _test_eof + _test_eof58: + cs = 58 + goto _test_eof _test_eof32: cs = 32 goto _test_eof + _test_eof59: + cs = 59 + goto _test_eof + _test_eof33: + cs = 33 + goto _test_eof + _test_eof60: + cs = 60 + goto _test_eof + _test_eof61: + cs = 61 + goto _test_eof + _test_eof62: + cs = 62 + goto _test_eof _test_eof: { } if p == eof { switch cs { - case 17: - goto tr42 + case 35: + goto tr68 case 0: goto tr0 - case 18: - goto tr43 - case 19: - goto tr44 + case 36: + goto tr69 + case 37: + goto tr70 case 1: - goto tr3 - case 20: - goto tr46 + goto tr0 case 2: - goto tr5 - case 21: - goto tr48 - case 3: goto tr0 + case 38: + goto tr72 + case 3: + goto tr9 case 4: - goto tr0 + goto tr9 + case 39: + goto tr72 case 5: - goto tr0 + goto tr9 case 6: - goto tr0 + goto tr9 case 7: - goto tr0 - case 22: - goto tr48 + goto tr9 case 8: - goto tr12 - case 23: - goto tr48 - case 24: - goto tr48 - case 25: - goto tr42 - case 26: - goto tr42 - case 27: - goto tr42 + goto tr0 + case 40: + goto tr72 case 9: - goto tr14 + goto tr9 + case 41: + goto tr72 case 10: - goto tr14 + goto tr0 + case 42: + goto tr72 case 11: - goto tr14 + goto tr9 + case 43: + goto tr72 + case 44: + goto tr72 + case 45: + goto tr72 case 12: - goto tr14 + goto tr19 + case 46: + goto tr77 case 13: - goto tr14 - case 28: - goto tr42 + goto tr21 case 14: goto tr0 - case 29: - goto tr0 case 15: - goto tr14 + goto tr0 + case 16: + goto tr21 + case 47: + goto tr78 + case 17: + goto tr26 + case 48: + goto tr80 + case 18: + goto tr28 + case 19: + goto tr28 + case 20: + goto tr0 + case 49: + goto tr68 + case 50: + goto tr81 + case 21: + goto tr0 + case 22: + goto tr0 + case 23: + goto tr0 + case 24: + goto tr0 + case 25: + goto tr0 + case 51: + goto tr81 + case 26: + goto tr37 + case 52: + goto tr81 + case 53: + goto tr81 + case 54: + goto tr85 + case 55: + goto tr68 + case 56: + goto tr68 + case 57: + goto tr68 + case 27: + goto tr39 + case 28: + goto tr39 + case 29: + goto tr39 case 30: - goto tr42 + goto tr39 case 31: - goto tr46 + goto tr39 + case 58: + goto tr68 case 32: - goto tr42 + goto tr0 + case 59: + goto tr0 + case 33: + goto tr39 + case 60: + goto tr68 + case 61: + goto tr78 + case 62: + goto tr68 } } diff --git a/spreadsheet/format/lexer.rl b/spreadsheet/format/lexer.rl index 38d1b60086..f5e769f0f7 100644 --- a/spreadsheet/format/lexer.rl +++ b/spreadsheet/format/lexer.rl @@ -68,28 +68,28 @@ import ( NFTime = (NFTimeToken | ':')+; cond = '[' any+ ']'; main := |* - '#,#' => { l.fmt.AddPlaceholder(FmtTypeDigitOptThousands,nil) }; - '0' => { l.fmt.AddPlaceholder(FmtTypeDigit,nil) }; - '#' => { l.fmt.AddPlaceholder(FmtTypeDigitOpt,nil) }; + '#,#' => { l.fmt.AddToken(FmtTypeDigitOptThousands,nil) }; + '0' => { l.fmt.AddToken(FmtTypeDigit,nil) }; + '#' => { l.fmt.AddToken(FmtTypeDigitOpt,nil) }; '?' => { }; # ignore for now - '.' => { l.fmt.AddPlaceholder(FmtTypeDecimal,nil) }; - ',' => { l.fmt.AddPlaceholder(FmtTypeComma,nil) }; - '%' => { l.fmt.AddPlaceholder(FmtTypePercent,nil) }; - '$' => { l.fmt.AddPlaceholder(FmtTypeDollar,nil) }; - '_' => { l.fmt.AddPlaceholder(FmtTypeUnderscore,nil) }; + '.' => { l.fmt.AddToken(FmtTypeDecimal,nil) }; + ',' => { l.fmt.AddToken(FmtTypeComma,nil) }; + '%' => { l.fmt.AddToken(FmtTypePercent,nil) }; + '$' => { l.fmt.AddToken(FmtTypeDollar,nil) }; + '_' => { l.fmt.AddToken(FmtTypeUnderscore,nil) }; ';' => { l.nextFmt() }; NFGeneral => { l.fmt.isGeneral = true }; - #NFFraction => {fmt.Println("FRACTION",string(data[ts:te]))}; + NFFraction => { l.fmt.AddToken(FmtTypeFraction,data[ts:te]) }; # we have to keep date/time separate as 'mm' is both minutes and month - NFDate => { l.fmt.AddPlaceholder(FmtTypeDate,data[ts:te]) }; - NFTime => { l.fmt.AddPlaceholder(FmtTypeTime,data[ts:te]) }; - NFAbsTimeToken => { l.fmt.AddPlaceholder(FmtTypeTime,data[ts:te]) }; + NFDate => { l.fmt.AddToken(FmtTypeDate,data[ts:te]) }; + NFTime => { l.fmt.AddToken(FmtTypeTime,data[ts:te]) }; + NFAbsTimeToken => { l.fmt.AddToken(FmtTypeTime,data[ts:te]) }; NFPartExponential => { l.fmt.IsExponential = true }; cond => {}; # ignoring # escaped - '\\' any => { l.fmt.AddPlaceholder(FmtTypeLiteral,data[ts+1:te]) }; - any => { l.fmt.AddPlaceholder(FmtTypeLiteral,data[ts:te]) }; - dquote ( not_dquote | dquote dquote)* dquote => { l.fmt.AddPlaceholder(FmtTypeLiteral,data[ts+1:te-1])}; + '\\' any => { l.fmt.AddToken(FmtTypeLiteral,data[ts+1:te]) }; + any => { l.fmt.AddToken(FmtTypeLiteral,data[ts:te]) }; + dquote ( not_dquote | dquote dquote)* dquote => { l.fmt.AddToken(FmtTypeLiteral,data[ts+1:te-1])}; *|;