Support decoding floats, scientific notation for JSON [GH-5]
This commit is contained in:
parent
b699557f16
commit
e868ca02fd
18
decoder.go
18
decoder.go
@ -48,6 +48,8 @@ func (d *decoder) decode(name string, o *hcl.Object, result reflect.Value) error
|
||||
switch k.Kind() {
|
||||
case reflect.Bool:
|
||||
return d.decodeBool(name, o, result)
|
||||
case reflect.Float64:
|
||||
return d.decodeFloat(name, o, result)
|
||||
case reflect.Int:
|
||||
return d.decodeInt(name, o, result)
|
||||
case reflect.Interface:
|
||||
@ -65,7 +67,7 @@ func (d *decoder) decode(name string, o *hcl.Object, result reflect.Value) error
|
||||
return d.decodeStruct(name, o, result)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
"%s: unknown kind to decode into: %s", name, result.Kind())
|
||||
"%s: unknown kind to decode into: %s", name, k.Kind())
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -82,6 +84,17 @@ func (d *decoder) decodeBool(name string, o *hcl.Object, result reflect.Value) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) decodeFloat(name string, o *hcl.Object, result reflect.Value) error {
|
||||
switch o.Type {
|
||||
case hcl.ValueTypeFloat:
|
||||
result.Set(reflect.ValueOf(o.Value.(float64)))
|
||||
default:
|
||||
return fmt.Errorf("%s: unknown type %s", name, o.Type)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) decodeInt(name string, o *hcl.Object, result reflect.Value) error {
|
||||
switch o.Type {
|
||||
case hcl.ValueTypeInt:
|
||||
@ -142,6 +155,9 @@ func (d *decoder) decodeInterface(name string, o *hcl.Object, result reflect.Val
|
||||
case hcl.ValueTypeBool:
|
||||
var result bool
|
||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||
case hcl.ValueTypeFloat:
|
||||
var result float64
|
||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||
case hcl.ValueTypeInt:
|
||||
var result int
|
||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||
|
@ -33,6 +33,15 @@ func TestDecode_interface(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"scientific.json",
|
||||
false,
|
||||
map[string]interface{}{
|
||||
"a": 1e-10,
|
||||
"b": 1e+10,
|
||||
"c": 1e10,
|
||||
},
|
||||
},
|
||||
{
|
||||
"terraform_heroku.hcl",
|
||||
false,
|
||||
|
12
json/lex.go
12
json/lex.go
@ -43,6 +43,18 @@ func (x *jsonLex) Lex(yylval *jsonSymType) int {
|
||||
}
|
||||
|
||||
switch c {
|
||||
case 'e':
|
||||
fallthrough
|
||||
case 'E':
|
||||
switch x.next() {
|
||||
case '+':
|
||||
return EPLUS
|
||||
case '-':
|
||||
return EMINUS
|
||||
default:
|
||||
x.backup()
|
||||
return EPLUS
|
||||
}
|
||||
case '.':
|
||||
return PERIOD
|
||||
case '-':
|
||||
|
27
json/parse.y
27
json/parse.y
@ -22,12 +22,12 @@ import (
|
||||
%type <num> int
|
||||
%type <obj> number object pair value
|
||||
%type <objlist> array elements members
|
||||
%type <str> frac
|
||||
%type <str> exp frac
|
||||
|
||||
%token <num> NUMBER
|
||||
%token <str> COLON COMMA IDENTIFIER EQUAL NEWLINE STRING
|
||||
%token <str> LEFTBRACE RIGHTBRACE LEFTBRACKET RIGHTBRACKET
|
||||
%token <str> TRUE FALSE NULL MINUS PERIOD
|
||||
%token <str> TRUE FALSE NULL MINUS PERIOD EPLUS EMINUS
|
||||
|
||||
%%
|
||||
|
||||
@ -148,6 +148,19 @@ number:
|
||||
panic(err)
|
||||
}
|
||||
|
||||
$$ = &hcl.Object{
|
||||
Type: hcl.ValueTypeFloat,
|
||||
Value: f,
|
||||
}
|
||||
}
|
||||
| int exp
|
||||
{
|
||||
fs := fmt.Sprintf("%d%s", $1, $2)
|
||||
f, err := strconv.ParseFloat(fs, 64)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
$$ = &hcl.Object{
|
||||
Type: hcl.ValueTypeFloat,
|
||||
Value: f,
|
||||
@ -164,6 +177,16 @@ int:
|
||||
$$ = $1
|
||||
}
|
||||
|
||||
exp:
|
||||
EPLUS NUMBER
|
||||
{
|
||||
$$ = "e" + strconv.FormatInt(int64($2), 10)
|
||||
}
|
||||
| EMINUS NUMBER
|
||||
{
|
||||
$$ = "e-" + strconv.FormatInt(int64($2), 10)
|
||||
}
|
||||
|
||||
frac:
|
||||
PERIOD NUMBER
|
||||
{
|
||||
|
82
json/y.go
82
json/y.go
@ -36,6 +36,8 @@ const FALSE = 57358
|
||||
const NULL = 57359
|
||||
const MINUS = 57360
|
||||
const PERIOD = 57361
|
||||
const EPLUS = 57362
|
||||
const EMINUS = 57363
|
||||
|
||||
var jsonToknames = []string{
|
||||
"NUMBER",
|
||||
@ -54,6 +56,8 @@ var jsonToknames = []string{
|
||||
"NULL",
|
||||
"MINUS",
|
||||
"PERIOD",
|
||||
"EPLUS",
|
||||
"EMINUS",
|
||||
}
|
||||
var jsonStatenames = []string{}
|
||||
|
||||
@ -61,7 +65,7 @@ const jsonEofCode = 1
|
||||
const jsonErrCode = 2
|
||||
const jsonMaxDepth = 200
|
||||
|
||||
//line parse.y:173
|
||||
//line parse.y:196
|
||||
|
||||
//line yacctab:1
|
||||
var jsonExca = []int{
|
||||
@ -70,59 +74,59 @@ var jsonExca = []int{
|
||||
-2, 0,
|
||||
}
|
||||
|
||||
const jsonNprod = 23
|
||||
const jsonNprod = 26
|
||||
const jsonPrivate = 57344
|
||||
|
||||
var jsonTokenNames []string
|
||||
var jsonStates []string
|
||||
|
||||
const jsonLast = 45
|
||||
const jsonLast = 50
|
||||
|
||||
var jsonAct = []int{
|
||||
|
||||
12, 23, 20, 25, 23, 3, 7, 13, 3, 10,
|
||||
21, 26, 17, 18, 19, 22, 30, 23, 22, 7,
|
||||
1, 5, 28, 13, 3, 29, 21, 32, 17, 18,
|
||||
19, 22, 9, 33, 6, 31, 15, 2, 8, 24,
|
||||
4, 27, 16, 14, 11,
|
||||
12, 23, 26, 27, 28, 23, 3, 13, 3, 20,
|
||||
21, 29, 17, 18, 19, 22, 7, 23, 5, 22,
|
||||
7, 9, 31, 13, 3, 37, 21, 8, 17, 18,
|
||||
19, 22, 32, 36, 6, 10, 35, 34, 38, 33,
|
||||
15, 2, 1, 24, 11, 25, 4, 30, 16, 14,
|
||||
}
|
||||
var jsonPact = []int{
|
||||
|
||||
-6, -1000, -1000, 9, 26, -1000, -1000, 4, -1000, -4,
|
||||
-5, -1000, -1000, 6, 15, -1000, -1000, 30, -1000, 10,
|
||||
13, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
|
||||
-16, -3, 0, -1000, -1000, 12, -1000, 21, -1000, -1000,
|
||||
-1000, -1000, 13, -1000,
|
||||
-17, -3, 1, -1000, -1000, -1000, 35, 33, 32, -1000,
|
||||
19, -1000, -1000, -1000, -1000, -1000, -1000, 13, -1000,
|
||||
}
|
||||
var jsonPgo = []int{
|
||||
|
||||
0, 2, 43, 36, 34, 0, 42, 41, 40, 39,
|
||||
20,
|
||||
0, 9, 49, 40, 34, 0, 48, 47, 46, 45,
|
||||
43, 42,
|
||||
}
|
||||
var jsonR1 = []int{
|
||||
|
||||
0, 10, 3, 3, 8, 8, 4, 5, 5, 5,
|
||||
0, 11, 3, 3, 8, 8, 4, 5, 5, 5,
|
||||
5, 5, 5, 5, 6, 6, 7, 7, 2, 2,
|
||||
1, 1, 9,
|
||||
2, 1, 1, 9, 9, 10,
|
||||
}
|
||||
var jsonR2 = []int{
|
||||
|
||||
0, 1, 3, 2, 1, 3, 3, 1, 1, 1,
|
||||
1, 1, 1, 1, 2, 3, 1, 3, 1, 2,
|
||||
2, 1, 2,
|
||||
2, 2, 1, 2, 2, 2,
|
||||
}
|
||||
var jsonChk = []int{
|
||||
|
||||
-1000, -10, -3, 11, -8, 12, -4, 10, 12, 6,
|
||||
-1000, -11, -3, 11, -8, 12, -4, 10, 12, 6,
|
||||
5, -4, -5, 10, -2, -3, -6, 15, 16, 17,
|
||||
-1, 13, 18, 4, -9, 19, 14, -7, -5, -1,
|
||||
4, 14, 6, -5,
|
||||
-1, 13, 18, 4, -10, -9, 19, 20, 21, 14,
|
||||
-7, -5, -1, 4, 4, 4, 14, 6, -5,
|
||||
}
|
||||
var jsonDef = []int{
|
||||
|
||||
0, -2, 1, 0, 0, 3, 4, 0, 2, 0,
|
||||
0, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
18, 0, 0, 21, 19, 0, 14, 0, 16, 20,
|
||||
22, 15, 0, 17,
|
||||
18, 0, 0, 22, 19, 20, 0, 0, 0, 14,
|
||||
0, 16, 21, 25, 23, 24, 15, 0, 17,
|
||||
}
|
||||
var jsonTok1 = []int{
|
||||
|
||||
@ -131,7 +135,7 @@ var jsonTok1 = []int{
|
||||
var jsonTok2 = []int{
|
||||
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
}
|
||||
var jsonTok3 = []int{
|
||||
0,
|
||||
@ -489,17 +493,41 @@ jsondefault:
|
||||
}
|
||||
}
|
||||
case 20:
|
||||
//line parse.y:159
|
||||
//line parse.y:157
|
||||
{
|
||||
fs := fmt.Sprintf("%d%s", jsonS[jsonpt-1].num, jsonS[jsonpt-0].str)
|
||||
f, err := strconv.ParseFloat(fs, 64)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
jsonVAL.obj = &hcl.Object{
|
||||
Type: hcl.ValueTypeFloat,
|
||||
Value: f,
|
||||
}
|
||||
}
|
||||
case 21:
|
||||
//line parse.y:172
|
||||
{
|
||||
jsonVAL.num = jsonS[jsonpt-0].num * -1
|
||||
}
|
||||
case 21:
|
||||
//line parse.y:163
|
||||
case 22:
|
||||
//line parse.y:176
|
||||
{
|
||||
jsonVAL.num = jsonS[jsonpt-0].num
|
||||
}
|
||||
case 22:
|
||||
//line parse.y:169
|
||||
case 23:
|
||||
//line parse.y:182
|
||||
{
|
||||
jsonVAL.str = "e" + strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10)
|
||||
}
|
||||
case 24:
|
||||
//line parse.y:186
|
||||
{
|
||||
jsonVAL.str = "e-" + strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10)
|
||||
}
|
||||
case 25:
|
||||
//line parse.y:192
|
||||
{
|
||||
jsonVAL.str = strconv.FormatInt(int64(jsonS[jsonpt-0].num), 10)
|
||||
}
|
||||
|
3
test-fixtures/scientific.hcl
Normal file
3
test-fixtures/scientific.hcl
Normal file
@ -0,0 +1,3 @@
|
||||
a = 1e-10
|
||||
b = 1e+10
|
||||
c = 1e10
|
5
test-fixtures/scientific.json
Normal file
5
test-fixtures/scientific.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"a": 1e-10,
|
||||
"b": 1e+10,
|
||||
"c": 1e10
|
||||
}
|
Loading…
Reference in New Issue
Block a user