json: Basic parsing of number values
This commit is contained in:
parent
4100bdfd2f
commit
b073937523
@ -3,6 +3,7 @@ package json
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/apparentlymart/go-zcl/zcl"
|
||||
)
|
||||
@ -207,7 +208,41 @@ func parseArray(p *peeker) (node, zcl.Diagnostics) {
|
||||
}
|
||||
|
||||
func parseNumber(p *peeker) (node, zcl.Diagnostics) {
|
||||
return nil, nil
|
||||
tok := p.Read()
|
||||
|
||||
// Use encoding/json to validate the number syntax.
|
||||
// TODO: Do this more directly to produce better diagnostics.
|
||||
var num json.Number
|
||||
err := json.Unmarshal(tok.Bytes, &num)
|
||||
if err != nil {
|
||||
return nil, zcl.Diagnostics{
|
||||
{
|
||||
Severity: zcl.DiagError,
|
||||
Summary: "Invalid JSON number",
|
||||
Detail: fmt.Sprintf("There is a syntax error in the given JSON number."),
|
||||
Subject: &tok.Range,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
f, _, err := (&big.Float{}).Parse(string(num), 10)
|
||||
if err != nil {
|
||||
// Should never happen if above passed, since JSON numbers are a subset
|
||||
// of what big.Float can parse...
|
||||
return nil, zcl.Diagnostics{
|
||||
{
|
||||
Severity: zcl.DiagError,
|
||||
Summary: "Invalid JSON number",
|
||||
Detail: fmt.Sprintf("There is a syntax error in the given JSON number."),
|
||||
Subject: &tok.Range,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return &numberVal{
|
||||
Value: f,
|
||||
SrcRange: tok.Range,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseString(p *peeker) (node, zcl.Diagnostics) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@ -111,6 +112,82 @@ func TestParse(t *testing.T) {
|
||||
nil,
|
||||
1,
|
||||
},
|
||||
{
|
||||
`1`,
|
||||
&numberVal{
|
||||
Value: mustBigFloat("1"),
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 1, Column: 1, Byte: 0},
|
||||
End: zcl.Pos{Line: 1, Column: 2, Byte: 1},
|
||||
},
|
||||
},
|
||||
0,
|
||||
},
|
||||
{
|
||||
`1.2`,
|
||||
&numberVal{
|
||||
Value: mustBigFloat("1.2"),
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 1, Column: 1, Byte: 0},
|
||||
End: zcl.Pos{Line: 1, Column: 4, Byte: 3},
|
||||
},
|
||||
},
|
||||
0,
|
||||
},
|
||||
{
|
||||
`-1`,
|
||||
&numberVal{
|
||||
Value: mustBigFloat("-1"),
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 1, Column: 1, Byte: 0},
|
||||
End: zcl.Pos{Line: 1, Column: 3, Byte: 2},
|
||||
},
|
||||
},
|
||||
0,
|
||||
},
|
||||
{
|
||||
`1.2e5`,
|
||||
&numberVal{
|
||||
Value: mustBigFloat("120000"),
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 1, Column: 1, Byte: 0},
|
||||
End: zcl.Pos{Line: 1, Column: 6, Byte: 5},
|
||||
},
|
||||
},
|
||||
0,
|
||||
},
|
||||
{
|
||||
`1.2e+5`,
|
||||
&numberVal{
|
||||
Value: mustBigFloat("120000"),
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 1, Column: 1, Byte: 0},
|
||||
End: zcl.Pos{Line: 1, Column: 7, Byte: 6},
|
||||
},
|
||||
},
|
||||
0,
|
||||
},
|
||||
{
|
||||
`1.2e-5`,
|
||||
&numberVal{
|
||||
Value: mustBigFloat("1.2e-5"),
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 1, Column: 1, Byte: 0},
|
||||
End: zcl.Pos{Line: 1, Column: 7, Byte: 6},
|
||||
},
|
||||
},
|
||||
0,
|
||||
},
|
||||
{
|
||||
`.1`,
|
||||
nil,
|
||||
1,
|
||||
},
|
||||
{
|
||||
`+2`,
|
||||
nil,
|
||||
1,
|
||||
},
|
||||
|
||||
// Objects
|
||||
{
|
||||
@ -259,3 +336,11 @@ func TestParse(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustBigFloat(s string) *big.Float {
|
||||
f, _, err := (&big.Float{}).Parse(s, 10)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user