json: Basic parsing of number values
This commit is contained in:
parent
4100bdfd2f
commit
b073937523
@ -3,6 +3,7 @@ package json
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/apparentlymart/go-zcl/zcl"
|
"github.com/apparentlymart/go-zcl/zcl"
|
||||||
)
|
)
|
||||||
@ -207,7 +208,41 @@ func parseArray(p *peeker) (node, zcl.Diagnostics) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseNumber(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) {
|
func parseString(p *peeker) (node, zcl.Diagnostics) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -111,6 +112,82 @@ func TestParse(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
1,
|
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
|
// 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