Skip to content

Commit 778c285

Browse files
JelteFpelletier
authored andcommitted
Add support for special float values (inf and nan) (#210)
1 parent a1e8a8d commit 778c285

File tree

6 files changed

+79
-2
lines changed

6 files changed

+79
-2
lines changed

lexer.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,14 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn {
204204
return l.lexFalse
205205
}
206206

207+
if l.follow("inf") {
208+
return l.lexInf
209+
}
210+
211+
if l.follow("nan") {
212+
return l.lexNan
213+
}
214+
207215
if isSpace(next) {
208216
l.skip()
209217
continue
@@ -265,6 +273,18 @@ func (l *tomlLexer) lexFalse() tomlLexStateFn {
265273
return l.lexRvalue
266274
}
267275

276+
func (l *tomlLexer) lexInf() tomlLexStateFn {
277+
l.fastForward(3)
278+
l.emit(tokenInf)
279+
return l.lexRvalue
280+
}
281+
282+
func (l *tomlLexer) lexNan() tomlLexStateFn {
283+
l.fastForward(3)
284+
l.emit(tokenNan)
285+
return l.lexRvalue
286+
}
287+
268288
func (l *tomlLexer) lexEqual() tomlLexStateFn {
269289
l.next()
270290
l.emit(tokenEqual)
@@ -651,7 +671,14 @@ func (l *tomlLexer) lexNumber() tomlLexStateFn {
651671

652672
if r == '+' || r == '-' {
653673
l.next()
674+
if l.follow("inf") {
675+
return l.lexInf
676+
}
677+
if l.follow("nan") {
678+
return l.lexNan
679+
}
654680
}
681+
655682
pointSeen := false
656683
expSeen := false
657684
digitSeen := false

parser.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package toml
55
import (
66
"errors"
77
"fmt"
8+
"math"
89
"reflect"
910
"regexp"
1011
"strconv"
@@ -243,6 +244,13 @@ func (p *tomlParser) parseRvalue() interface{} {
243244
return true
244245
case tokenFalse:
245246
return false
247+
case tokenInf:
248+
if tok.val[0] == '-' {
249+
return math.Inf(-1)
250+
}
251+
return math.Inf(1)
252+
case tokenNan:
253+
return math.NaN()
246254
case tokenInteger:
247255
cleanedVal := cleanupNumberToken(tok.val)
248256
var err error

parser_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package toml
22

33
import (
44
"fmt"
5+
"math"
56
"reflect"
67
"testing"
78
"time"
@@ -93,6 +94,25 @@ func TestSimpleNumbers(t *testing.T) {
9394
})
9495
}
9596

97+
func TestSpecialFloats(t *testing.T) {
98+
tree, err := Load(`
99+
normalinf = inf
100+
plusinf = +inf
101+
minusinf = -inf
102+
normalnan = nan
103+
plusnan = +nan
104+
minusnan = -nan
105+
`)
106+
assertTree(t, tree, err, map[string]interface{}{
107+
"normalinf": math.Inf(1),
108+
"plusinf": math.Inf(1),
109+
"minusinf": math.Inf(-1),
110+
"normalnan": math.NaN(),
111+
"plusnan": math.NaN(),
112+
"minusnan": math.NaN(),
113+
})
114+
}
115+
96116
func TestHexIntegers(t *testing.T) {
97117
tree, err := Load(`a = 0xDEADBEEF`)
98118
assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})

token.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const (
2323
tokenTrue
2424
tokenFalse
2525
tokenFloat
26+
tokenInf
27+
tokenNan
2628
tokenEqual
2729
tokenLeftBracket
2830
tokenRightBracket
@@ -55,6 +57,8 @@ var tokenTypeNames = []string{
5557
"True",
5658
"False",
5759
"Float",
60+
"Inf",
61+
"NaN",
5862
"=",
5963
"[",
6064
"]",

tomltree_write.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
5454
// Ensure a round float does contain a decimal point. Otherwise feeding
5555
// the output back to the parser would convert to an integer.
5656
if math.Trunc(value) == value {
57-
return strconv.FormatFloat(value, 'f', 1, 32), nil
57+
return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil
5858
}
59-
return strconv.FormatFloat(value, 'f', -1, 32), nil
59+
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
6060
case string:
6161
return "\"" + encodeTomlString(value) + "\"", nil
6262
case []byte:

tomltree_write_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,24 @@ func TestTreeWriteToFloat(t *testing.T) {
309309
}
310310
}
311311

312+
func TestTreeWriteToSpecialFloat(t *testing.T) {
313+
expected := `a = +inf
314+
b = -inf
315+
c = nan`
316+
317+
tree, err := Load(expected)
318+
if err != nil {
319+
t.Fatal(err)
320+
}
321+
str, err := tree.ToTomlString()
322+
if err != nil {
323+
t.Fatal(err)
324+
}
325+
if strings.TrimSpace(str) != strings.TrimSpace(expected) {
326+
t.Fatalf("Expected:\n%s\nGot:\n%s", expected, str)
327+
}
328+
}
329+
312330
func BenchmarkTreeToTomlString(b *testing.B) {
313331
toml, err := Load(sampleHard)
314332
if err != nil {

0 commit comments

Comments
 (0)